events {
    worker_connections 1024;
}

http {
    # --- DNS resolver (Docker internal DNS) ---
    # Re-resolves hostnames on every request so nginx survives service restarts
    resolver 127.0.0.11 valid=5s ipv6=off;
    resolver_timeout 3s;

    # --- Timeouts ---
    proxy_connect_timeout 10s;
    proxy_send_timeout    60s;
    proxy_read_timeout    60s;

    # --- Request body ---
    client_max_body_size 75m;

    # --- Security headers ---
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header X-XSS-Protection "0" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

    # --- Hide server version ---
    server_tokens off;

    # --- TLS / SSL config (mkcert-issued local cert + local root CA) ---
    # Certs are mounted into the nginx container at /etc/nginx/certs by the
    # docker compose volume `../certs:/etc/nginx/certs:ro`. Run
    # `scripts/install-tls.sh` (Mac/Linux) or `install-tls.ps1` (Windows)
    # to (re)generate them. See docs/08-runtime-devops/tls-setup.md.
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers off;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 1d;

    # Trust the mkcert root CA when proxying to HTTPS upstreams so the
    # internal service-to-service hop is verified end-to-end. Without this,
    # nginx would log "SSL certificate verify error" on every request.
    proxy_ssl_trusted_certificate /etc/nginx/certs/rootCA.pem;
    proxy_ssl_verify              on;
    proxy_ssl_verify_depth        2;
    proxy_ssl_server_name         on;

    # ---- HTTP -> HTTPS redirect ----
    # Catches anyone bookmarked to http://claw.local:4000 and bounces them to
    # https://localhost. Listen on 80 (nginx container) which is published
    # to host port 4000 by the dev compose file.
    server {
        listen 80;
        # Match localhost, claw.local, *.claw.local, and any other Host header.
        # _ at the end is the catch-all default_server fallback.
        server_name localhost claw.local *.claw.local _;
        # 301 (permanent) so browsers stop hitting :4000 over plain HTTP.
        return 301 https://$host$request_uri;
    }

    # ---- Main TLS server block ----
    server {
        listen 443 ssl;
        http2 on;
        # Same hosts as the redirect block — leaf cert covers all of these.
        server_name localhost claw.local *.claw.local _;

        ssl_certificate     /etc/nginx/certs/claw.crt;
        ssl_certificate_key /etc/nginx/certs/claw.key;

        # --- Shared proxy headers ---
        proxy_set_header Host $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 $scheme;
        proxy_set_header Origin $http_origin;

        # --- Auth Service ---
        location /api/v1/auth {
            set $auth_backend https://auth-service:4001;
            proxy_pass $auth_backend;
        }

        location /api/v1/users {
            set $auth_backend https://auth-service:4001;
            proxy_pass $auth_backend;
        }

        # Admin RBAC: plans + roles CRUD (auth-service, ADMIN-gated controllers).
        location /api/v1/admin {
            set $auth_backend https://auth-service:4001;
            proxy_pass $auth_backend;
        }

        # --- Chat Service ---
        location /api/v1/threads {
            set $chat_backend https://chat-service:4002;
            rewrite ^/api/v1/threads/(.*)$ /api/v1/chat-threads/$1 break;
            proxy_pass $chat_backend;
        }

        location /api/v1/messages {
            set $chat_backend https://chat-service:4002;
            rewrite ^/api/v1/messages/(.*)$ /api/v1/chat-messages/$1 break;
            proxy_pass $chat_backend;
        }

        location /api/v1/chat-threads {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
        }

        location /api/v1/chat-messages/stream {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_read_timeout 86400;
            proxy_buffering off;
            proxy_cache off;
        }

        location /api/v1/chat-messages/parallel {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 180s;
        }

        location /api/v1/chat-messages/consensus {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 180s;
        }

        location /api/v1/chat-messages/escalation-chain {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 180s;
        }

        location /api/v1/chat-messages/decompose {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 30s;
        }

        location /api/v1/chat-messages/best-of-n {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 30s;
        }

        location /api/v1/chat-messages/verify {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 30s;
        }

        location /api/v1/chat-messages/pipeline {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 120s;
        }

        location /api/v1/chat-messages/cost-ensemble {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 120s;
        }

        location /api/v1/chat-messages/role-pack {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
            proxy_read_timeout 120s;
        }

        location /api/v1/chat-messages {
            set $chat_backend https://chat-service:4002;
            proxy_pass $chat_backend;
        }

        # --- Connector Service ---
        location /api/v1/connectors {
            set $connector_backend https://connector-service:4003;
            proxy_pass $connector_backend;
        }

        location /api/v1/models {
            set $connector_backend https://connector-service:4003;
            proxy_pass $connector_backend;
        }

        # --- Routing Service ---
        location /api/v1/routing/adaptive-insights {
            set $routing_backend https://routing-service:4004;
            proxy_pass $routing_backend;
            proxy_read_timeout 30s;
        }

        location /api/v1/routing {
            set $routing_backend https://routing-service:4004;
            proxy_pass $routing_backend;
        }

        # --- Memory Service ---
        location /api/v1/memory {
            set $memory_backend https://memory-service:4005;
            rewrite ^/api/v1/memory/(.*)$ /api/v1/memories/$1 break;
            proxy_pass $memory_backend;
        }

        location /api/v1/context {
            set $memory_backend https://memory-service:4005;
            rewrite ^/api/v1/context/(.*)$ /api/v1/context-packs/$1 break;
            proxy_pass $memory_backend;
        }

        location /api/v1/memories {
            set $memory_backend https://memory-service:4005;
            proxy_pass $memory_backend;
        }

        location /api/v1/context-packs {
            set $memory_backend https://memory-service:4005;
            proxy_pass $memory_backend;
        }

        # --- File Service ---
        location /api/v1/files {
            set $file_backend https://file-service:4006;
            proxy_pass $file_backend;
        }

        # --- Audit Service ---
        location /api/v1/audits {
            set $audit_backend https://audit-service:4007;
            proxy_pass $audit_backend;
        }

        location /api/v1/usage {
            set $audit_backend https://audit-service:4007;
            proxy_pass $audit_backend;
        }

        # --- Ollama Service: SSE pull-progress (must come before generic) ---
        location ~ ^/api/v1/ollama/pull-jobs/[^/]+/progress$ {
            set $ollama_sse_backend https://ollama-service:4008;
            proxy_pass $ollama_sse_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header X-Accel-Buffering "no";
            proxy_read_timeout 86400;
            proxy_buffering off;
            proxy_cache off;
        }

        # --- Ollama Service ---
        location /api/v1/ollama {
            set $ollama_backend https://ollama-service:4008;
            proxy_pass $ollama_backend;
        }

        # --- Image Service ---
        location /api/v1/images {
            set $image_backend https://image-service:4012;
            proxy_pass $image_backend;
        }

        # --- Image Service SSE ---
        location /api/v1/images/ {
            set $image_backend https://image-service:4012;
            proxy_pass $image_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_read_timeout 86400;
            proxy_buffering off;
            proxy_cache off;
        }

        # --- File Generation Service ---
        location /api/v1/file-generations {
            set $file_gen_backend https://file-generation-service:4013;
            proxy_pass $file_gen_backend;
        }

        # --- File Generation Service SSE ---
        location /api/v1/file-generations/ {
            set $file_gen_backend https://file-generation-service:4013;
            proxy_pass $file_gen_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_read_timeout 86400;
            proxy_buffering off;
            proxy_cache off;
        }

        # --- Workspace Service ---
        # AI action generation runs the LLM synchronously and routinely sits
        # at 60-120s (slow local Ollama models). Must be declared BEFORE the
        # generic /workspace block so nginx's longest-prefix match picks it.
        location /api/v1/workspace/ai-actions/run {
            set $workspace_backend https://workspace-service:4014;
            proxy_pass $workspace_backend;
            proxy_read_timeout 600s;
            proxy_send_timeout 600s;
        }

        location /api/v1/workspace {
            set $workspace_backend https://workspace-service:4014;
            proxy_pass $workspace_backend;
        }

        # --- Agent Service (SSE stream — must be declared before generic) ---
        location ~ ^/api/v1/agent/commands/[^/]+/stream$ {
            set $agent_stream_backend https://agent-service:4015;
            proxy_pass $agent_stream_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header X-Accel-Buffering "no";
            proxy_buffering off;
            proxy_cache off;
            proxy_read_timeout 86400s;
            proxy_send_timeout 86400s;
        }

        # --- Agent Service ---
        location /api/v1/agent {
            set $agent_backend https://agent-service:4015;
            proxy_pass $agent_backend;
        }

        # --- Research Service ---
        location /api/v1/research {
            set $research_backend https://research-service:4016;
            proxy_pass $research_backend;
        }

        # --- Client Logs Service ---
        location /api/v1/client-logs {
            set $client_logs_backend https://client-logs-service:4010;
            proxy_pass $client_logs_backend;
        }

        # --- Server Logs Service ---
        location /api/v1/server-logs {
            set $server_logs_backend https://server-logs-service:4011;
            proxy_pass $server_logs_backend;
        }

        # --- Llamacpp Service: SSE pull-progress (must come before generic) ---
        # Service controllers are NOT under /llamacpp/ (unlike ollama-service); strip the prefix.
        location ~ ^/api/v1/llamacpp/pull-jobs/[^/]+/progress$ {
            set $llamacpp_sse_backend https://llamacpp-service:4017;
            rewrite ^/api/v1/llamacpp(/.*)$ /api/v1$1 break;
            proxy_pass $llamacpp_sse_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header X-Accel-Buffering "no";
            proxy_buffering off;
            proxy_cache off;
            proxy_read_timeout 86400s;
            proxy_send_timeout 86400s;
        }

        # --- Llamacpp Service: OpenAI-compatible inference (SSE-capable) ---
        location /api/v1/llamacpp/v1/ {
            set $llamacpp_inference_backend https://llamacpp-service:4017;
            rewrite ^/api/v1/llamacpp(/.*)$ /api/v1$1 break;
            proxy_pass $llamacpp_inference_backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_buffering off;
            proxy_cache off;
            proxy_read_timeout 86400;
            proxy_request_buffering off;
        }

        # --- Llamacpp Service: catalog / pull / models / hardware / runtime / health ---
        # Service mounts controllers WITHOUT a /llamacpp/ prefix; nginx strips it here.
        location /api/v1/llamacpp/ {
            set $llamacpp_backend https://llamacpp-service:4017;
            rewrite ^/api/v1/llamacpp(/.*)$ /api/v1$1 break;
            proxy_pass $llamacpp_backend;
        }

        # --- Health Service ---
        location /api/v1/health {
            set $health_backend https://health-service:4009;
            proxy_pass $health_backend;
        }

        # --- Frontend (Next.js dev server, plain HTTP internally) ---
        # Catch-all: everything that isn't /api/v1/* goes to the Next dev
        # server. Must be declared LAST so longest-prefix match picks the
        # API routes first.
        location / {
            set $frontend_backend http://claw-frontend:3000;
            proxy_pass $frontend_backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }
    }
}
