package com.saas.voip.service;

import com.saas.admin.entity.TenantAIConfig;
import com.saas.tenant.service.TenantAIConfigService;
import com.saas.voip.dto.CallResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * Retell Call Bridge Service
 * 
 * Bridges incoming Telnyx calls to Retell AI agents
 * 
 * Flow:
 * 1. Receive Telnyx webhook with call_control_id
 * 2. Get tenant AI config
 * 3. Answer the Telnyx call
 * 4. Transfer/bridge to Retell phone number or SIP
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class RetellCallBridgeService {

    private final TelnyxCallControlService telnyxCallControl;
    private final RetellApiClient retellApiClient;
    private final TenantAIConfigService aiConfigService;

    /**
     * Bridge Telnyx call to Retell AI agent
     * 
     * @param callControlId Telnyx call control ID
     * @param tenantId      Tenant identifier
     * @param fromNumber    Caller phone number
     * @param toNumber      Called phone number (tenant's number)
     */
    public void bridgeTelnyxCallToRetell(
            String callControlId,
            String tenantId,
            String fromNumber,
            String toNumber) {
        log.info("🔗 Bridging Telnyx call {} to Retell for tenant: {}", callControlId, tenantId);

        try {
            // 1. Get AI configuration
            Optional<TenantAIConfig> configOpt = aiConfigService.getConfigForTenant(tenantId);

            if (configOpt.isEmpty()) {
                log.warn("⚠️ No AI config found for tenant: {}", tenantId);
                handleNoConfig(callControlId);
                return;
            }

            TenantAIConfig config = configOpt.get();

            // Verify Retell is configured
            if (config.getRetellAgentId() == null) {
                log.warn("⚠️ No Retell agent configured for tenant: {}", tenantId);
                handleNoConfig(callControlId);
                return;
            }

            // 2. Answer the Telnyx call first
            telnyxCallControl.answerCall(callControlId);

            // 3. Determine bridging method
            String retellPhoneNumber = config.getRetellPhoneNumber();

            if (retellPhoneNumber != null && !retellPhoneNumber.isEmpty()) {
                // Method 1: Transfer to Retell's phone number
                log.info("📞 Transferring to Retell phone number: {}", retellPhoneNumber);
                telnyxCallControl.transferCall(callControlId, retellPhoneNumber);
            } else {
                // Method 2: Initiate Retell outbound call and bridge
                log.info("🚀 Initiating Retell outbound call to bridge");
                bridgeViaRetellOutbound(callControlId, config, fromNumber, toNumber);
            }

            log.info("✅ Successfully bridged Telnyx → Retell");

        } catch (Exception e) {
            log.error("❌ Failed to bridge Telnyx call to Retell", e);
            handleBridgeFailure(callControlId, e);
        }
    }

    /**
     * Bridge via Retell outbound call
     * 
     * This method:
     * 1. Initiates a Retell outbound call to the original caller
     * 2. Bridges the Telnyx call to Retell's SIP endpoint
     */
    private void bridgeViaRetellOutbound(
            String callControlId,
            TenantAIConfig config,
            String fromNumber,
            String toNumber) {
        // Prepare metadata for Retell
        Map<String, Object> metadata = new HashMap<>();
        metadata.put("telnyx_call_control_id", callControlId);
        metadata.put("tenant_id", config.getTenantId());
        metadata.put("original_from", fromNumber);
        metadata.put("original_to", toNumber);

        // Prepare dynamic variables for LLM context
        Map<String, Object> dynamicVariables = new HashMap<>();
        dynamicVariables.put("caller_number", fromNumber);
        dynamicVariables.put("called_number", toNumber);

        // Initiate Retell call
        CallResponse retellCall = retellApiClient.initiateCall(
                toNumber, // from_number (tenant's number)
                fromNumber, // to_number (caller's number)
                config.getRetellAgentId(),
                metadata,
                dynamicVariables);

        log.info("📞 Retell call initiated: {}", retellCall.getCallId());

        // Note: In production, you would need to:
        // 1. Get Retell's SIP URI from their API response
        // 2. Bridge Telnyx call to that SIP URI
        //
        // For now, we rely on Retell's phone number method
    }

    /**
     * Handle case where no AI config is found
     */
    private void handleNoConfig(String callControlId) {
        log.warn("⚠️ No AI configuration - playing message and hanging up");

        try {
            // Play a message to the caller
            telnyxCallControl.speak(
                    callControlId,
                    "Désolé, ce service n'est pas disponible pour le moment. Veuillez réessayer plus tard.",
                    "female",
                    "fr-FR");

            // Wait a bit then hangup
            Thread.sleep(3000);
            telnyxCallControl.hangupCall(callControlId);

        } catch (Exception e) {
            log.error("Error handling no-config scenario", e);
        }
    }

    /**
     * Handle bridge failure
     */
    private void handleBridgeFailure(String callControlId, Exception error) {
        log.error("⚠️ Bridge failure - attempting fallback", error);

        try {
            // Play error message
            telnyxCallControl.speak(
                    callControlId,
                    "Nous rencontrons un problème technique. Veuillez réessayer dans quelques instants.",
                    "female",
                    "fr-FR");

            // Hangup
            Thread.sleep(3000);
            telnyxCallControl.hangupCall(callControlId);

        } catch (Exception e) {
            log.error("Error handling bridge failure", e);
        }
    }
}
