package com.saas.voip.service;

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

import java.util.Optional;

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

    private final TelnyxCallControlService telnyxCallControl;
    private final VapiService vapiService;
    private final TenantAIConfigService aiConfigService;

    /**
     * Bridge Telnyx call to Vapi AI assistant
     * 
     * @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 bridgeTelnyxCallToVapi(
            String callControlId,
            String tenantId,
            String fromNumber,
            String toNumber) {
        log.info("🔗 Bridging Telnyx call {} to Vapi 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 Vapi is configured
            if (config.getVapiAssistantId() == null) {
                log.warn("⚠️ No Vapi assistant configured for tenant: {}", tenantId);
                handleNoConfig(callControlId);
                return;
            }

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

            // 3. Determine bridging method
            String vapiPhoneNumber = config.getVapiPhoneNumber();

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

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

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

    /**
     * Bridge via Vapi outbound call
     * 
     * This method initiates a Vapi outbound call to the original caller
     */
    private void bridgeViaVapiOutbound(
            String callControlId,
            TenantAIConfig config,
            String fromNumber,
            String toNumber) {
        // Create Vapi call request
        StartVapiCallDTO vapiCallRequest = StartVapiCallDTO.builder()
                .assistantId(config.getVapiAssistantId())
                .customerNumber(fromNumber)
                .phoneNumberId(config.getVapiPhoneNumberId())
                .build();

        // Start Vapi call
        VapiCallDTO vapiCall = vapiService.startCall(config.getTenantId(), vapiCallRequest);

        log.info("📞 Vapi call initiated: {}", vapiCall.getVapiCallId());

        // Note: In production, you would need to:
        // 1. Get Vapi's SIP URI or phone number from the call response
        // 2. Bridge Telnyx call to that endpoint
        //
        // For now, we rely on Vapi'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);
        }
    }
}
