RewriteEngine On

# Security Headers (compatible con hosting compartido)
<IfModule mod_headers.c>
    # Prevenir MIME type sniffing
    Header always set X-Content-Type-Options nosniff
    
    # Prevenir clickjacking
    Header always set X-Frame-Options DENY
    
    # Protección XSS
    Header always set X-XSS-Protection "1; mode=block"
    
    # Control de referrer
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    
    # Content Security Policy mejorado
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests;"
    
    # Prevenir información del servidor
    Header always unset Server
    Header always unset X-Powered-By
    Header always unset X-AspNet-Version
    Header always unset X-AspNetMvc-Version
    
    # Strict Transport Security (descomenta para HTTPS)
    # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    
    # Permissions Policy mejorado
    Header always set Permissions-Policy "geolocation=(self), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), speaker=(), fullscreen=(self), picture-in-picture=(), accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), gyroscope=(), layout-animations=(), legacy-image-formats=(), magnetometer=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), sync-xhr=(), usb=(), wake-lock=(), screen-wake-lock=(), web-share=(), xr-spatial-tracking=()"
    
    # Cache Control para archivos sensibles
    <FilesMatch "\.(php|log|sql|txt|md)$">
        Header always set Cache-Control "no-cache, no-store, must-revalidate"
        Header always set Pragma "no-cache"
        Header always set Expires "0"
    </FilesMatch>
    
    # Headers específicos para PDFs
    <FilesMatch "\.pdf$">
        Header always set X-Content-Type-Options nosniff
        Header always set Content-Security-Policy "default-src 'none'; object-src 'none'; frame-ancestors 'none';"
        Header always set X-Frame-Options DENY
        Header always set Content-Disposition "attachment"
    </FilesMatch>
    
    # Headers para archivos de logs
    <FilesMatch "\.log$">
        Header always set Cache-Control "no-cache, no-store, must-revalidate"
        Header always set Pragma "no-cache"
        Header always set Expires "0"
    </FilesMatch>
    
    # Headers para archivos de configuración
    <FilesMatch "\.(env|config|ini|conf)$">
        Header always set Cache-Control "no-cache, no-store, must-revalidate"
        Header always set Pragma "no-cache"
        Header always set Expires "0"
    </FilesMatch>
</IfModule>

# Brotli compression (preferred over gzip)
<IfModule mod_brotli.c>
    # Enable Brotli compression
    BrotliCompressionLevel 6
    BrotliCompressionWindow 22
    
    # Compress these file types with Brotli
    AddOutputFilterByType BROTLI_COMPRESS text/html
    AddOutputFilterByType BROTLI_COMPRESS text/plain
    AddOutputFilterByType BROTLI_COMPRESS text/xml
    AddOutputFilterByType BROTLI_COMPRESS text/css
    AddOutputFilterByType BROTLI_COMPRESS text/javascript
    AddOutputFilterByType BROTLI_COMPRESS application/javascript
    AddOutputFilterByType BROTLI_COMPRESS application/x-javascript
    AddOutputFilterByType BROTLI_COMPRESS application/json
    AddOutputFilterByType BROTLI_COMPRESS application/xml
    AddOutputFilterByType BROTLI_COMPRESS application/rss+xml
    AddOutputFilterByType BROTLI_COMPRESS application/atom+xml
    AddOutputFilterByType BROTLI_COMPRESS application/manifest+json
    AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
    AddOutputFilterByType BROTLI_COMPRESS font/ttf
    AddOutputFilterByType BROTLI_COMPRESS font/otf
    AddOutputFilterByType BROTLI_COMPRESS font/woff
    AddOutputFilterByType BROTLI_COMPRESS font/woff2
</IfModule>

# Serve pre-compressed files if available
<IfModule mod_rewrite.c>
    # Check for Brotli compressed files first
    RewriteCond %{HTTP:Accept-Encoding} br
    RewriteCond %{REQUEST_FILENAME}\.br -f
    RewriteRule ^(.*)$ $1.br [L]
    
    # Check for gzip compressed files as fallback
    RewriteCond %{HTTP:Accept-Encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -f
    RewriteRule ^(.*)$ $1.gz [L]
</IfModule>

# Set proper content-type and encoding for pre-compressed files
<FilesMatch "\.js\.br$">
    Header set Content-Type "application/javascript"
    Header set Content-Encoding "br"
    Header set Vary "Accept-Encoding"
</FilesMatch>

<FilesMatch "\.css\.br$">
    Header set Content-Type "text/css"
    Header set Content-Encoding "br"
    Header set Vary "Accept-Encoding"
</FilesMatch>

<FilesMatch "\.js\.gz$">
    Header set Content-Type "application/javascript"
    Header set Content-Encoding "gzip"
    Header set Vary "Accept-Encoding"
</FilesMatch>

<FilesMatch "\.css\.gz$">
    Header set Content-Type "text/css"
    Header set Content-Encoding "gzip"
    Header set Vary "Accept-Encoding"
</FilesMatch>

# Enable GZIP compression with enhanced configuration (fallback)
<IfModule mod_deflate.c>
    # Compress HTML, CSS, JavaScript, Text, XML and fonts
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
    AddOutputFilterByType DEFLATE application/x-font
    AddOutputFilterByType DEFLATE application/x-font-opentype
    AddOutputFilterByType DEFLATE application/x-font-otf
    AddOutputFilterByType DEFLATE application/x-font-truetype
    AddOutputFilterByType DEFLATE application/x-font-ttf
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/ld+json
    AddOutputFilterByType DEFLATE application/manifest+json
    AddOutputFilterByType DEFLATE font/opentype
    AddOutputFilterByType DEFLATE font/otf
    AddOutputFilterByType DEFLATE font/ttf
    AddOutputFilterByType DEFLATE font/woff
    AddOutputFilterByType DEFLATE font/woff2
    AddOutputFilterByType DEFLATE image/svg+xml
    AddOutputFilterByType DEFLATE image/x-icon
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/cache-manifest

    # Set compression level (1-9, 6 is optimal balance)
    DeflateCompressionLevel 6
    
    # Don't compress already compressed files
    SetEnvIfNoCase Request_URI \
        \.(?:gif|jpe?g|png|zip|gz|bz2|sit|rar|7z|br)$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \
        \.(?:exe|t?gz|zip|bz2|sit|rar|pdf|mov|avi|mp3|mp4|rm)$ no-gzip dont-vary

    # Remove browser bugs (only needed for really old browsers)
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
    Header append Vary User-Agent env=!dont-vary
</IfModule>

# Alternative GZIP compression using mod_gzip
<IfModule mod_gzip.c>
    mod_gzip_on Yes
    mod_gzip_dechunk Yes
    mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
    mod_gzip_item_include handler ^cgi-script$
    mod_gzip_item_include mime ^text/.*
    mod_gzip_item_include mime ^application/x-javascript.*
    mod_gzip_item_exclude mime ^image/.*
    mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>

# Enhanced caching for static files
<IfModule mod_expires.c>
    ExpiresActive on
    
    # CSS and JavaScript
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType application/x-javascript "access plus 1 year"
    
    # Images
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"
    
    # Fonts
    ExpiresByType font/ttf "access plus 1 year"
    ExpiresByType font/otf "access plus 1 year"
    ExpiresByType font/woff "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType application/font-woff "access plus 1 year"
    ExpiresByType application/font-woff2 "access plus 1 year"
    
    # Documents
    ExpiresByType application/pdf "access plus 1 month"
    
    # Data
    ExpiresByType application/json "access plus 1 hour"
    ExpiresByType application/xml "access plus 1 hour"
    ExpiresByType text/xml "access plus 1 hour"
    
    # HTML
    ExpiresByType text/html "access plus 1 hour"
    
    # Manifest files
    ExpiresByType application/manifest+json "access plus 1 week"
    ExpiresByType text/cache-manifest "access plus 0 seconds"
</IfModule>

# Add cache control headers
<IfModule mod_headers.c>
    # Cache static assets for 1 year
    <FilesMatch "\.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff|woff2|ttf|otf)$">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>
    
    # Cache HTML for 1 hour
    <FilesMatch "\.(html|htm)$">
        Header set Cache-Control "public, max-age=3600"
    </FilesMatch>
    
    # Don't cache service worker
    <FilesMatch "sw\.js$">
        Header set Cache-Control "no-cache, no-store, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires "0"
    </FilesMatch>
    
    # Don't cache manifest
    <FilesMatch "manifest\.json$">
        Header set Cache-Control "no-cache, no-store, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires "0"
    </FilesMatch>
</IfModule>

# API Routes - redirect all /api requests to api/index.php
RewriteRule ^api/(.*)$ api/index.php [QSA,L]

# Install script - allow direct access
RewriteRule ^install\.php$ - [L]

# Test scripts - allow direct access (remove in production)
RewriteRule ^test_.*\.php$ - [L]

# Protect sensitive files
<FilesMatch "^(config\.php|\.env|composer\.json|package\.json|\.htaccess|\.htpasswd)$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect log files
<FilesMatch "\.log$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect database files
<FilesMatch "\.(sql|db|sqlite|mdb|accdb)$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect backup and temporary files
<FilesMatch "\.(bak|backup|tmp|temp|old|orig|save|swp|swo|~)$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect version control files
<FilesMatch "^(\.git|\.svn|\.hg|\.bzr)">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect IDE and editor files
<FilesMatch "\.(idea|vscode|sublime-project|sublime-workspace|project|workspace)$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect system and configuration files
<FilesMatch "^(readme|license|changelog|install|upgrade|todo).*\.(txt|md|rst)$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Protect PHP include files
<FilesMatch "^(inc|include|lib|class).*\.php$">
    <RequireAll>
        Require all denied
    </RequireAll>
</FilesMatch>

# Block access to uploads directory directly (files should be served through API)
<Directory "uploads">
    <RequireAll>
        Require all denied
    </RequireAll>
</Directory>

# Block access to logs directory
<Directory "logs">
    <RequireAll>
        Require all denied
    </RequireAll>
</Directory>

# Block access to api config directory
<Directory "api/config">
    <RequireAll>
        Require all denied
    </RequireAll>
</Directory>

# Rate limiting for API endpoints (if mod_evasive is available)
<IfModule mod_evasive24.c>
    DOSHashTableSize    2048
    DOSPageCount        10
    DOSPageInterval     1
    DOSSiteCount        50
    DOSSiteInterval     1
    DOSBlockingPeriod   600
</IfModule>

# Block common attack patterns
<IfModule mod_rewrite.c>
    # Block SQL injection attempts
    RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
    RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
    RewriteCond %{QUERY_STRING} \.\./\.\./\.\./\.\./\.\./\.\./\.\./\.\./ [OR]
    RewriteCond %{QUERY_STRING} (union|select|insert|drop|delete|update|create|alter|exec|execute|declare|cast|set|convert|concat|char|varchar|nvarchar|substring|ascii|hex|unhex|md5|sha1|sha2|password|encode|decode|compress|uncompress|base64|from_base64|to_base64|aes_encrypt|aes_decrypt|des_encrypt|des_decrypt|benchmark|sleep|get_lock|release_lock|is_free_lock|is_used_lock|master_pos_wait|name_const|rand|connection_id|current_user|database|schema|user|system_user|session_user|version|load_file|into|outfile|dumpfile) [NC]
    RewriteRule .* - [F,L]
    
    # Block XSS attempts
    RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} javascript: [NC,OR]
    RewriteCond %{QUERY_STRING} vbscript: [NC,OR]
    RewriteCond %{QUERY_STRING} onload= [NC,OR]
    RewriteCond %{QUERY_STRING} onunload= [NC,OR]
    RewriteCond %{QUERY_STRING} onchange= [NC,OR]
    RewriteCond %{QUERY_STRING} onsubmit= [NC,OR]
    RewriteCond %{QUERY_STRING} onreset= [NC,OR]
    RewriteCond %{QUERY_STRING} onselect= [NC,OR]
    RewriteCond %{QUERY_STRING} onblur= [NC,OR]
    RewriteCond %{QUERY_STRING} onfocus= [NC,OR]
    RewriteCond %{QUERY_STRING} onabort= [NC,OR]
    RewriteCond %{QUERY_STRING} onkeydown= [NC,OR]
    RewriteCond %{QUERY_STRING} onkeypress= [NC,OR]
    RewriteCond %{QUERY_STRING} onkeyup= [NC,OR]
    RewriteCond %{QUERY_STRING} onclick= [NC,OR]
    RewriteCond %{QUERY_STRING} ondblclick= [NC,OR]
    RewriteCond %{QUERY_STRING} onmousedown= [NC,OR]
    RewriteCond %{QUERY_STRING} onmousemove= [NC,OR]
    RewriteCond %{QUERY_STRING} onmouseout= [NC,OR]
    RewriteCond %{QUERY_STRING} onmouseover= [NC,OR]
    RewriteCond %{QUERY_STRING} onmouseup= [NC]
    RewriteRule .* - [F,L]
</IfModule>

# React Router - handle client-side routing
# Don't rewrite files that exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Don't rewrite API calls
RewriteCond %{REQUEST_URI} !^/api/
# Don't rewrite install script
RewriteCond %{REQUEST_URI} !^/install\.php
# Don't rewrite test scripts
RewriteCond %{REQUEST_URI} !^/test_.*\.php$
# Redirect everything else to index.html for React Router
RewriteRule . /index.html [L]

# Prevent access to source files in production
<FilesMatch "\.(jsx?|ts|tsx|map)$">
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_URI} !^/static/
        RewriteRule .* - [F,L]
    </IfModule>
</FilesMatch>

# Force HTTPS (uncomment for production)
# RewriteCond %{HTTPS} off
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Prevent directory browsing
Options -Indexes

# Set default charset
AddDefaultCharset UTF-8