"""Type definitions for the PriceToken SDK."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Literal

ModelStatus = Literal["active", "deprecated", "preview"]
DataConfidence = Literal["high", "low"]
Source = Literal["fetched", "seed", "admin", "verified"]


@dataclass(slots=True)
class ModelPricing:
    model_id: str
    provider: str
    display_name: str
    input_per_m_tok: float
    output_per_m_tok: float
    context_window: int | None
    max_output_tokens: int | None
    source: Source
    status: ModelStatus | None
    confidence: DataConfidence
    last_updated: str | None
    launch_date: str | None


@dataclass(slots=True)
class CostEstimate:
    model_id: str
    input_tokens: int
    output_tokens: int
    input_cost: float
    output_cost: float
    total_cost: float


@dataclass(slots=True)
class PriceHistoryPoint:
    date: str
    input_per_m_tok: float
    output_per_m_tok: float


@dataclass(slots=True)
class ModelHistory:
    model_id: str
    provider: str
    display_name: str
    history: list[PriceHistoryPoint]


@dataclass(slots=True)
class ProviderSummary:
    id: str
    display_name: str
    model_count: int
    cheapest_input_per_m_tok: float
    cheapest_output_per_m_tok: float


class PriceTokenError(Exception):
    """Raised when the PriceToken API returns an error."""

    def __init__(self, error: str, status: int) -> None:
        super().__init__(error)
        self.error = error
        self.status = status


def _parse_model_pricing(data: dict[str, Any]) -> ModelPricing:
    return ModelPricing(
        model_id=data["modelId"],
        provider=data["provider"],
        display_name=data["displayName"],
        input_per_m_tok=data["inputPerMTok"],
        output_per_m_tok=data["outputPerMTok"],
        context_window=data.get("contextWindow"),
        max_output_tokens=data.get("maxOutputTokens"),
        source=data["source"],
        status=data.get("status"),
        confidence=data["confidence"],
        last_updated=data.get("lastUpdated"),
        launch_date=data.get("launchDate"),
    )


def _parse_history_point(data: dict[str, Any]) -> PriceHistoryPoint:
    return PriceHistoryPoint(
        date=data["date"],
        input_per_m_tok=data["inputPerMTok"],
        output_per_m_tok=data["outputPerMTok"],
    )


def _parse_model_history(data: dict[str, Any]) -> ModelHistory:
    return ModelHistory(
        model_id=data["modelId"],
        provider=data["provider"],
        display_name=data["displayName"],
        history=[_parse_history_point(p) for p in data["history"]],
    )


def _parse_provider_summary(data: dict[str, Any]) -> ProviderSummary:
    return ProviderSummary(
        id=data["id"],
        display_name=data["displayName"],
        model_count=data["modelCount"],
        cheapest_input_per_m_tok=data["cheapestInputPerMTok"],
        cheapest_output_per_m_tok=data["cheapestOutputPerMTok"],
    )


# ---------------------------------------------------------------------------
# Image pricing types
# ---------------------------------------------------------------------------

ImageQualityTier = Literal["standard", "hd", "ultra"]


@dataclass(slots=True)
class ImageModelPricing:
    model_id: str
    provider: str
    display_name: str
    price_per_image: float
    price_per_megapixel: float | None
    default_resolution: str
    quality_tier: ImageQualityTier
    max_resolution: str | None
    supported_formats: list[str]
    source: Source
    status: ModelStatus | None
    confidence: DataConfidence
    last_updated: str | None
    launch_date: str | None


@dataclass(slots=True)
class ImageCostEstimate:
    model_id: str
    image_count: int
    price_per_image: float
    total_cost: float


@dataclass(slots=True)
class ImagePriceHistoryPoint:
    date: str
    price_per_image: float


@dataclass(slots=True)
class ImageModelHistory:
    model_id: str
    provider: str
    display_name: str
    history: list[ImagePriceHistoryPoint]


@dataclass(slots=True)
class ImageProviderSummary:
    id: str
    display_name: str
    model_count: int
    cheapest_per_image: float


def _parse_image_model_pricing(data: dict[str, Any]) -> ImageModelPricing:
    return ImageModelPricing(
        model_id=data["modelId"],
        provider=data["provider"],
        display_name=data["displayName"],
        price_per_image=data["pricePerImage"],
        price_per_megapixel=data.get("pricePerMegapixel"),
        default_resolution=data["defaultResolution"],
        quality_tier=data["qualityTier"],
        max_resolution=data.get("maxResolution"),
        supported_formats=data.get("supportedFormats", ["png"]),
        source=data["source"],
        status=data.get("status"),
        confidence=data["confidence"],
        last_updated=data.get("lastUpdated"),
        launch_date=data.get("launchDate"),
    )


def _parse_image_history_point(data: dict[str, Any]) -> ImagePriceHistoryPoint:
    return ImagePriceHistoryPoint(date=data["date"], price_per_image=data["pricePerImage"])


def _parse_image_model_history(data: dict[str, Any]) -> ImageModelHistory:
    return ImageModelHistory(
        model_id=data["modelId"],
        provider=data["provider"],
        display_name=data["displayName"],
        history=[_parse_image_history_point(p) for p in data["history"]],
    )


def _parse_image_provider_summary(data: dict[str, Any]) -> ImageProviderSummary:
    return ImageProviderSummary(
        id=data["id"],
        display_name=data["displayName"],
        model_count=data["modelCount"],
        cheapest_per_image=data["cheapestPerImage"],
    )


# ---------------------------------------------------------------------------
# Video pricing types
# ---------------------------------------------------------------------------


@dataclass(slots=True)
class VideoModelPricing:
    model_id: str
    provider: str
    display_name: str
    cost_per_minute: float
    resolution: str | None
    max_duration: int | None
    quality_mode: str | None
    source: Source
    status: ModelStatus | None
    confidence: DataConfidence
    last_updated: str | None
    launch_date: str | None


@dataclass(slots=True)
class VideoCostEstimate:
    model_id: str
    duration_seconds: float
    cost_per_minute: float
    total_cost: float


@dataclass(slots=True)
class VideoPriceHistoryPoint:
    date: str
    cost_per_minute: float


@dataclass(slots=True)
class VideoModelHistory:
    model_id: str
    provider: str
    display_name: str
    history: list[VideoPriceHistoryPoint]


@dataclass(slots=True)
class VideoProviderSummary:
    id: str
    display_name: str
    model_count: int
    cheapest_cost_per_minute: float


def _parse_video_model_pricing(data: dict[str, Any]) -> VideoModelPricing:
    return VideoModelPricing(
        model_id=data["modelId"],
        provider=data["provider"],
        display_name=data["displayName"],
        cost_per_minute=data["costPerMinute"],
        resolution=data.get("resolution"),
        max_duration=data.get("maxDuration"),
        quality_mode=data.get("qualityMode"),
        source=data["source"],
        status=data.get("status"),
        confidence=data["confidence"],
        last_updated=data.get("lastUpdated"),
        launch_date=data.get("launchDate"),
    )


def _parse_video_history_point(data: dict[str, Any]) -> VideoPriceHistoryPoint:
    return VideoPriceHistoryPoint(
        date=data["date"],
        cost_per_minute=data["costPerMinute"],
    )


def _parse_video_model_history(data: dict[str, Any]) -> VideoModelHistory:
    return VideoModelHistory(
        model_id=data["modelId"],
        provider=data["provider"],
        display_name=data["displayName"],
        history=[_parse_video_history_point(p) for p in data["history"]],
    )


def _parse_video_provider_summary(data: dict[str, Any]) -> VideoProviderSummary:
    return VideoProviderSummary(
        id=data["id"],
        display_name=data["displayName"],
        model_count=data["modelCount"],
        cheapest_cost_per_minute=data["cheapestCostPerMinute"],
    )
