package com.saas.voip.service.ai;

import com.saas.shared.dto.AiCostCalculationResult;
import com.saas.shared.service.ai.AiCostCalculator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

/**
 * OpenAI Realtime API Cost Calculator
 * 
 * Pricing (as of Oct 2024 - gpt-4o-realtime-preview):
 * - Input audio tokens:  $5.00 per 1M tokens  ($0.000005 per token)
 * - Output audio tokens: $20.00 per 1M tokens ($0.000020 per token)
 * 
 * Source: https://openai.com/api/pricing/
 * 
 * Token Calculation:
 * - Audio tokens are based on duration and sample rate
 * - Typical: ~75 tokens per second of audio
 * - Usage data comes from OpenAI API response headers or events
 * 
 * Clean Architecture:
 * - Implements AiCostCalculator interface
 * - Single Responsibility: Calculate OpenAI Realtime API costs
 * - No persistence logic (handled by AiCostTrackingService)
 */
@Service
@Slf4j
public class OpenAiRealtimeCostCalculator implements AiCostCalculator {
    
    // Pricing per token (USD)
    private static final BigDecimal INPUT_AUDIO_TOKEN_PRICE = new BigDecimal("0.000005");  // $5/1M
    private static final BigDecimal OUTPUT_AUDIO_TOKEN_PRICE = new BigDecimal("0.000020"); // $20/1M
    
    private static final String PROVIDER_NAME = "OPENAI";
    private static final String COST_TYPE = "REALTIME_API";
    
    @Override
    public AiCostCalculationResult calculateCost(Map<String, Object> usageMetrics) {
        log.debug("💰 [OpenAI] Calculating cost from usage metrics: {}", usageMetrics);
        
        if (usageMetrics == null || usageMetrics.isEmpty()) {
            log.warn("⚠️ [OpenAI] Empty usage metrics provided");
            return createZeroCostResult();
        }
        
        try {
            // Extract usage data
            long inputAudioTokens = extractLong(usageMetrics, "input_audio_tokens");
            long outputAudioTokens = extractLong(usageMetrics, "output_audio_tokens");
            
            log.info("💰 [OpenAI] Usage - Input: {} tokens, Output: {} tokens", 
                    inputAudioTokens, outputAudioTokens);
            
            // Calculate costs
            BigDecimal inputCost = BigDecimal.valueOf(inputAudioTokens)
                    .multiply(INPUT_AUDIO_TOKEN_PRICE)
                    .setScale(6, RoundingMode.HALF_UP);
            
            BigDecimal outputCost = BigDecimal.valueOf(outputAudioTokens)
                    .multiply(OUTPUT_AUDIO_TOKEN_PRICE)
                    .setScale(6, RoundingMode.HALF_UP);
            
            BigDecimal totalCost = inputCost.add(outputCost);
            
            log.info("💰 [OpenAI] Cost breakdown - Input: ${}, Output: ${}, Total: ${}", 
                    inputCost, outputCost, totalCost);
            
            // Build detailed usage map
            Map<String, Object> detailedUsage = new HashMap<>();
            detailedUsage.put("input_audio_tokens", inputAudioTokens);
            detailedUsage.put("output_audio_tokens", outputAudioTokens);
            detailedUsage.put("input_cost", inputCost);
            detailedUsage.put("output_cost", outputCost);
            detailedUsage.put("model", usageMetrics.getOrDefault("model", "gpt-4o-realtime-preview"));
            
            // Add optional metadata
            Map<String, Object> metadata = new HashMap<>();
            if (usageMetrics.containsKey("session_id")) {
                metadata.put("session_id", usageMetrics.get("session_id"));
            }
            if (usageMetrics.containsKey("conversation_id")) {
                metadata.put("conversation_id", usageMetrics.get("conversation_id"));
            }
            
            return AiCostCalculationResult.builder()
                    .aiProvider(PROVIDER_NAME)
                    .costType(COST_TYPE)
                    .cost(totalCost)
                    .currency("USD")
                    .usageDetails(detailedUsage)
                    .metadata(metadata.isEmpty() ? null : metadata)
                    .build();
            
        } catch (Exception e) {
            log.error("❌ [OpenAI] Error calculating cost", e);
            return createZeroCostResult();
        }
    }
    
    @Override
    public String getProviderName() {
        return PROVIDER_NAME;
    }
    
    @Override
    public String[] getSupportedCostTypes() {
        return new String[]{COST_TYPE};
    }
    
    /**
     * Extract long value from usage metrics
     * Supports both Integer and Long types
     */
    private long extractLong(Map<String, Object> metrics, String key) {
        Object value = metrics.get(key);
        if (value == null) {
            return 0L;
        }
        if (value instanceof Integer) {
            return ((Integer) value).longValue();
        }
        if (value instanceof Long) {
            return (Long) value;
        }
        if (value instanceof String) {
            try {
                return Long.parseLong((String) value);
            } catch (NumberFormatException e) {
                log.warn("⚠️ [OpenAI] Cannot parse {} as long: {}", key, value);
                return 0L;
            }
        }
        log.warn("⚠️ [OpenAI] Unexpected type for {}: {}", key, value.getClass());
        return 0L;
    }
    
    /**
     * Create a zero-cost result for error cases
     */
    private AiCostCalculationResult createZeroCostResult() {
        return AiCostCalculationResult.builder()
                .aiProvider(PROVIDER_NAME)
                .costType(COST_TYPE)
                .cost(BigDecimal.ZERO)
                .currency("USD")
                .usageDetails(new HashMap<>())
                .build();
    }
}
