package com.saas.voip.controller;

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.AIProvider;
import com.saas.shared.enums.Provider;
import com.saas.tenant.entity.InboundCallData;
import com.saas.tenant.service.InboundCallService;
import com.saas.tenant.service.TenantAIConfigService;
import com.saas.voip.extractor.TelnyxCallDataExtractor;
import com.saas.voip.service.RetellCallBridgeService;
import com.saas.voip.service.VapiCallBridgeService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.time.LocalTime;
import java.util.Enumeration;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/api/voip/telnyx")
@Slf4j
@RequiredArgsConstructor
public class TelnyxVoiceController {

    private final TelnyxCallDataExtractor callDataExtractor;
    private final InboundCallService inboundCallService;
    private final PhoneNumberRepository phoneNumberRepository;
    private final TenantRepository tenantRepository;
    private final TenantAIConfigService aiConfigService;
    private final RetellCallBridgeService retellBridgeService;
    private final VapiCallBridgeService vapiBridgeService;

    @PostMapping(value = "/incoming-call", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map<String, Object> handleIncomingCall(HttpServletRequest request,
            @RequestBody Map<String, Object> payload) {

        log.info("=== TELNYX WEBHOOK RECEIVED ===");

        // Extract event type from Telnyx webhook
        Map<String, Object> eventData = (Map<String, Object>) payload.get("data");
        String eventType = (String) eventData.get("event_type");

        log.info("📞 Event Type: {}", eventType);

        // Only handle call.initiated events for incoming calls
        if (!"call.initiated".equals(eventType)) {
            log.info("⏭️ Ignoring event type: {}", eventType);
            return Map.of("status", "ignored", "event_type", eventType);
        }

        Map<String, Object> callPayload = (Map<String, Object>) eventData.get("payload");

        String fromNumber = (String) callPayload.get("from");
        String toNumber = (String) callPayload.get("to");
        String callControlId = (String) callPayload.get("call_control_id");
        String callSessionId = (String) callPayload.get("call_session_id");
        String direction = (String) callPayload.get("direction");

        log.info("📞 Direction: {}, From: {}, To: {}", direction, fromNumber, toNumber);
        log.info("🆔 Call Control ID: {}, Session ID: {}", callControlId, callSessionId);

        // Only handle incoming calls
        if (!"incoming".equals(direction)) {
            log.info("⏭️ Ignoring non-incoming call");
            return Map.of("status", "ignored", "direction", direction);
        }

        String schemaName = null;
        String tenantId = null;

        // Identify tenant via phone number
        if (toNumber != null) {
            try {
                Optional<PhoneNumber> phoneOpt = phoneNumberRepository.findByPhoneNumber(toNumber);

                if (phoneOpt.isPresent() && phoneOpt.get().getProvider() == Provider.TELNYX) {
                    tenantId = phoneOpt.get().getTenantId();
                    log.info("📞 Identified Tenant ID: {} for Telnyx number: {}", tenantId, toNumber);

                    // Get tenant schema
                    Optional<Tenant> tenant = tenantRepository.findByTenantId(tenantId);
                    if (tenant.isPresent()) {
                        schemaName = tenant.get().getSchemaName();
                        log.info("📊 Using schema: {} for tenant: {}", schemaName, tenantId);
                    }
                } else {
                    log.warn("⚠️ No Telnyx tenant found for phone number: {}", toNumber);
                }
            } catch (Exception e) {
                log.error("Error looking up tenant", e);
            }
        }

        // Save call data to tenant schema
        if (schemaName != null && callSessionId != null) {
            TenantContext.setTenantId(schemaName);

            try {
                // Extract and save call data
                InboundCallData callData = callDataExtractor.extractFromTelnyxRequest(payload);
                inboundCallService.saveCallData(callData);

                log.info("✅ Telnyx call data saved to tenant schema: {}", schemaName);
            } catch (Exception e) {
                log.error("Error saving Telnyx call data", e);
            } finally {
                TenantContext.clear();
            }
        }

        // ========== AI BRIDGING LOGIC ==========
        if (tenantId != null && callControlId != null) {
            try {
                log.info("🤖 Attempting to bridge call to AI assistant");

                // Get AI configuration for tenant
                AIProvider provider = aiConfigService.resolveProvider(tenantId, LocalTime.now());

                log.info("🎯 Resolved AI provider: {}", provider);

                // Bridge to appropriate AI provider
                switch (provider) {
                    case RETELL:
                        log.info("🔗 Bridging to Retell AI");
                        retellBridgeService.bridgeTelnyxCallToRetell(
                                callControlId,
                                tenantId,
                                fromNumber,
                                toNumber);
                        return Map.of(
                                "status", "bridged",
                                "provider", "RETELL",
                                "call_control_id", callControlId);

                    case VAPI:
                        log.info("🔗 Bridging to Vapi AI");
                        vapiBridgeService.bridgeTelnyxCallToVapi(
                                callControlId,
                                tenantId,
                                fromNumber,
                                toNumber);
                        return Map.of(
                                "status", "bridged",
                                "provider", "VAPI",
                                "call_control_id", callControlId);

                    case NONE:
                    default:
                        log.warn("⚠️ No AI provider configured for tenant: {}", tenantId);
                        return Map.of(
                                "status", "no_ai_configured",
                                "call_control_id", callControlId,
                                "message", "No AI assistant configured for this tenant");
                }

            } catch (Exception e) {
                log.error("❌ Error bridging call to AI", e);
                return Map.of(
                        "status", "bridge_failed",
                        "call_control_id", callControlId,
                        "error", e.getMessage());
            }
        }

        // Return 200 OK - Telnyx doesn't expect commands in webhook response
        return Map.of(
                "status", "received",
                "call_control_id", callControlId,
                "message", "Call received but not bridged");
    }

    @PostMapping(value = "/call-initiated", produces = MediaType.APPLICATION_JSON_VALUE)
    public void handleCallInitiated(@RequestBody Map<String, Object> payload) {
        log.info("📞 Telnyx call initiated event received");
        // Log the event, no action needed
    }

    @PostMapping(value = "/call-answered", produces = MediaType.APPLICATION_JSON_VALUE)
    public void handleCallAnswered(@RequestBody Map<String, Object> payload) {
        log.info("✅ Telnyx call answered event received");
    }

    @PostMapping(value = "/call-hangup", produces = MediaType.APPLICATION_JSON_VALUE)
    public void handleCallHangup(@RequestBody Map<String, Object> payload) {
        log.info("📴 Telnyx call hangup event received");

        Map<String, Object> eventData = (Map<String, Object>) payload.get("data");
        Map<String, Object> callPayload = (Map<String, Object>) eventData.get("payload");

        String callSessionId = (String) callPayload.get("call_session_id");

        // Update call status in database
        // TODO: Extract duration and update
    }

    @GetMapping("/health")
    public String health() {
        return "Telnyx VoIP Service is running!";
    }

    /**
     * Get Telnyx AI Assistant ID for a tenant
     * Can be configured per tenant or use a global default
     */
    private String getTelnyxAIAssistantId(String tenantId) {
        // TODO: Implement tenant-specific AI assistant lookup
        // For now, return default or from env variable
        String defaultAssistantId = System.getenv("TELNYX_AI_ASSISTANT_ID");
        return defaultAssistantId != null ? defaultAssistantId : "default-assistant";
    }
}
