# ─────────────────────────────────────────────────────────────
# WebPush Platform — Apache .htaccess
# ─────────────────────────────────────────────────────────────

# Default index file
DirectoryIndex index.php index.html

RewriteEngine On

# ── CORS Preflight (OPTIONS) Handling ───────────────────────
# Browsers send an OPTIONS request before POSTing cross-origin JSON.
# We must respond with 204 + CORS headers, and skip all other rules.
# This must come BEFORE any other RewriteRule or RedirectMatch.
<IfModule mod_headers.c>
    # Always set CORS headers for /api/ endpoints (handles preflight + actual)
    <LocationMatch "^/api/">
        Header always set Access-Control-Allow-Origin "*"
        Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
        Header always set Access-Control-Allow-Headers "Content-Type, X-API-Key, Authorization"
        Header always set Access-Control-Max-Age "86400"
    </LocationMatch>
</IfModule>

# Respond to OPTIONS preflight with 204 immediately (before routing)
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^api/ - [R=204,L,QSA]

# Route all /api/* requests through the API router (api/index.php)
RewriteCond %{REQUEST_METHOD} !OPTIONS
RewriteRule ^api/(.*)$ api/index.php [QSA,L]

# Deny direct access to sensitive PHP files (only accessible via router)
RewriteRule ^api/(subscribe|unsubscribe|send|campaigns|campaign-detail|stats|track-click|vapid-keys)\.php$ - [F]

# Deny access to sensitive directories
RedirectMatch 404 ^/lib/
RedirectMatch 404 ^/Models/
RedirectMatch 404 ^/Services/
RedirectMatch 404 ^/Http/

# Deny access to worker directory EXCEPT web-trigger.php (which is web-accessible for queue processing).
# The app lives under /web/, so the path is /web/worker/... — match either prefix.
RedirectMatch 403 ^(/web)?/worker/(?!web-trigger\.php).*$

# Deny access to sensitive files
<FilesMatch "\.(sql|log|env|lock|installed|md)$">
    Require all denied
</FilesMatch>

# Protect config.php from direct access (it's a PHP file but contains only defines,
# so direct access shows a blank page — still, let's deny it for safety)
<Files "config.php">
    Require all denied
</Files>

# ── Security Headers ────────────────────────────────────────
<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "DENY"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "same-origin"
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"

    # HSTS — only enable if you're sure you'll always use HTTPS
    # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

# ── Performance ─────────────────────────────────────────────
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE application/json application/javascript text/javascript
</IfModule>

<IfModule mod_expires.c>
    ExpiresActive On
    # Service workers MUST NOT be cached — browsers check for updates on every page load.
    # Setting Cache-Control: no-cache via FilesMatch below takes priority anyway.
    ExpiresByType application/javascript "access plus 1 hour"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 month"
</IfModule>

# ── Service Worker & SDK Cache Bypass ─────────────────────────
# SW files must never be cached — browsers check for updates on every page load.
# The loader-generated SDK must also be fresh per-request.
<FilesMatch "^(sw-.*|webpush-sw)\.js$">
    <IfModule mod_headers.c>
        Header always set Cache-Control "no-cache, no-store, must-revalidate"
        Header always set Pragma "no-cache"
        Header always set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
    </IfModule>
</FilesMatch>
