package com.saas.admin.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * AI API Cost Record - Stores costs from AI providers (OpenAI, ElevenLabs, Gemini, etc.)
 * 
 * Clean Architecture:
 * - Stored ONLY in admin database (saas_db) for centralized cost tracking
 * - Separate from VoIP call costs (CallCostRecord) following Single Responsibility Principle
 * - Linked to calls via call_sid for cost consolidation
 * 
 * Design Rationale:
 * - VoIP costs (Twilio/Telnyx) vs AI costs (OpenAI/ElevenLabs) are different domains
 * - Separation allows independent evolution of cost tracking for each domain
 * - Enables granular cost analysis per AI provider and cost type
 */
@Entity(name = "AdminAiApiCostRecord")
@Table(name = "ai_api_cost_records", 
       indexes = {
           @Index(name = "idx_ai_cost_call_sid", columnList = "call_sid"),
           @Index(name = "idx_ai_cost_provider", columnList = "ai_provider"),
           @Index(name = "idx_ai_cost_tenant", columnList = "tenant_id"),
           @Index(name = "idx_ai_cost_created_at", columnList = "created_at")
       })
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AiApiCostRecord {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    /**
     * Call SID - Links to InboundCallData for cost consolidation
     * Multiple AI cost records can exist per call (e.g., OpenAI + ElevenLabs)
     */
    @Column(name = "call_sid", nullable = false, length = 200)
    private String callSid;
    
    /**
     * Tenant ID for multi-tenant cost filtering
     */
    @Column(name = "tenant_id", nullable = false, length = 100)
    private String tenantId;
    
    /**
     * AI Provider: OPENAI, ELEVENLABS, GEMINI, ANTHROPIC, etc.
     */
    @Column(name = "ai_provider", nullable = false, length = 50)
    private String aiProvider;
    
    /**
     * Cost Type: REALTIME_API, TTS, STT, LLM, COMPLETION, etc.
     * Allows granular cost breakdown per API type
     */
    @Column(name = "cost_type", nullable = false, length = 50)
    private String costType;
    
    /**
     * Total cost for this AI API usage
     */
    @Column(name = "cost", precision = 10, scale = 6, nullable = false)
    private BigDecimal cost;
    
    /**
     * Currency (default: USD)
     */
    @Column(name = "currency", length = 3, nullable = false)
    @Builder.Default
    private String currency = "USD";
    
    /**
     * Usage details in JSON format
     * 
     * Examples:
     * OpenAI Realtime: {"input_audio_tokens": 12500, "output_audio_tokens": 8300, "model": "gpt-4o-realtime"}
     * ElevenLabs TTS: {"characters": 1250, "model": "eleven_turbo_v2"}
     * Gemini: {"input_tokens": 5000, "output_tokens": 2000, "model": "gemini-2.0-flash"}
     */
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "usage_details", columnDefinition = "JSON")
    private Map<String, Object> usageDetails;
    
    /**
     * Call timing for cost analysis
     */
    @Column(name = "call_start_time")
    private LocalDateTime callStartTime;
    
    @Column(name = "call_end_time")
    private LocalDateTime callEndTime;
    
    /**
     * Call duration in seconds
     */
    @Column(name = "call_duration_seconds")
    private Integer callDurationSeconds;
    
    /**
     * Phone numbers for reference
     */
    @Column(name = "from_number", length = 50)
    private String fromNumber;
    
    @Column(name = "to_number", length = 50)
    private String toNumber;
    
    /**
     * API request/response metadata (optional)
     * Can store: request_id, model version, latency, error details
     */
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "metadata", columnDefinition = "JSON")
    private Map<String, Object> metadata;
    
    /**
     * Timestamps
     */
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
}
