"""
Asgard Metrics History Models

Provides data models for persisting analysis snapshots and computing metric trends
over time. Trends are used to understand whether code quality is improving,
stable, or degrading across successive analysis runs.
"""

from datetime import datetime
from enum import Enum
from typing import Dict, List, Optional, Tuple

from pydantic import BaseModel, Field


class MetricSnapshot(BaseModel):
    """
    A single metric value captured at analysis time.

    Represents one data point for a named metric (e.g. security_score,
    duplication_percentage) as part of an AnalysisSnapshot.
    """
    metric_name: str = Field(..., description="Metric identifier (e.g. 'maintainability_index')")
    value: float = Field(..., description="Numeric value of the metric at snapshot time")
    unit: str = Field("", description="Optional unit label (e.g. '%', 'hours', 'score')")

    class Config:
        use_enum_values = True


class AnalysisSnapshot(BaseModel):
    """
    A complete point-in-time record of all analysis metrics for a project.

    Snapshots are stored in a SQLite database at ~/.asgard/history.db and are
    keyed by snapshot_id (UUID). Each snapshot optionally captures the current
    git commit and branch so trends can be correlated to code changes.
    """
    snapshot_id: str = Field(..., description="UUID identifying this snapshot")
    project_path: str = Field(..., description="Absolute path to the analysed project root")
    scan_timestamp: datetime = Field(
        default_factory=datetime.now,
        description="When this analysis was performed",
    )
    git_commit: Optional[str] = Field(
        None,
        description="HEAD commit hash at scan time (if available)",
    )
    git_branch: Optional[str] = Field(
        None,
        description="Current git branch at scan time (if available)",
    )
    metrics: List[MetricSnapshot] = Field(
        default_factory=list,
        description="All metric values captured in this snapshot",
    )
    quality_gate_status: Optional[str] = Field(
        None,
        description="Quality gate outcome: 'passed', 'failed', or 'warning'",
    )
    ratings: Dict[str, str] = Field(
        default_factory=dict,
        description="Letter ratings by dimension (e.g. {'security': 'A', 'reliability': 'B'})",
    )

    class Config:
        use_enum_values = True

    def get_metric(self, metric_name: str) -> Optional[float]:
        """Return the value for a named metric, or None if not present."""
        for m in self.metrics:
            if m.metric_name == metric_name:
                return m.value
        return None


class TrendDirection(str, Enum):
    """Indicates whether a metric is improving, stable, or degrading over time."""
    IMPROVING = "improving"
    STABLE = "stable"
    DEGRADING = "degrading"


class MetricTrend(BaseModel):
    """
    Trend analysis for a single metric across multiple snapshots.

    Direction is computed from the percentage change between the most recent
    and the immediately preceding snapshot. For metrics where lower values are
    better (e.g. duplication, complexity), the direction logic is inverted.
    """
    metric_name: str = Field(..., description="Metric being trended")
    current_value: float = Field(..., description="Most recent value")
    previous_value: float = Field(..., description="Value from the preceding snapshot")
    change: float = Field(..., description="Absolute change (current - previous)")
    change_percentage: float = Field(..., description="Percentage change relative to previous value")
    direction: TrendDirection = Field(..., description="Whether the metric is improving, stable, or degrading")
    snapshots: List[Tuple[datetime, float]] = Field(
        default_factory=list,
        description="Historical (timestamp, value) pairs in chronological order",
    )

    class Config:
        use_enum_values = True


class TrendReport(BaseModel):
    """
    A summary of metric trends for a project across all recorded snapshots.

    Generated by HistoryStore.get_trend_report() and used to surface
    quality trajectory information in the CLI and reports.
    """
    project_path: str = Field(..., description="Absolute path to the analysed project root")
    metric_trends: List[MetricTrend] = Field(
        default_factory=list,
        description="Trend analysis for each tracked metric",
    )
    analysis_count: int = Field(0, description="Total number of snapshots recorded for this project")
    first_analysis: Optional[datetime] = Field(
        None,
        description="Timestamp of the earliest recorded snapshot",
    )
    last_analysis: Optional[datetime] = Field(
        None,
        description="Timestamp of the most recent snapshot",
    )
    generated_at: datetime = Field(
        default_factory=datetime.now,
        description="When this trend report was generated",
    )

    class Config:
        use_enum_values = True
