package com.saas.voip.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.saas.tenant.entity.CallCostRecord;
import com.saas.tenant.service.CallCostTrackingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

@Service
@RequiredArgsConstructor
@Slf4j
public class TelnyxCostService {
    
    @Value("${telnyx.api.key:}")
    private String telnyxApiKey;
    
    private final CallCostTrackingService callCostTrackingService;
    private final ObjectMapper objectMapper;
    private final RestTemplate restTemplate = new RestTemplate();
    
    /**
     * Fetch call cost from Telnyx API and save to admin database (saas_db).
     * Uses Telnyx Detail Records API to retrieve pricing information.
     * 
     * @param callSessionId Telnyx Call Session ID
     * @param fromNumber Caller phone number
     * @param toNumber Called phone number
     * @param tenantSchemaName Tenant schema name (for reference)
     */
    public void fetchAndSaveCallCost(String callSessionId, String fromNumber, String toNumber, String tenantSchemaName) {
        log.info("🚀 [TelnyxCostService] fetchAndSaveCallCost() CALLED - SessionId: {}, From: {}, To: {}, Tenant: {}", 
            callSessionId, fromNumber, toNumber, tenantSchemaName);
        
        if (telnyxApiKey == null || telnyxApiKey.isEmpty()) {
            log.error("❌ [TelnyxCostService] Telnyx API Key not configured - CANNOT fetch call cost!");
            log.error("❌ [TelnyxCostService] Please set telnyx.api.key in application properties");
            return;
        }
        
        log.info("✅ [TelnyxCostService] Telnyx API Key configured");
        
        try {
            // Telnyx Detail Records API endpoint
            // Note: Detail records are available a few minutes after call ends
            String url = String.format(
                "https://api.telnyx.com/v2/detail_records?filter[call_session_id]=%s",
                callSessionId
            );
            
            // Create Bearer Auth header
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer " + telnyxApiKey);
            headers.set("Accept", "application/json");
            
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            log.info("🔍 [TelnyxCostService] Calling Telnyx Detail Records API: {}", url);
            
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
            
            log.info("📡 [TelnyxCostService] Telnyx API response status: {}", response.getStatusCode());
            
            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("📄 [TelnyxCostService] Telnyx API response body: {}", response.getBody());
                
                JsonNode root = objectMapper.readTree(response.getBody());
                JsonNode data = root.get("data");
                
                if (data != null && data.isArray() && data.size() > 0) {
                    JsonNode record = data.get(0);
                    
                    // Extract cost information
                    String cost = record.has("cost") ? record.get("cost").asText() : null;
                    String duration = record.has("duration") ? record.get("duration").asText() : null;
                    String startTime = record.has("start_time") ? record.get("start_time").asText() : null;
                    String endTime = record.has("end_time") ? record.get("end_time").asText() : null;
                    
                    log.info("💰 [TelnyxCostService] Parsed data - Cost: {} USD, Duration: {}s", cost, duration);
                    
                    if (cost != null && !cost.isEmpty()) {
                        saveCallCost(callSessionId, cost, duration, startTime, endTime, fromNumber, toNumber, tenantSchemaName);
                    } else {
                        log.warn("⚠️ [TelnyxCostService] No cost data available in Telnyx API response");
                    }
                } else {
                    log.warn("⚠️ [TelnyxCostService] No detail records found for call session: {}", callSessionId);
                    log.warn("⚠️ [TelnyxCostService] Call detail records may not be available yet (wait a few minutes after call ends)");
                }
            } else {
                log.error("❌ [TelnyxCostService] Failed to fetch - HTTP Status: {}, Body: {}", 
                    response.getStatusCode(), response.getBody());
            }
            
        } catch (Exception e) {
            log.error("❌ [TelnyxCostService] EXCEPTION while fetching call cost for SessionId: {}", callSessionId, e);
            log.error("❌ [TelnyxCostService] Exception message: {}", e.getMessage());
            log.error("❌ [TelnyxCostService] Exception class: {}", e.getClass().getName());
        }
    }
    
    private void saveCallCost(String callSessionId, String costStr, String durationStr, 
                             String startTimeStr, String endTimeStr, String from, String to, String tenantSchemaName) {
        try {
            log.info("💾 [TelnyxCostService] Calling callCostTrackingService.saveCallCost()...");
            
            CallCostRecord record = new CallCostRecord();
            record.setProvider("TELNYX");
            record.setCallSid(callSessionId);
            record.setFromNumber(from);
            record.setToNumber(to);
            
            // Parse cost (Telnyx uses negative values for outbound calls)
            if (costStr != null && !costStr.isEmpty()) {
                try {
                    BigDecimal cost = new BigDecimal(costStr).abs(); // Use absolute value
                    record.setCost(cost);
                    record.setCurrency("USD"); // Telnyx uses USD
                    log.info("💵 [TelnyxCostService] Cost set: {} USD", cost);
                } catch (NumberFormatException e) {
                    log.error("❌ [TelnyxCostService] Failed to parse cost: {}", costStr, e);
                }
            }
            
            // Parse duration
            if (durationStr != null && !durationStr.isEmpty()) {
                try {
                    Integer duration = Integer.parseInt(durationStr);
                    record.setCallDurationSeconds(duration);
                    log.info("⏱️ [TelnyxCostService] Duration set: {} seconds", duration);
                } catch (NumberFormatException e) {
                    log.error("❌ [TelnyxCostService] Failed to parse duration: {}", durationStr, e);
                }
            }
            
            // Parse timestamps (Telnyx uses ISO 8601 format)
            DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
            
            if (startTimeStr != null && !startTimeStr.isEmpty()) {
                try {
                    LocalDateTime startTime = ZonedDateTime.parse(startTimeStr, formatter).toLocalDateTime();
                    record.setCallStartTime(startTime);
                    log.info("🕐 [TelnyxCostService] Start time set: {}", startTime);
                } catch (Exception e) {
                    log.warn("⚠️ [TelnyxCostService] Failed to parse start time: {}", startTimeStr);
                }
            }
            
            if (endTimeStr != null && !endTimeStr.isEmpty()) {
                try {
                    LocalDateTime endTime = ZonedDateTime.parse(endTimeStr, formatter).toLocalDateTime();
                    record.setCallEndTime(endTime);
                    log.info("🕑 [TelnyxCostService] End time set: {}", endTime);
                } catch (Exception e) {
                    log.warn("⚠️ [TelnyxCostService] Failed to parse end time: {}", endTimeStr);
                }
            }
            
            log.info("🎯 [TelnyxCostService] Setting TenantContext to saas_db for ADMIN database save");
            // CRITICAL: Set TenantContext to saas_db to save costs in ADMIN database ONLY
            com.saas.shared.core.TenantContext.setTenantId("saas_db");
            
            try {
                // Save to admin database (saas_db)
                callCostTrackingService.saveCallCost(record);
                log.info("✅ [TelnyxCostService] Telnyx call cost saved to ADMIN database (saas_db)!");
            } finally {
                com.saas.shared.core.TenantContext.clear();
                log.info("🧹 [TelnyxCostService] TenantContext cleared");
            }
            
        } catch (Exception e) {
            log.error("❌ [TelnyxCostService] EXCEPTION while saving call cost!", e);
            log.error("❌ [TelnyxCostService] Exception type: {}, Message: {}", 
                e.getClass().getName(), e.getMessage());
        }
    }
}
