from pydantic import BaseModel, Field, ConfigDict


class LatchConfig(BaseModel):
    api_key: str
    base_url: str = "https://api.latch.dev"
    timeout: float = 30.0
    mode: str = Field(default="observe", pattern="^(observe|suggest|enforce)$")
    fallback_enabled: bool = True


class Message(BaseModel):
    role: str
    content: str


class DecisionMeta(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    input_tokens: int = Field(alias="inputTokens")
    output_tokens_estimate: int = Field(alias="outputTokensEstimate")
    was_cached: bool = Field(alias="wasCached")
    decision_latency_ms: int = Field(alias="decisionLatencyMs")


class DecisionResponse(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    decision_id: str = Field(alias="decisionId")
    should_call_llm: bool = Field(alias="shouldCallLLM")
    model: str
    context_fraction: float = Field(alias="contextFraction")
    estimated_cost: float = Field(alias="estimatedCost")
    reasoning: str | None = None
    metadata: DecisionMeta


class UsageStats(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    input_tokens: int = Field(alias="inputTokens")
    output_tokens: int = Field(alias="outputTokens")
    total_cost: float = Field(alias="totalCost")


class ExecuteMeta(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    decision_latency_ms: int = Field(alias="decisionLatencyMs")
    llm_latency_ms: int = Field(alias="llmLatencyMs")
    total_latency_ms: int = Field(alias="totalLatencyMs")


class ExecuteResponse(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    decision_id: str = Field(alias="decisionId")
    model: str
    cost: float
    response: Message
    usage: UsageStats
    metadata: ExecuteMeta

    @property
    def content(self) -> str:
        """Get the response content"""
        return self.response.content


class DecisionRequest(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    messages: list[Message]
    task: str
    budget: float | None = None
    max_latency: int | None = Field(default=None, alias="maxLatency")
    metadata: dict | None = None


class ReportRequest(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    decision_id: str = Field(alias="decisionId")
    input_tokens: int = Field(alias="inputTokens")
    output_tokens: int = Field(alias="outputTokens")
    llm_latency_ms: int = Field(alias="llmLatencyMs")
    model: str | None = None
    success: bool = True
    error_message: str | None = Field(default=None, alias="errorMessage")


class ReportResponse(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

    decision_id: str = Field(alias="decisionId")
    actual_cost: float = Field(alias="actualCost")
    total_latency_ms: int = Field(alias="totalLatencyMs")
