package com.saas.voip.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

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

/**
 * Telnyx Call Control Service
 * 
 * Manages call control operations via Telnyx Call Control API
 * - Answer calls
 * - Transfer calls
 * - Bridge calls to SIP URIs
 * - Hangup calls
 * 
 * API Reference: https://developers.telnyx.com/docs/api/v2/call-control
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TelnyxCallControlService {

    private final RestTemplate restTemplate;

    @Value("${telnyx.api.key}")
    private String telnyxApiKey;

    @Value("${telnyx.api.base-url:https://api.telnyx.com}")
    private String telnyxBaseUrl;

    /**
     * Answer an incoming call
     * 
     * @param callControlId Call Control ID from webhook
     */
    public void answerCall(String callControlId) {
        log.info("📞 Answering Telnyx call: {}", callControlId);

        String url = telnyxBaseUrl + "/v2/calls/" + callControlId + "/actions/answer";

        Map<String, Object> payload = new HashMap<>();
        payload.put("client_state", "answered");

        HttpHeaders headers = createHeaders();
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);

        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    request,
                    Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("✅ Telnyx call answered successfully: {}", callControlId);
            } else {
                log.error("❌ Failed to answer Telnyx call. Status: {}", response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("❌ Error answering Telnyx call: {}", callControlId, e);
            throw new RuntimeException("Failed to answer call", e);
        }
    }

    /**
     * Transfer call to another phone number
     * 
     * @param callControlId Call Control ID
     * @param toNumber      Destination phone number (E.164 format)
     */
    public void transferCall(String callControlId, String toNumber) {
        log.info("🔄 Transferring Telnyx call {} to {}", callControlId, toNumber);

        String url = telnyxBaseUrl + "/v2/calls/" + callControlId + "/actions/transfer";

        Map<String, Object> payload = new HashMap<>();
        payload.put("to", toNumber);

        HttpHeaders headers = createHeaders();
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);

        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    request,
                    Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("✅ Telnyx call transferred successfully to: {}", toNumber);
            } else {
                log.error("❌ Failed to transfer Telnyx call. Status: {}", response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("❌ Error transferring Telnyx call", e);
            throw new RuntimeException("Failed to transfer call", e);
        }
    }

    /**
     * Bridge call to SIP URI (for AI assistants)
     * 
     * @param callControlId Call Control ID
     * @param sipUri        SIP URI to bridge to
     */
    public void bridgeCall(String callControlId, String sipUri) {
        log.info("🌉 Bridging Telnyx call {} to SIP: {}", callControlId, sipUri);

        String url = telnyxBaseUrl + "/v2/calls/" + callControlId + "/actions/bridge";

        Map<String, Object> payload = new HashMap<>();
        payload.put("to", sipUri);
        payload.put("from", "sip:telnyx@sip.telnyx.com");

        HttpHeaders headers = createHeaders();
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);

        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    request,
                    Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("✅ Telnyx call bridged successfully to: {}", sipUri);
            } else {
                log.error("❌ Failed to bridge Telnyx call. Status: {}", response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("❌ Error bridging Telnyx call", e);
            throw new RuntimeException("Failed to bridge call", e);
        }
    }

    /**
     * Hangup/terminate a call
     * 
     * @param callControlId Call Control ID
     */
    public void hangupCall(String callControlId) {
        log.info("📴 Hanging up Telnyx call: {}", callControlId);

        String url = telnyxBaseUrl + "/v2/calls/" + callControlId + "/actions/hangup";

        HttpHeaders headers = createHeaders();
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(new HashMap<>(), headers);

        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    request,
                    Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("✅ Telnyx call hung up successfully: {}", callControlId);
            } else {
                log.error("❌ Failed to hangup Telnyx call. Status: {}", response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("❌ Error hanging up Telnyx call", e);
            throw new RuntimeException("Failed to hangup call", e);
        }
    }

    /**
     * Play audio to caller
     * 
     * @param callControlId Call Control ID
     * @param audioUrl      URL of audio file to play
     */
    public void playAudio(String callControlId, String audioUrl) {
        log.info("🔊 Playing audio on Telnyx call {}: {}", callControlId, audioUrl);

        String url = telnyxBaseUrl + "/v2/calls/" + callControlId + "/actions/playback_start";

        Map<String, Object> payload = new HashMap<>();
        payload.put("audio_url", audioUrl);

        HttpHeaders headers = createHeaders();
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);

        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    request,
                    Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("✅ Audio playback started on Telnyx call");
            } else {
                log.error("❌ Failed to play audio. Status: {}", response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("❌ Error playing audio on Telnyx call", e);
            throw new RuntimeException("Failed to play audio", e);
        }
    }

    /**
     * Speak text to caller (TTS)
     * 
     * @param callControlId Call Control ID
     * @param text          Text to speak
     * @param voice         Voice to use (e.g., "female", "male")
     * @param language      Language code (e.g., "fr-FR", "en-US")
     */
    public void speak(String callControlId, String text, String voice, String language) {
        log.info("🗣️ Speaking on Telnyx call {}: {}", callControlId, text);

        String url = telnyxBaseUrl + "/v2/calls/" + callControlId + "/actions/speak";

        Map<String, Object> payload = new HashMap<>();
        payload.put("payload", text);
        payload.put("voice", voice != null ? voice : "female");
        payload.put("language", language != null ? language : "fr-FR");

        HttpHeaders headers = createHeaders();
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);

        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    request,
                    Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("✅ TTS started on Telnyx call");
            } else {
                log.error("❌ Failed to speak. Status: {}", response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("❌ Error speaking on Telnyx call", e);
            throw new RuntimeException("Failed to speak", e);
        }
    }

    /**
     * Create HTTP headers with Telnyx API authentication
     */
    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(telnyxApiKey);
        return headers;
    }
}
