version: '3.7'

services:
  # ==========================================
  # Frontend (Vite Dev Server)
  # ==========================================
  frontend:
    build: 
      context: ./frontend
    ports:
      - "5173:5173" # Vite default port
    depends_on:
      - backend
    # Hot Reload requires binding volume locally
    volumes:
      - ./frontend:/app
      - /app/node_modules # Avoid overwriting node_modules
    environment:
      # Browser needs to access backend directly for CORS requests in Dev mode
      - VITE_API_BASE_URL=http://localhost:8000/api/v1
    restart: always

  # ==========================================
  # Nginx (Frontend Production)
  # ==========================================
  nginx:
    build:
      context: ./frontend
      target: production-stage
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - backend
    volumes:
      - certs_data:/etc/nginx/certs
    restart: always

  # ==========================================
  # Backend (FastAPI)
  # ==========================================
  backend:
    build:
      context: ./backend
    ports:
      - "8000:8000"
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_SERVER=db
      - MYSQL_PORT=3306
      - MYSQL_USER=uap_user
      - MYSQL_PASSWORD=uap_pass
      - MYSQL_DB=uap_db
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - HYDRA_ADMIN_URL=http://hydra:4445
      # CORS: Add * to allow debugging from any origin if localhost fails
      # Also explictly allow 127.0.0.1 and localhost with port 5173
      - BACKEND_CORS_ORIGINS=["https://api.hnyunzhu.com"]
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
      hydra:
        condition: service_started
      db-migration:
        condition: service_completed_successfully
    volumes:
      - ./backend:/app # Hot Reload for Backend too
      - certs_data:/app/certs
      - ./backups:/app/backups # 数据库备份目录
    restart: always

  # ==========================================
  # Database (MySQL)
  # ==========================================
  db:
    image: mysql:8.0
    container_name: uap_mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: uap_db
      MYSQL_USER: uap_user
      MYSQL_PASSWORD: uap_pass
    ports:
      - "3308:3306"
    volumes:
      - db_data:/var/lib/mysql
      # - ./config/my.cnf:/etc/mysql/conf.d/my.cnf
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ==========================================
  # Database Version Migration (Flyway)
  # ==========================================
  db-migration:
    image: flyway/flyway:9-alpine
    container_name: uap_migration
    depends_on:
      db:
        condition: service_healthy
    command: -connectRetries=60 -baselineOnMigrate=true migrate
    environment:
      FLYWAY_URL: jdbc:mysql://db:3306/uap_db
      FLYWAY_USER: root
      FLYWAY_PASSWORD: root_password
    volumes:
      - ./sql:/flyway/sql

  # ==========================================
  # Database Auto Backup (Sidecar)
  # ==========================================
  db-backup:
    image: fradelg/mysql-cron-backup
    container_name: uap_backup
    restart: always
    depends_on:
      - db
    environment:
      - MYSQL_HOST=db
      - MYSQL_PORT=3306
      - MYSQL_USER=root
      - MYSQL_PASS=root_password
      - CRON_TIME=0 3 * * *
      - MAX_BACKUPS=7
      - GZIP_COMPRESSION=true
    volumes:
      - ./backups:/backup

  # ==========================================
  # Redis
  # ==========================================
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    restart: always
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ==========================================
  # Ory Hydra Services
  # ==========================================
  hydra-migrate:
    image: oryd/hydra:v2.2.0
    environment:
      - TZ=Asia/Shanghai
      - DSN=postgres://hydra:secret@postgresd:5432/hydra?sslmode=disable&max_conns=20&max_idle_conns=4
    command: migrate sql -e --yes
    depends_on:
      postgresd:
        condition: service_healthy
    restart: on-failure

  hydra:
    image: oryd/hydra:v2.2.0
    depends_on:
      hydra-migrate:
        condition: service_completed_successfully
    ports:
      - "4444:4444"
      - "4445:4445"
      - "5555:5555"
    command: serve all --dev
    environment:
      - TZ=Asia/Shanghai
      - DSN=postgres://hydra:secret@postgresd:5432/hydra?sslmode=disable&max_conns=20&max_idle_conns=4
      - URLS_SELF_ISSUER=https://api.hnyunzhu.com/hydra
      - URLS_CONSENT=https://api.hnyunzhu.com/consent
      - URLS_LOGIN=https://api.hnyunzhu.com/auto-login
      - URLS_LOGOUT=https://api.hnyunzhu.com/auto-logout
      - SECRETS_SYSTEM=youReallyNeedToChangeThis
      - OIDC_SUBJECT_IDENTIFIERS_SUPPORTED_TYPES=public,pairwise
      - OIDC_SUBJECT_IDENTIFIERS_PAIRWISE_SALT=youReallyNeedToChangeThis
      - SERVE_COOKIES_SAME_SITE_MODE=Lax
      - SERVE_COOKIES_SAME_SITE_LEGACY_WORKAROUND=true
      - SERVE_PUBLIC_CORS_ENABLED=true
      - SERVE_PUBLIC_CORS_ALLOWED_ORIGINS=*
      - SERVE_PUBLIC_CORS_ALLOWED_METHODS=POST,GET,PUT,DELETE,PATCH,OPTIONS
      - SERVE_PUBLIC_CORS_ALLOWED_HEADERS=Authorization,Content-Type
      - SERVE_ADMIN_CORS_ENABLED=true
      - SERVE_ADMIN_CORS_ALLOWED_ORIGINS=*

  postgresd:
    image: postgres:15
    environment:
      - TZ=Asia/Shanghai
      - POSTGRES_USER=hydra
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=hydra
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U hydra"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

volumes:
  db_data:
  postgres_data:
  certs_data:
