import uuid
from datetime import date, datetime

from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Index, Integer, String, Text, UniqueConstraint, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from api.models.base import Base, TimestampMixin, new_uuid


class LegacyInterface(Base, TimestampMixin):
    __tablename__ = "legacy_interfaces"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=new_uuid
    )
    interface_key: Mapped[str] = mapped_column(String(300), nullable=False, unique=True, index=True)
    interface_kind: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
    legacy_since: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), nullable=False, index=True
    )
    replacement_ref: Mapped[str] = mapped_column(Text, nullable=False)
    owner_component: Mapped[str] = mapped_column(
        String(100), nullable=False, default="state-hub", server_default="state-hub", index=True
    )
    status: Mapped[str] = mapped_column(
        String(30), nullable=False, default="legacy", server_default="legacy", index=True
    )
    replacement_verified: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False, server_default="false"
    )
    manual_hold: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False, server_default="false"
    )
    hold_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)
    retired_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    usage_buckets: Mapped[list["LegacyInterfaceUsageBucket"]] = relationship(  # noqa: F821
        "LegacyInterfaceUsageBucket",
        back_populates="legacy_interface",
        cascade="all, delete-orphan",
        lazy="selectin",
    )


class LegacyInterfaceUsageBucket(Base, TimestampMixin):
    __tablename__ = "legacy_interface_usage_buckets"
    __table_args__ = (
        UniqueConstraint(
            "legacy_interface_id",
            "period_start",
            "bucket_kind",
            "bucket_key",
            name="uq_legacy_usage_bucket",
        ),
        Index("ix_legacy_usage_interface_period", "legacy_interface_id", "period_start"),
        Index("ix_legacy_usage_bucket_kind_key", "bucket_kind", "bucket_key"),
    )

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=new_uuid
    )
    legacy_interface_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("legacy_interfaces.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )
    period_start: Mapped[date] = mapped_column(Date, nullable=False, index=True)
    bucket_kind: Mapped[str] = mapped_column(String(30), nullable=False)
    bucket_key: Mapped[str] = mapped_column(String(200), nullable=False)
    call_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
    first_seen_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    last_seen_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True)

    legacy_interface: Mapped["LegacyInterface"] = relationship(  # noqa: F821
        "LegacyInterface", back_populates="usage_buckets"
    )
