# nginx tile cache for Martin vector tile server
# Proxy-cache layer: 10-100x faster on repeat requests, zero PostGIS load for cached tiles

proxy_cache_path /var/cache/nginx/tiles
  levels=1:2
  keys_zone=tiles:64m
  max_size=2g
  inactive=7d
  use_temp_path=off;

# Log format with cache status for monitoring (docker logs tile-cache | grep HIT/MISS)
log_format tiles '$remote_addr [$time_local] "$request" $status '
                 'cache=$upstream_cache_status size=$body_bytes_sent '
                 'time=$request_time';

server {
  access_log /var/log/nginx/access.log tiles;
  listen 80;
  server_name _;

  # Health check
  location = /health {
    access_log off;
    return 200 "ok\n";
    add_header Content-Type text/plain;
  }

  # nginx status (active connections, request counts) — for monitoring
  location = /status {
    access_log off;
    stub_status on;
  }

  # Martin catalog endpoint (no cache)
  location = /catalog {
    proxy_pass http://martin:3000/catalog;
    proxy_set_header Host $host;
  }

  # PMTiles from MinIO — HTTPS proxy for browser access (avoids mixed-content block)
  # Browser fetches: /pmtiles/overview.pmtiles → MinIO http://10.10.10.166:9002/tiles/overview.pmtiles
  location /pmtiles/ {
    proxy_pass http://10.10.10.166:9002/tiles/;
    proxy_set_header Host 10.10.10.166:9002;
    proxy_http_version 1.1;

    # Range requests — essential for PMTiles (byte-range tile lookups)
    proxy_set_header Range $http_range;
    proxy_set_header If-Range $http_if_range;
    proxy_pass_request_headers on;

    # Browser cache — file changes only on rebuild (~weekly)
    add_header Cache-Control "public, max-age=3600, stale-while-revalidate=86400" always;

    # CORS — PMTiles loaded from tools.beletage.ro page
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Range, If-None-Match, If-Range, Accept-Encoding" always;
    add_header Access-Control-Expose-Headers "Content-Range, Content-Length, ETag, Accept-Ranges" always;

    # Preflight
    if ($request_method = OPTIONS) {
      add_header Access-Control-Allow-Origin "*";
      add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS";
      add_header Access-Control-Allow-Headers "Range, If-Range";
      add_header Access-Control-Max-Age 86400;
      add_header Content-Length 0;
      return 204;
    }
  }

  # Tile requests — cache aggressively
  location / {
    proxy_pass http://martin:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    # Cache config — tiles change only on sync (weekly), long TTL is safe
    proxy_cache tiles;
    proxy_cache_key "$request_uri";
    proxy_cache_valid 200 7d;
    proxy_cache_valid 204 1h;
    proxy_cache_valid 404 1m;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_cache_lock on;
    proxy_cache_lock_timeout 5s;

    # Browser caching — tiles are immutable between syncs
    add_header Cache-Control "public, max-age=86400, stale-while-revalidate=604800" always;

    # Pass cache status header (useful for debugging)
    add_header X-Cache-Status $upstream_cache_status always;

    # CORS headers for tile requests
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Range, If-None-Match, Accept-Encoding" always;
    add_header Access-Control-Expose-Headers "Content-Range, Content-Length, ETag, X-Cache-Status" always;

    # Handle preflight
    if ($request_method = OPTIONS) {
      add_header Access-Control-Allow-Origin "*";
      add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS";
      add_header Access-Control-Max-Age 86400;
      add_header Content-Length 0;
      return 204;
    }

    # Let Martin gzip natively — pass compressed response through to client and cache
    gzip off;

    # Timeouts (Martin can be slow on low-zoom tiles)
    proxy_connect_timeout 10s;
    proxy_read_timeout 120s;
    proxy_send_timeout 30s;
  }
}
