services:
  # ============================================
  # NEXUS APP SERVICES
  # ============================================

  # Vault Agent for nexus migrations (one-shot, runs before app)
  vault-agent-migrate:
    image: hashicorp/vault:1.18
    container_name: nexus-vault-agent-migrate
    network_mode: host
    user: "0:0"

    command: >
      sh -c "rm -f /vault/secrets/.env;
             vault agent -config=/vault/config/agent-config.hcl &
             while [ ! -f /vault/secrets/.env ]; do sleep 1; done;
             echo 'Secrets rendered, exiting'; exit 0"

    cap_add:
      - IPC_LOCK

    volumes:
      - ./vault/agent-config-migrate.hcl:/vault/config/agent-config.hcl:ro
      - ./vault/templates:/vault/templates:ro
      - ./secrets/migrate/role-id:/vault/role-id:ro
      - ./secrets/migrate/secret-id:/vault/secret-id:ro
      - ./run/migrate:/vault/secrets

    environment:
      - VAULT_ADDR=http://vault.example.local:8200

  # Nexus migration runner (one-shot, runs before app)
  migrate:
    build:
      context: .
      dockerfile: Dockerfile.migrate
    container_name: nexus-migrate
    network_mode: host

    depends_on:
      vault-agent-migrate:
        condition: service_completed_successfully

    volumes:
      - ./run/migrate:/vault/secrets:ro
      - ./migrations:/app/migrations:ro

    working_dir: /app

    command:
      - |
        set -e
        echo "Loading credentials from Vault..."
        set -a
        . /vault/secrets/.env
        set +a
        echo "Running migrations..."
        sqlx migrate run
        echo "Migrations complete!"

  # Vault Agent for nexus app runtime (long-running)
  vault-agent:
    image: hashicorp/vault:1.18
    container_name: nexus-vault-agent
    restart: unless-stopped
    network_mode: host
    pid: host  # Share PID namespace to signal nexus on credential refresh
    user: "0:0"

    command: ["vault", "agent", "-config=/vault/config/agent-config.hcl"]

    cap_add:
      - IPC_LOCK
      - KILL  # Required to send SIGHUP to nexus for credential refresh

    volumes:
      - ./vault/agent-config.hcl:/vault/config/agent-config.hcl:ro
      - ./vault/templates:/vault/templates:ro
      - ./secrets/app/role-id:/vault/role-id:ro
      - ./secrets/app/secret-id:/vault/secret-id:ro
      - ./run/app:/vault/secrets

    environment:
      - VAULT_ADDR=http://vault.example.local:8200

    healthcheck:
      test: ["CMD", "test", "-f", "/vault/secrets/.env"]
      interval: 5s
      timeout: 3s
      retries: 30
      start_period: 10s

  # Main nexus application
  nexus:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: nexus
    restart: unless-stopped
    network_mode: host
    pid: host  # Share PID namespace so vault-agent can signal us

    depends_on:
      migrate:
        condition: service_completed_successfully
      vault-agent:
        condition: service_healthy

    volumes:
      - ./run/app:/vault/secrets  # Not read-only - app writes nexus.pid

    environment:
      - RUST_LOG=nexus=info,tower_http=info

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5050/health/ready"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # PGBOUNCER SERVICE (for Kratos)
  # ============================================

  # PgBouncer with integrated Vault Agent
  # Proxies Kratos DB connections with dynamic Vault credentials
  pgbouncer:
    build:
      context: ./pgbouncer
      dockerfile: Dockerfile
    container_name: nexus-pgbouncer
    restart: unless-stopped
    network_mode: host

    cap_add:
      - IPC_LOCK

    volumes:
      - ./vault/agent-config-pgbouncer.hcl:/vault/config/agent-config.hcl:ro
      - ./vault/templates:/vault/templates:ro
      - ./secrets/kratos-app/role-id:/vault/role-id:ro
      - ./secrets/kratos-app/secret-id:/vault/secret-id:ro

    environment:
      - VAULT_ADDR=http://vault.example.local:8200

    healthcheck:
      test: ["CMD", "pg_isready", "-h", "127.0.0.1", "-p", "6432", "-U", "kratos"]
      interval: 5s
      timeout: 3s
      retries: 30
      start_period: 15s

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # KRATOS SERVICES
  # ============================================

  # Vault Agent for Kratos migrations (one-shot)
  vault-agent-kratos-migrate:
    image: hashicorp/vault:1.18
    container_name: nexus-vault-agent-kratos-migrate
    network_mode: host
    user: "0:0"

    command: >
      sh -c "rm -f /vault/secrets/.env;
             vault agent -config=/vault/config/agent-config.hcl &
             while [ ! -f /vault/secrets/.env ]; do sleep 1; done;
             echo 'Secrets rendered, exiting'; exit 0"

    cap_add:
      - IPC_LOCK

    volumes:
      - ./vault/agent-config-kratos-migrate.hcl:/vault/config/agent-config.hcl:ro
      - ./vault/templates:/vault/templates:ro
      - ./secrets/kratos-migrate/role-id:/vault/role-id:ro
      - ./secrets/kratos-migrate/secret-id:/vault/secret-id:ro
      - ./run/kratos-migrate:/vault/secrets

    environment:
      - VAULT_ADDR=http://vault.example.local:8200

  # Kratos migration runner (one-shot)
  kratos-migrate:
    image: oryd/kratos:v1.1.0
    container_name: nexus-kratos-migrate
    network_mode: host

    depends_on:
      vault-agent-kratos-migrate:
        condition: service_completed_successfully
      migrate:
        condition: service_completed_successfully  # Nexus migrations create kratos schema

    volumes:
      - ./kratos/config:/etc/kratos:ro
      - ./run/kratos-migrate:/vault/secrets:ro

    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        export $(grep -v '^#' /vault/secrets/.env | xargs)
        exec kratos migrate sql -e --yes

  # Vault Agent for Kratos runtime (long-running)
  vault-agent-kratos:
    image: hashicorp/vault:1.18
    container_name: nexus-vault-agent-kratos
    restart: unless-stopped
    network_mode: host
    user: "0:0"

    command: ["vault", "agent", "-config=/vault/config/agent-config.hcl"]

    cap_add:
      - IPC_LOCK

    volumes:
      - ./vault/agent-config-kratos.hcl:/vault/config/agent-config.hcl:ro
      - ./vault/templates:/vault/templates:ro
      - ./secrets/kratos-app/role-id:/vault/role-id:ro
      - ./secrets/kratos-app/secret-id:/vault/secret-id:ro
      - ./run/kratos:/vault/secrets

    environment:
      - VAULT_ADDR=http://vault.example.local:8200

    healthcheck:
      test: ["CMD", "test", "-f", "/vault/secrets/.env"]
      interval: 5s
      timeout: 3s
      retries: 30
      start_period: 10s

  # Kratos identity server (long-running)
  kratos:
    image: oryd/kratos:v1.1.0
    container_name: nexus-kratos
    restart: unless-stopped
    network_mode: host

    depends_on:
      kratos-migrate:
        condition: service_completed_successfully
      vault-agent-kratos:
        condition: service_healthy
      pgbouncer:
        condition: service_healthy

    volumes:
      - ./kratos/config:/etc/kratos:ro
      - ./run/kratos:/vault/secrets:ro

    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        export $(grep -v '^#' /vault/secrets/.env | xargs)
        exec kratos serve --config /etc/kratos/kratos.yml

    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:6050/health/alive"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # OATHKEEPER SERVICE
  # ============================================

  # Vault Agent for Oathkeeper (long-running)
  vault-agent-oathkeeper:
    image: hashicorp/vault:1.18
    container_name: nexus-vault-agent-oathkeeper
    restart: unless-stopped
    network_mode: host
    user: "0:0"

    command: ["vault", "agent", "-config=/vault/config/agent-config.hcl"]

    cap_add:
      - IPC_LOCK

    volumes:
      - ./vault/agent-config-oathkeeper.hcl:/vault/config/agent-config.hcl:ro
      - ./vault/templates:/vault/templates:ro
      - ./secrets/oathkeeper/role-id:/vault/role-id:ro
      - ./secrets/oathkeeper/secret-id:/vault/secret-id:ro
      - ./run/oathkeeper:/vault/secrets

    environment:
      - VAULT_ADDR=http://vault.example.local:8200

    healthcheck:
      test: ["CMD", "test", "-f", "/vault/secrets/.env"]
      interval: 5s
      timeout: 3s
      retries: 30
      start_period: 10s

  # Oathkeeper API gateway (stateless, long-running)
  oathkeeper:
    build:
      context: ./oathkeeper
      dockerfile: Dockerfile
    container_name: nexus-oathkeeper
    restart: unless-stopped
    network_mode: host

    depends_on:
      kratos:
        condition: service_healthy
      nexus:
        condition: service_healthy
      vault-agent-oathkeeper:
        condition: service_healthy

    volumes:
      - ./run/oathkeeper:/vault/secrets:ro

    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:7250/health/alive"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # AUTH FRONTEND SERVICE
  # ============================================

  # Auth frontend (account.example.com)
  auth-frontend:
    build:
      context: ./auth-frontend
      dockerfile: Dockerfile
    container_name: nexus-auth-frontend
    restart: unless-stopped
    network_mode: host

    environment:
      - KRATOS_SERVER_URL=http://localhost:6000
      - ORIGIN=https://account.example.com
      - ADMIN_USER_ID=00000000-0000-0000-0000-000000000000  # Replace with your admin user ID

    depends_on:
      kratos:
        condition: service_healthy
      oathkeeper:
        condition: service_healthy

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # MAIN FRONTEND SERVICE
  # ============================================

  # Main frontend (app.example.com)
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    container_name: nexus-frontend
    restart: unless-stopped
    network_mode: host

    environment:
      - NODE_ENV=production
      - ORIGIN=https://app.example.com

    depends_on:
      oathkeeper:
        condition: service_healthy

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
