package com.saas.shared.security;

import com.saas.shared.core.TenantContext;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * Filter that extracts tenant identifier from JWT and sets it in TenantContext
 * BEFORE EntityManager opens connection. This ensures multi-tenant routing works correctly.
 * 
 * Execution order: JwtAuthenticationFilter → THIS FILTER → Controllers → Repositories
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TenantIdentifierFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwtTokenProvider;

    @Override
    protected void doFilterInternal(
            @NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain) throws ServletException, IOException {

        try {
            // CRITICAL: Check if tenant already set by a higher-priority filter (e.g., TelnyxTenantResolverFilter)
            // DO NOT overwrite if tenant context already exists
            String existingTenant = TenantContext.getTenantId();
            
            if (existingTenant != null && !existingTenant.isEmpty()) {
                log.debug("🔒 TenantIdentifierFilter: Tenant already set to '{}', skipping JWT extraction for URI: {}", 
                    existingTenant, request.getRequestURI());
            } else {
                // Only extract from JWT if no tenant was set by previous filters
                String tenantId = extractTenantFromRequest(request);
                
                if (tenantId != null && !tenantId.isEmpty()) {
                    TenantContext.setTenantId(tenantId);
                    log.debug("🔑 TenantIdentifierFilter: Set TenantContext to '{}' for URI: {}", 
                        tenantId, request.getRequestURI());
                } else {
                    log.debug("⚠️ TenantIdentifierFilter: No tenant found, defaulting to 'saas_db' for URI: {}", 
                        request.getRequestURI());
                }
            }
            
            filterChain.doFilter(request, response);
            
        } finally {
            TenantContext.clear();
            log.debug("🧹 TenantIdentifierFilter: Cleared TenantContext after request");
        }
    }

    /**
     * Extracts tenant identifier (schemaName) from JWT token in Authorization header.
     */
    private String extractTenantFromRequest(HttpServletRequest request) {
        String authHeader = request.getHeader("Authorization");
        
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            try {
                String token = authHeader.substring(7);
                String schemaName = jwtTokenProvider.getSchemaNameFromToken(token);
                
                if (schemaName != null && !schemaName.isEmpty()) {
                    log.debug("✅ TenantIdentifierFilter: Extracted tenant '{}' from JWT", schemaName);
                    return schemaName;
                }
            } catch (Exception e) {
                log.warn("⚠️ TenantIdentifierFilter: Failed to extract tenant from JWT: {}", e.getMessage());
            }
        }
        
        return null;
    }
}
