"""Coverage snapshot models — periodic snapshots of coverage state.

CoverageSnapshot stores aggregate metrics at a point in time.
SnapshotTechniqueState stores per-technique state (normalized, one row
per technique per snapshot) to avoid bloated JSONB fields.
"""

# Import uuid
import uuid

# Import  from sqlalchemy
from sqlalchemy import (
    Column,
    DateTime,
    Float,
    ForeignKey,
    Index,
    Integer,
    String,
    func,
)

# Import JSONB, UUID from sqlalchemy.dialects.postgresql
from sqlalchemy.dialects.postgresql import JSONB, UUID

# Import relationship from sqlalchemy.orm
from sqlalchemy.orm import relationship

# Import Base from app.database
from app.database import Base


# Define class CoverageSnapshot
class CoverageSnapshot(Base):
    """A point-in-time snapshot of the organisation's overall coverage."""

    # Assign __tablename__ = "coverage_snapshots"
    __tablename__ = "coverage_snapshots"

    # Assign id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    # Assign name = Column(String, nullable=True)  # e.g. "Pre-remediación Q1"
    name = Column(String, nullable=True)  # e.g. "Pre-remediación Q1"
    # Assign organization_score = Column(Float, nullable=False)
    organization_score = Column(Float, nullable=False)
    # Assign total_techniques = Column(Integer, nullable=False)
    total_techniques = Column(Integer, nullable=False)
    # Assign validated_count = Column(Integer, nullable=False)
    validated_count = Column(Integer, nullable=False)
    # Assign partial_count = Column(Integer, nullable=False)
    partial_count = Column(Integer, nullable=False)
    # Assign not_covered_count = Column(Integer, nullable=False)
    not_covered_count = Column(Integer, nullable=False)
    # Assign in_progress_count = Column(Integer, nullable=False)
    in_progress_count = Column(Integer, nullable=False)
    # Assign not_evaluated_count = Column(Integer, nullable=False)
    not_evaluated_count = Column(Integer, nullable=False)
    # Assign coverage_percentage = Column(Float, nullable=False, default=0.0)
    coverage_percentage = Column(Float, nullable=False, default=0.0)
    # Assign by_tactic = Column(JSONB, nullable=False, default=dict)
    by_tactic = Column(JSONB, nullable=False, default=dict)
    # Assign by_status = Column(JSONB, nullable=False, default=dict)
    by_status = Column(JSONB, nullable=False, default=dict)
    # Assign stale_count = Column(Integer, nullable=False, default=0)
    stale_count = Column(Integer, nullable=False, default=0)
    # Assign never_tested_count = Column(Integer, nullable=False, default=0)
    never_tested_count = Column(Integer, nullable=False, default=0)
    # Assign created_by = Column(
    created_by = Column(
        UUID(as_uuid=True),
        ForeignKey("users.id", ondelete="SET NULL"),
        # Keyword argument: nullable
        nullable=True,
    )
    # Assign created_at = Column(DateTime(timezone=True), server_default=func.now())
    created_at = Column(DateTime(timezone=True), server_default=func.now())

    # Relationships
    creator = relationship("User", foreign_keys=[created_by])
    # Assign technique_states = relationship(
    technique_states = relationship(
        # Literal argument value
        "SnapshotTechniqueState",
        # Keyword argument: back_populates
        back_populates="snapshot",
        # Keyword argument: cascade
        cascade="all, delete-orphan",
    )


# Define class SnapshotTechniqueState
class SnapshotTechniqueState(Base):
    """Per-technique state within a snapshot (normalised storage)."""

    # Assign __tablename__ = "snapshot_technique_states"
    __tablename__ = "snapshot_technique_states"

    # Assign id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    # Assign snapshot_id = Column(
    snapshot_id = Column(
        UUID(as_uuid=True),
        ForeignKey("coverage_snapshots.id", ondelete="CASCADE"),
        # Keyword argument: nullable
        nullable=False,
    )
    # Assign technique_id = Column(
    technique_id = Column(
        UUID(as_uuid=True),
        ForeignKey("techniques.id", ondelete="CASCADE"),
        # Keyword argument: nullable
        nullable=False,
    )
    # Assign mitre_id = Column(String, nullable=False)  # denormalised for fast queries
    mitre_id = Column(String, nullable=False)  # denormalised for fast queries
    # Assign status = Column(String, nullable=False)
    status = Column(String, nullable=False)
    # Assign score = Column(Float, nullable=True)
    score = Column(Float, nullable=True)

    # Relationships
    snapshot = relationship("CoverageSnapshot", back_populates="technique_states")
    # Assign technique = relationship("Technique")
    technique = relationship("Technique")

    # Assign __table_args__ = (
    __table_args__ = (
        Index("ix_snapshot_technique_states_snapshot", "snapshot_id"),
        Index("ix_snapshot_technique_states_technique", "technique_id"),
    )
