"""Usage tracking models for billing and metrics.

Services report flexible metrics to vikdata. The metric_type is service-defined
and can be anything (api_request, storage_gb_hour, telemetry_points, etc.).

The plan's usage_pricing configuration determines which metrics are billable.
"""

from datetime import datetime
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


class UsageMetric(BaseModel):
    """Single usage metric for billing.

    Services define their own metric types. Examples:
    - fishinfo: 'api_request', 'storage_gb_hour', 'telemetry_points', 'data_egress_mb'
    - ingress: 'core_hour', 'data_ingested_mb', 'requests_processed'

    The metadata field allows additional context for analytics.
    """

    tenant_id: str = Field(description="Tenant ID (UUID as string)")
    metric_type: str = Field(description="Service-defined metric type")
    quantity: float = Field(ge=0, description="Metric quantity")
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    metadata: dict[str, Any] | None = Field(
        default=None,
        description="Additional context (endpoint, method, status_code, etc.)"
    )

    model_config = ConfigDict(from_attributes=True)


class UsageMetrics(BaseModel):
    """Legacy model for backward compatibility - use UsageMetric instead.

    Maps old format to new flexible format.
    """

    tenant_id: str
    service: str
    endpoint: str
    method: str
    count: int = 1
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    latency_ms: float | None = None
    status_code: int | None = None

    model_config = ConfigDict(from_attributes=True)

    def to_usage_metric(self) -> UsageMetric:
        """Convert to new UsageMetric format."""
        return UsageMetric(
            tenant_id=self.tenant_id,
            metric_type="api_request",
            quantity=float(self.count),
            timestamp=self.timestamp,
            metadata={
                "service": self.service,
                "endpoint": self.endpoint,
                "method": self.method,
                "latency_ms": self.latency_ms,
                "status_code": self.status_code,
            },
        )


class UsageReportRequest(BaseModel):
    """Batch of metrics to send to vikdata."""

    metrics: list[UsageMetric]

    model_config = ConfigDict(from_attributes=True)


class UsageReportResponse(BaseModel):
    """Response from usage report endpoint."""

    accepted: int
    rejected: int
    errors: list[str] | None = None

    model_config = ConfigDict(from_attributes=True)


class UsageReport(BaseModel):
    """Legacy batch usage report - use UsageReportRequest instead."""

    service: str
    metrics: list[UsageMetrics]
    reported_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = ConfigDict(from_attributes=True)

    def to_request(self) -> UsageReportRequest:
        """Convert to new UsageReportRequest format."""
        return UsageReportRequest(
            metrics=[m.to_usage_metric() for m in self.metrics]
        )


class UsageStats(BaseModel):
    """Aggregated usage statistics."""

    tenant_id: str
    service: str
    endpoint: str | None = None
    total_requests: int
    period_start: datetime
    period_end: datetime
    avg_latency_ms: float | None = None
    error_rate: float | None = None

    model_config = ConfigDict(from_attributes=True)
