events {
    worker_connections 1024;
}
pid /tmp/nginx.pid;
http {
    # Basic settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Logging
    access_log /dev/stdout;
    error_log /dev/stderr;

    # Docker internal DNS (for resolving k3s hostname)
    resolver 127.0.0.11 valid=10s ipv6=off;

    # Preserve an upstream proxy's X-Forwarded-Proto so the Gateway sees the real
    # client scheme when DeerFlow's nginx runs BEHIND another TLS-terminating
    # reverse proxy (e.g. Pangolin/Traefik, Cloudflare, Caddy). Without this the
    # Gateway treats HTTPS browser traffic as HTTP and rejects the login POST with
    # 403 "Cross-site auth request denied" (Origin scheme mismatch), and also drops
    # the Secure flag / max-age on session cookies. Falls back to $scheme when nginx
    # is itself the TLS edge (standalone `make dev` / Docker), so default
    # deployments are unchanged.
    map $http_x_forwarded_proto $forwarded_proto {
        default    $scheme;
        "~*^https" https;
    }

    # ── Main server (path-based routing) ─────────────────────────────────
    server {
        listen 2026 default_server;
        listen [::]:2026 default_server;
        server_name _;

        # Resolve Docker service names at request time to avoid stale upstream
        # IPs when containers restart and receive new addresses.
        set $gateway_upstream gateway:8001;
        set $frontend_upstream frontend:3000;

        # Default proxy settings for all locations (streaming/SSE support)
        proxy_buffering off;
        proxy_cache off;

        # Keep the unified nginx endpoint same-origin by default. When split
        # frontend/backend or port-forwarded deployments need browser CORS,
        # configure the Gateway allowlist with GATEWAY_CORS_ORIGINS so CORS and
        # CSRF origin checks stay aligned instead of approving every origin at
        # the proxy layer.

        # LangGraph-compatible API routes served by Gateway.
        # Rewrites /api/langgraph/* to /api/* before proxying to Gateway.
        location /api/langgraph/ {
            rewrite ^/api/langgraph/(.*) /api/$1 break;
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;

            # Headers
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;
            proxy_set_header Connection '';

            # SSE/Streaming support
            proxy_set_header X-Accel-Buffering no;

            # Timeouts for long-running requests
            proxy_connect_timeout 600s;
            proxy_send_timeout 600s;
            proxy_read_timeout 600s;

            # Chunked transfer encoding
            chunked_transfer_encoding on;
        }

        # Custom API: Models endpoint
        location /api/models {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Custom API: Memory endpoint
        location /api/memory {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Custom API: MCP configuration endpoint
        location /api/mcp {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Custom API: Skills configuration endpoint
        location /api/skills {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Custom API: Agents endpoint
        location /api/agents {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Custom API: Uploads endpoint
        location ~ ^/api/threads/[^/]+/uploads {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

            # Large file upload support
            client_max_body_size 100M;
            proxy_request_buffering off;

            # Disable response buffering to avoid permission errors
        }

        # Custom API: Other endpoints under /api/threads
        location ~ ^/api/threads {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # API Documentation: Swagger UI
        location /docs {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # API Documentation: ReDoc
        location /redoc {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # API Documentation: OpenAPI Schema
        location /openapi.json {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Health check endpoint (gateway)
        location /health {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # ── Provisioner API (sandbox management) ────────────────────────
        # Use a variable so nginx resolves provisioner at request time (not startup).
        # This allows nginx to start even when provisioner container is not running.
        location /api/sandboxes {
            set $provisioner_upstream provisioner:8002;
            proxy_pass http://$provisioner_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

        }

        # Catch-all for /api/ routes not covered above (e.g. /api/v1/auth/*).
        # More specific prefix and regex locations above still take precedence.
        location /api/ {
            proxy_pass http://$gateway_upstream;
            proxy_http_version 1.1;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;

            # Disable buffering to avoid permission errors when nginx
            # runs as a non-root user (e.g. local development).
        }

        # All other requests go to frontend
        location / {
            proxy_pass http://$frontend_upstream;
            proxy_http_version 1.1;

            # Headers
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $forwarded_proto;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_cache_bypass $http_upgrade;

            # Timeouts
            proxy_connect_timeout 600s;
            proxy_send_timeout 600s;
            proxy_read_timeout 600s;
        }
    }
}