package com.gnx.telemedicine.config;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * Security headers configuration filter.
 * Adds security headers to all HTTP responses for enhanced security.
 * Headers are configurable via application properties.
 */
@Component
@Order(1)
@Slf4j
public class SecurityHeadersConfig extends OncePerRequestFilter {

    @Value("${server.ssl.enabled:false}")
    private boolean sslEnabled;

    @Value("${security.headers.hsts.enabled:${server.ssl.enabled:false}}")
    private boolean hstsEnabled;

    @Value("${security.headers.hsts.max-age:63072000}")
    private long hstsMaxAge;

    @Value("${security.headers.hsts.include-subdomains:true}")
    private boolean hstsIncludeSubdomains;

    @Value("${security.headers.hsts.preload:false}")
    private boolean hstsPreload;

    @Value("${security.headers.csp.enabled:true}")
    private boolean cspEnabled;

    @Value("${security.headers.frame-options:DENY}")
    private String frameOptions;

    @Value("${security.headers.content-type-options:nosniff}")
    private String contentTypeOptions;

    @Value("${security.headers.xss-protection:1; mode=block}")
    private String xssProtection;

    @Value("${security.headers.referrer-policy:strict-origin-when-cross-origin}")
    private String referrerPolicy;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        // Strict Transport Security (HSTS) - Only enabled when SSL is enabled
        if (hstsEnabled && sslEnabled) {
            StringBuilder hstsValue = new StringBuilder("max-age=").append(hstsMaxAge);
            if (hstsIncludeSubdomains) {
                hstsValue.append("; includeSubDomains");
            }
            if (hstsPreload) {
                hstsValue.append("; preload");
            }
            response.setHeader("Strict-Transport-Security", hstsValue.toString());
            log.debug("HSTS header set: {}", hstsValue);
        }
        
        // Content Security Policy - Enhanced for enterprise security
        if (cspEnabled) {
            // Check if we're in production mode
            String profile = System.getenv("SPRING_PROFILES_ACTIVE");
            boolean isProduction = "prod".equals(profile) || "production".equals(profile);
            
            // Build CSP based on environment
            StringBuilder csp = new StringBuilder();
            
            // Default source - only allow same origin
            csp.append("default-src 'self'; ");
            
            // Script source - allow same origin, inline scripts for Swagger (development only)
            if (isProduction) {
                csp.append("script-src 'self'; ");
            } else {
                csp.append("script-src 'self' 'unsafe-inline' 'unsafe-eval'; "); // Allow inline scripts for Swagger in dev
            }
            
            // Style source - allow same origin and inline styles
            csp.append("style-src 'self' 'unsafe-inline'; ");
            
            // Image source - allow same origin, data URIs, and HTTPS
            String cspImgSrc = "'self' data: https:";
            if (!isProduction) {
                cspImgSrc += " http://localhost:8080 http://localhost:4200 http://127.0.0.1:8080 http://127.0.0.1:4200";
            }
            csp.append("img-src ").append(cspImgSrc).append("; ");
            
            // Font source - allow same origin and data URIs
            csp.append("font-src 'self' data:; ");
            
            // Connect source - allow same origin, WebSocket, and HTTPS
            String cspConnectSrc = "'self' https:";
            if (!isProduction) {
                cspConnectSrc += " ws://localhost:* wss://localhost:* ws://127.0.0.1:* wss://127.0.0.1:* http://localhost:8080 http://localhost:4200 http://127.0.0.1:8080 http://127.0.0.1:4200";
            } else {
                cspConnectSrc += " wss:";
            }
            csp.append("connect-src ").append(cspConnectSrc).append("; ");
            
            // Frame ancestors - prevent clickjacking
            csp.append("frame-ancestors 'none'; ");
            
            // Base URI - only allow same origin
            csp.append("base-uri 'self'; ");
            
            // Form action - only allow same origin
            csp.append("form-action 'self'; ");
            
            // Upgrade insecure requests - only in production with SSL
            if (isProduction && sslEnabled) {
                csp.append("upgrade-insecure-requests; ");
            }
            
            // Object source - prevent plugins
            csp.append("object-src 'none'; ");
            
            // Media source - allow same origin
            csp.append("media-src 'self'; ");
            
            // Worker source - allow same origin
            csp.append("worker-src 'self'; ");
            
            // Manifest source - allow same origin
            csp.append("manifest-src 'self'; ");
            
            response.setHeader("Content-Security-Policy", csp.toString());
            log.debug("CSP header set for {} environment", isProduction ? "production" : "development");
        }
        
        // Prevent clickjacking
        response.setHeader("X-Frame-Options", frameOptions);
        
        // Prevent MIME type sniffing
        response.setHeader("X-Content-Type-Options", contentTypeOptions);
        
        // Enable XSS protection (legacy header, CSP is preferred)
        response.setHeader("X-XSS-Protection", xssProtection);
        
        // Referrer Policy - Enhanced for privacy
        response.setHeader("Referrer-Policy", referrerPolicy);
        
        // Permissions Policy (formerly Feature Policy) - Enhanced for HIPAA compliance
        response.setHeader("Permissions-Policy", 
            "geolocation=(), " +
            "microphone=(), " +
            "camera=(), " +
            "payment=(), " +
            "usb=(), " +
            "magnetometer=(), " +
            "gyroscope=(), " +
            "accelerometer=()");
        
        // Additional enterprise security headers
        // Cross-Origin Embedder Policy - relaxed for file resources and API endpoints
        String requestPathForCOEP = request.getRequestURI();
        if (requestPathForCOEP != null && (requestPathForCOEP.startsWith("/api/") || 
                                          requestPathForCOEP.startsWith("/files/") ||
                                          requestPathForCOEP.startsWith("/actuator/") ||
                                          requestPathForCOEP.startsWith("/auth/") ||
                                          requestPathForCOEP.startsWith("/ws/") ||
                                          requestPathForCOEP.contains("/avatars/") ||
                                          requestPathForCOEP.endsWith(".ico") ||
                                          requestPathForCOEP.endsWith(".png") ||
                                          requestPathForCOEP.endsWith(".jpg") ||
                                          requestPathForCOEP.endsWith(".jpeg") ||
                                          requestPathForCOEP.endsWith(".gif") ||
                                          requestPathForCOEP.endsWith(".svg"))) {
            // Don't set COEP for API and file resources to allow cross-origin loading
            // response.setHeader("Cross-Origin-Embedder-Policy", "unsafe-none");
        } else {
            response.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
        }
        
        // Cross-Origin Opener Policy
        response.setHeader("Cross-Origin-Opener-Policy", "same-origin");
        
        // Cross-Origin Resource Policy
        // Allow cross-origin for file resources, API endpoints, and public resources
        String requestPath = request.getRequestURI();
        if (requestPath != null && (requestPath.startsWith("/api/") || 
                                    requestPath.startsWith("/files/") ||
                                    requestPath.startsWith("/actuator/") ||
                                    requestPath.startsWith("/auth/") ||
                                    requestPath.startsWith("/ws/") ||
                                    requestPath.contains("/avatars/") ||
                                    requestPath.endsWith(".ico") ||
                                    requestPath.endsWith(".png") ||
                                    requestPath.endsWith(".jpg") ||
                                    requestPath.endsWith(".jpeg") ||
                                    requestPath.endsWith(".gif") ||
                                    requestPath.endsWith(".svg"))) {
            response.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
        } else {
            response.setHeader("Cross-Origin-Resource-Policy", "same-origin");
        }
        
        // Expect-CT (Certificate Transparency) - Disabled since SSL is not enabled
        // Only set Expect-CT when SSL is enabled
        // response.setHeader("Expect-CT", "max-age=86400, enforce");
        
        // Clear Site Data (for GDPR compliance - can be used for logout)
        // Note: This is set per request, not here. Use it when needed.
        
        // Privacy-focused headers
        response.setHeader("X-Permitted-Cross-Domain-Policies", "none");
        
        // DNS Prefetch Control
        response.setHeader("X-DNS-Prefetch-Control", "off");
        
        filterChain.doFilter(request, response);
    }
}

