# ═══════════════════════════════════════════════════════════════════
# 15code Verify — Nginx reverse proxy
# Path layout:
#   /                 → web (Next.js on :3000)
#   /api/*            → API (FastAPI on :8000)  ← strip /api prefix
#   /v1/*             → API (direct, same backend)
#   /download/*       → static download artifacts
#   /health           → API health
# ═══════════════════════════════════════════════════════════════════

upstream verify_web { server 127.0.0.1:3000; keepalive 32; }
upstream verify_api { server 127.0.0.1:8000; keepalive 32; }

# Rate-limiting zones (protect API abuse)
limit_req_zone $binary_remote_addr zone=scan_zone:10m rate=6r/m;   # 6 scans / min / IP
limit_req_zone $binary_remote_addr zone=api_zone:10m rate=60r/m;

server {
    listen 80;
    server_name verify.15code.com;

    # certbot will inject 443 server block + redirect.
    # This block is kept for HTTP-01 challenges.

    location /.well-known/acme-challenge/ { root /var/www/html; }
    location / { return 301 https://$host$request_uri; }
}

server {
    listen 443 ssl http2;
    server_name verify.15code.com;

    # cert paths populated by certbot
    # ssl_certificate     /etc/letsencrypt/live/verify.15code.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/verify.15code.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    # Security headers
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

    # Payload size (for large scan configs)
    client_max_body_size 2M;

    # Gzip
    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;

    # ─── Health (quick check, no rate limit) ─────────────────────
    location = /health {
        proxy_pass http://verify_api/health;
        access_log off;
    }

    # ─── API: /v1/* → FastAPI (direct) ───────────────────────────
    location /v1/ {
        limit_req zone=api_zone burst=20 nodelay;
        proxy_pass http://verify_api;
        proxy_http_version 1.1;
        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_buffering    off;        # critical for SSE
        proxy_cache        off;
        proxy_read_timeout 10m;        # long scans
    }

    # Apply stricter limit to POST /v1/scan
    location = /v1/scan {
        limit_req zone=scan_zone burst=3 nodelay;
        proxy_pass http://verify_api;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # ─── Download artifacts (static, cacheable) ──────────────────
    location /download/ {
        alias /opt/15code-verify/dist/;
        autoindex off;
        expires 1h;
        add_header Cache-Control "public";
        # CORS so the web can reference these
        add_header Access-Control-Allow-Origin "https://verify.15code.com";
    }

    # ─── Web UI (Next.js) ────────────────────────────────────────
    location / {
        proxy_pass http://verify_web;
        proxy_http_version 1.1;
        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   Upgrade           $http_upgrade;
        proxy_set_header   Connection        "upgrade";
    }
}
