"""Data models for monitoring database records.

Plain dataclasses that map to the monitoring.* PostgreSQL tables.
Used for type-safe construction before insertion — not an ORM.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from decimal import Decimal
from typing import Any
from uuid import uuid4


def _now() -> datetime:
    return datetime.now(timezone.utc)


def _uuid() -> str:
    return str(uuid4())


# ── Trace ─────────────────────────────────────────────────────


@dataclass
class TraceRecord:
    """Maps to monitoring.traces."""

    trace_id: str = field(default_factory=_uuid)
    root_span_id: str | None = None

    service_name: str = "default"
    environment: str = "development"
    tags: dict[str, Any] = field(default_factory=dict)

    entry_input: str | None = None
    final_output: str | None = None
    total_duration_ms: int | None = None
    total_cost: Decimal | None = None
    total_input_tokens: int = 0
    total_output_tokens: int = 0
    total_tokens: int = 0
    span_count: int = 0

    status: str = "in_progress"
    error_message: str | None = None

    created_at: datetime = field(default_factory=_now)
    updated_at: datetime = field(default_factory=_now)


# ── Span ──────────────────────────────────────────────────────


@dataclass
class SpanRecord:
    """Maps to monitoring.spans."""

    span_id: str = field(default_factory=_uuid)
    trace_id: str = ""
    parent_span_id: str | None = None

    span_type: str = ""  # 'agent' | 'llm' | 'tool'
    component_class: str = ""
    component_name: str = ""
    model: str | None = None
    provider: str | None = None

    sequence_number: int = 0

    started_at: datetime = field(default_factory=_now)
    ended_at: datetime | None = None
    duration_ms: int | None = None

    status: str = "in_progress"
    error_message: str | None = None
    depth: int = 0


# ── LLM Call Details ──────────────────────────────────────────


@dataclass
class LLMCallDetailRecord:
    """Maps to monitoring.llm_call_details."""

    span_id: str = ""

    model: str = ""
    provider: str = ""
    api_type: str | None = None

    input_messages: list[dict[str, Any]] | None = None
    input_message_count: int = 0
    system_prompt: str | None = None

    output_text: str | None = None
    output_content: list[dict[str, Any]] | None = None
    reasoning_text: str | None = None
    stop_reason: str | None = None

    input_tokens: int = 0
    output_tokens: int = 0
    reasoning_tokens: int | None = None
    cached_tokens: int | None = None
    total_tokens: int = 0

    input_cost: Decimal | None = None
    output_cost: Decimal | None = None
    reasoning_cost: Decimal | None = None
    cached_cost: Decimal | None = None
    total_cost: Decimal | None = None

    temperature: float | None = None
    max_output_tokens: int | None = None
    top_p: float | None = None
    reasoning_enabled: bool = False
    reasoning_effort: str | None = None
    streaming: bool = False

    response_id: str | None = None
    config_snapshot: dict[str, Any] | None = None
    raw_response: dict[str, Any] | None = None
    tool_names: list[dict[str, Any]] | None = None


# ── Agent Call Details ────────────────────────────────────────


@dataclass
class AgentCallDetailRecord:
    """Maps to monitoring.agent_call_details."""

    span_id: str = ""

    agent_class: str = ""
    agent_name: str = ""

    system_prompt: str | None = None
    user_prompt_template: str | None = None

    input_messages: list[dict[str, Any]] | None = None
    input_message_count: int = 0
    output_text: str | None = None
    output_content: list[dict[str, Any]] | None = None
    context: dict[str, Any] | None = None

    tool_count: int = 0
    tool_names: list[dict[str, Any]] | None = None
    sub_agent_count: int = 0
    iteration_count: int = 0
    total_llm_calls: int = 0

    config_snapshot: dict[str, Any] | None = None
    tool_interactions: list[dict[str, Any]] | None = None


# ── Tool Call Details ─────────────────────────────────────────


@dataclass
class ToolCallDetailRecord:
    """Maps to monitoring.tool_call_details."""

    id: str = field(default_factory=_uuid)
    span_id: str = ""

    tool_call_id: str = ""
    tool_name: str = ""
    tool_type: str = "function"

    arguments: dict[str, Any] | None = None
    result_content: str | None = None
    is_error: bool = False

    started_at: datetime | None = None
    ended_at: datetime | None = None
    duration_ms: int | None = None

    iteration_number: int = 1
    sequence_in_batch: int = 0


# ── Usage Hourly Rollup ──────────────────────────────────────


@dataclass
class UsageHourlyRollupRecord:
    """Maps to monitoring.usage_hourly_rollup."""

    hour_bucket: datetime = field(default_factory=_now)

    component_type: str = ""
    component_class: str = ""
    component_name: str = ""
    model: str | None = None
    provider: str | None = None
    service_name: str = "default"
    environment: str = "development"

    request_count: int = 0
    total_input_tokens: int = 0
    total_output_tokens: int = 0
    total_reasoning_tokens: int = 0
    total_tokens: int = 0
    total_cost: Decimal = Decimal("0")
    avg_duration_ms: float | None = None
    min_duration_ms: int | None = None
    max_duration_ms: int | None = None
    error_count: int = 0
