package com.saas.voip.filter;

import com.saas.admin.entity.PhoneNumber;
import com.saas.admin.entity.Tenant;
import com.saas.admin.repository.PhoneNumberRepository;
import com.saas.admin.repository.TenantRepository;
import com.saas.shared.core.TenantContext;
import com.saas.shared.enums.Provider;
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.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Optional;

/**
 * CRITICAL: High-priority filter that resolves tenant BEFORE OpenEntityManagerInViewFilter.
 * 
 * Execution order: THIS FILTER (HIGHEST_PRECEDENCE) → OpenEntityManagerInViewFilter → Controllers
 * 
 * This ensures EntityManager opens with the correct tenant schema for VoIP webhooks.
 */
@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@RequiredArgsConstructor
public class TelnyxTenantResolverFilter extends OncePerRequestFilter {

    private final PhoneNumberRepository phoneNumberRepository;
    private final TenantRepository tenantRepository;

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

        String requestUri = request.getRequestURI();
        
        // Only intercept Telnyx webhook endpoints
        if (isTelnyxWebhook(requestUri)) {
            log.debug("🎯 TelnyxTenantResolverFilter: Intercepting webhook: {}", requestUri);
            
            try {
                // Step 1: Set to saas_db for admin queries
                TenantContext.setTenantId("saas_db");
                
                // Step 2: Extract phone number from request
                String toNumber = extractToNumber(request);
                
                if (toNumber != null) {
                    // Step 3: Look up tenant from phone number
                    Optional<PhoneNumber> phoneOpt = phoneNumberRepository.findByPhoneNumber(toNumber);
                    
                    if (phoneOpt.isPresent() && phoneOpt.get().getProvider() == Provider.TELNYX) {
                        String tenantId = phoneOpt.get().getTenantId();
                        
                        Optional<Tenant> tenantOpt = tenantRepository.findByTenantId(tenantId);
                        
                        if (tenantOpt.isPresent()) {
                            String schemaName = tenantOpt.get().getSchemaName();
                            
                            // CRITICAL: Store tenant info in request attributes for controller
                            // DO NOT change TenantContext here - leave it as saas_db
                            request.setAttribute("RESOLVED_TENANT_ID", tenantId);
                            request.setAttribute("RESOLVED_TENANT_SCHEMA", schemaName);
                            
                            log.info("✅ TelnyxTenantResolverFilter: Resolved tenant '{}' (schema: {}) for number: {} - Context remains 'saas_db'", 
                                    tenantId, schemaName, toNumber);
                        } else {
                            log.warn("⚠️ TelnyxTenantResolverFilter: Tenant not found for ID: {}", tenantId);
                        }
                    } else {
                        log.warn("⚠️ TelnyxTenantResolverFilter: No Telnyx phone number found: {}", toNumber);
                    }
                } else {
                    log.warn("⚠️ TelnyxTenantResolverFilter: Could not extract 'To' number from request");
                }
                
                // Proceed with filter chain (EntityManager will now open with correct schema)
                filterChain.doFilter(request, response);
                
            } finally {
                // Step 5: Clear context after request
                TenantContext.clear();
                log.debug("🧹 TelnyxTenantResolverFilter: Cleared TenantContext");
            }
        } else {
            // Not a Telnyx webhook, proceed normally
            filterChain.doFilter(request, response);
        }
    }

    /**
     * Check if request is a Telnyx webhook
     */
    private boolean isTelnyxWebhook(String uri) {
        return uri != null && uri.contains("/api/voip/telnyx/");
    }

    /**
     * Extract 'To' phone number from request parameters
     */
    private String extractToNumber(HttpServletRequest request) {
        // Try query parameters first
        String to = request.getParameter("To");
        
        if (to == null) {
            // Try form data (for POST with application/x-www-form-urlencoded)
            to = request.getParameter("to");
        }
        
        if (to == null) {
            // Try case-insensitive search
            to = request.getParameter("TO");
        }
        
        return to;
    }
}
