worker_processes auto;
error_log /dev/stderr warn;
pid /tmp/nginx.pid;

events {
  worker_connections 1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;

  log_format main '$remote_addr - [$time_local] "$request" $status $body_bytes_sent';
  access_log /dev/stdout main;

  sendfile on;
  tcp_nopush on;
  keepalive_timeout 65;

  # Serve pre-compressed assets (gzip .gz — built by vite brotliPrecompressPlugin)
  # brotli_static requires ngx_brotli module — not in Alpine nginx, use gzip fallback
  gzip_static on;
  gzip on;
  gzip_comp_level 5;
  gzip_min_length 1024;
  gzip_vary on;
  gzip_types application/json application/javascript text/css text/plain application/xml text/xml image/svg+xml;

  # Temp dirs writable by non-root
  client_body_temp_path /tmp/nginx-client-body;
  proxy_temp_path /tmp/nginx-proxy;
  fastcgi_temp_path /tmp/nginx-fastcgi;
  uwsgi_temp_path /tmp/nginx-uwsgi;
  scgi_temp_path /tmp/nginx-scgi;

  server {
    listen 8080;
    root /usr/share/nginx/html;
    index index.html;

    # Static assets — immutable cache
    location /assets/ {
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header Referrer-Policy "strict-origin-when-cross-origin" always;
      add_header X-XSS-Protection "1; mode=block" always;
      add_header Cache-Control "public, max-age=31536000, immutable";
      try_files $uri =404;
    }

    location /map-styles/ {
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header Referrer-Policy "strict-origin-when-cross-origin" always;
      add_header X-XSS-Protection "1; mode=block" always;
      add_header Cache-Control "public, max-age=31536000, immutable";
      try_files $uri =404;
    }

    location /data/ {
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header Referrer-Policy "strict-origin-when-cross-origin" always;
      add_header X-XSS-Protection "1; mode=block" always;
      add_header Cache-Control "public, max-age=31536000, immutable";
      try_files $uri =404;
    }

    location /textures/ {
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header Referrer-Policy "strict-origin-when-cross-origin" always;
      add_header X-XSS-Protection "1; mode=block" always;
      add_header Cache-Control "public, max-age=31536000, immutable";
      try_files $uri =404;
    }

    # API proxy → Node.js local-api-server
    location /api/ {
      proxy_pass http://127.0.0.1:${LOCAL_API_PORT};
      proxy_http_version 1.1;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      # Pass Origin as localhost so api key checks pass for browser-origin requests
      proxy_set_header Origin http://localhost;
      proxy_read_timeout 120s;
      proxy_send_timeout 120s;
    }

    # SPA fallback — all other routes serve index.html
    location / {
      add_header X-Content-Type-Options "nosniff" always;
      add_header X-Frame-Options "SAMEORIGIN" always;
      add_header Referrer-Policy "strict-origin-when-cross-origin" always;
      add_header X-XSS-Protection "1; mode=block" always;
      add_header Cache-Control "no-cache, no-store, must-revalidate";
      # Allow nested YouTube iframes to call requestStorageAccess().
      add_header Permissions-Policy "storage-access=(self \"https://www.youtube.com\" \"https://youtube.com\")";
      try_files $uri $uri/ /index.html;
    }
  }
}
