package com.saas.voip.service;

import com.saas.shared.service.EventPublisherService;
import com.saas.voip.dto.CallRequest;
import com.saas.voip.dto.CallResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * VoIP Orchestration Service
 * 
 * Phase 3.1 - Centralized VoIP orchestration layer
 * 
 * Responsibilities:
 * - Route calls to appropriate VoIP provider (Vapi, Retell, Twilio, Telnyx)
 * - Abstract provider-specific logic from controllers
 * - Publish VoIP events to Kafka for event-driven processing
 * - Coordinate multi-provider workflows
 * - Standardize call lifecycle management
 * 
 * Benefits:
 * - Single entry point for all VoIP operations
 * - Controllers become thin (delegation only)
 * - Easy to add new providers
 * - Consistent error handling and logging
 * - Event-driven architecture integration
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class VoIPOrchestrationService {
    
    private final VapiService vapiService;
    private final RetellApiClient retellApiClient;
    private final EventPublisherService eventPublisher;
    
    /**
     * Initiate outbound call using Vapi.ai
     * 
     * @param request Call request with assistant ID and phone number
     * @return Call response with call ID and status
     */
    public CallResponse initiateVapiCall(CallRequest request) {
        log.info("🚀 Orchestrating Vapi outbound call to: {}", request.getPhoneNumber());
        
        try {
            // Build Vapi call DTO
            com.saas.admin.dto.StartVapiCallDTO vapiCallDto = new com.saas.admin.dto.StartVapiCallDTO();
            vapiCallDto.setAssistantId(request.getAssistantId());
            vapiCallDto.setCustomerNumber(request.getPhoneNumber());
            
            // Delegate to Vapi service
            com.saas.admin.dto.VapiCallDTO vapiCall = vapiService.startCall(request.getTenantId(), vapiCallDto);
            
            // Convert to CallResponse
            CallResponse response = CallResponse.builder()
                    .callId(vapiCall.getVapiCallId())
                    .provider("VAPI")
                    .status(vapiCall.getStatus())
                    .phoneNumber(request.getPhoneNumber())
                    .message("Call initiated successfully")
                    .build();
            
            // Publish event for async processing (TODO: Create CallInitiatedEvent)
            log.debug("📤 Call initiated event logged - Call ID: {}", response.getCallId());
            
            log.info("✅ Vapi call initiated - Call ID: {}", response.getCallId());
            return response;
            
        } catch (Exception e) {
            log.error("❌ Failed to initiate Vapi call", e);
            
            // Publish failure event (TODO: Create CallFailedEvent)
            log.error("📤 Call failed event logged - Provider: VAPI, Error: {}", e.getMessage());
            
            throw new RuntimeException("Call initiation failed: " + e.getMessage(), e);
        }
    }
    
    /**
     * Initiate outbound call using Retell AI
     * API V2: POST /v2/create-phone-call
     * 
     * @param request Call request with agent ID, from_number (required), and to_number
     * @return Call response with call ID and status
     */
    public CallResponse initiateRetellCall(CallRequest request) {
        log.info("🚀 Orchestrating Retell AI outbound call - From: {}, To: {}", 
                request.getFromNumber(), request.getPhoneNumber());
        
        // Validate required from_number
        if (request.getFromNumber() == null || request.getFromNumber().isEmpty()) {
            throw new IllegalArgumentException("from_number is required for Retell AI calls (E.164 format)");
        }
        
        try {
            // Phase 4.5: Delegate to Retell API client with V2 parameters
            CallResponse response = retellApiClient.initiateCall(
                    request.getFromNumber(),      // from_number (required)
                    request.getPhoneNumber(),     // to_number (required)
                    request.getAssistantId(),     // override_agent_id (optional)
                    null,                         // metadata
                    request.getDynamicVariables() // retell_llm_dynamic_variables
            );
            
            // Publish event for async processing
            log.debug("📤 Retell call initiated event logged - Call ID: {}", response.getCallId());
            
            log.info("✅ Retell call initiated - Call ID: {}", response.getCallId());
            return response;
            
        } catch (Exception e) {
            log.error("❌ Failed to initiate Retell call", e);
            log.error("📤 Call failed event logged - Provider: RETELL, Error: {}", e.getMessage());
            
            throw new RuntimeException("Call initiation failed: " + e.getMessage(), e);
        }
    }
    
    /**
     * Route call to appropriate provider based on strategy
     * 
     * @param request Call request
     * @param provider Target VoIP provider (VAPI, RETELL, TWILIO, TELNYX)
     * @return Call response
     */
    public CallResponse routeCall(CallRequest request, String provider) {
        log.info("🔀 Routing call to provider: {}", provider);
        
        return switch (provider.toUpperCase()) {
            case "VAPI" -> initiateVapiCall(request);
            case "RETELL" -> initiateRetellCall(request);
            case "TWILIO" -> throw new UnsupportedOperationException("Twilio routing pending");
            case "TELNYX" -> throw new UnsupportedOperationException("Telnyx routing pending");
            default -> throw new IllegalArgumentException("Unknown VoIP provider: " + provider);
        };
    }
    
    /**
     * Get call status from any provider
     * 
     * @param callId Call ID
     * @param provider VoIP provider
     * @return Call status
     */
    public String getCallStatus(String callId, String provider, String tenantId) {
        log.debug("📊 Fetching call status - ID: {}, Provider: {}", callId, provider);
        
        return switch (provider.toUpperCase()) {
            case "VAPI" -> {
                com.saas.admin.dto.VapiCallDTO call = vapiService.getCall(tenantId, callId);
                yield call.getStatus();
            }
            case "RETELL" -> retellApiClient.getCallStatus(callId);
            default -> throw new IllegalArgumentException("Unknown provider: " + provider);
        };
    }
    
    /**
     * Terminate active call
     * 
     * @param callId Call ID
     * @param provider VoIP provider
     */
    public void terminateCall(String callId, String provider) {
        log.warn("🛑 Terminating call - ID: {}, Provider: {}", callId, provider);
        
        switch (provider.toUpperCase()) {
            case "VAPI" -> {
                // Vapi doesn't have call termination API, log warning
                log.warn("⚠️ Vapi.ai doesn't support call termination via API");
                throw new UnsupportedOperationException("Vapi.ai call termination not supported");
            }
            case "RETELL" -> retellApiClient.terminateCall(callId);
            default -> throw new IllegalArgumentException("Unknown provider: " + provider);
        }
        
        // Publish termination event (TODO: Create CallTerminatedEvent)
        log.info("📤 Call terminated event logged - Call ID: {}, Provider: {}", callId, provider);
    }
}
