import uuid
from datetime import date, datetime

from sqlalchemy import Date, DateTime, ForeignKey, Index, String, Text
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

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


class InterfaceChange(Base, TimestampMixin):
    __tablename__ = "interface_changes"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=new_uuid
    )
    repo_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), ForeignKey("managed_repos.id", ondelete="CASCADE"),
        nullable=False, index=True,
    )
    interface_type: Mapped[str] = mapped_column(
        String(40), nullable=False
    )  # rest_api | mcp_tool | cli | schema | capability
    change_type: Mapped[str] = mapped_column(
        String(40), nullable=False
    )  # breaking | additive | deprecation | removal
    title: Mapped[str] = mapped_column(String(300), nullable=False)
    description: Mapped[str] = mapped_column(Text, nullable=False)
    affected_paths: Mapped[list] = mapped_column(
        JSONB, nullable=False, default=list, server_default="[]"
    )
    affected_repo_slugs: Mapped[list] = mapped_column(
        JSONB, nullable=False, default=list, server_default="[]"
    )
    status: Mapped[str] = mapped_column(
        String(20), nullable=False, default="draft", index=True
    )  # draft | published | resolved
    planned_for: Mapped[date | None] = mapped_column(Date, nullable=True)
    published_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    resolved_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    author: Mapped[str] = mapped_column(String(100), nullable=False, default="custodian")

    repo: Mapped["ManagedRepo"] = relationship(  # noqa: F821
        "ManagedRepo", lazy="selectin"
    )

    __table_args__ = (
        Index("ix_interface_changes_repo_status", "repo_id", "status"),
    )
