import uuid
from datetime import date, datetime

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

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


class ManagedRepo(Base, TimestampMixin):
    __tablename__ = "managed_repos"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=new_uuid
    )
    domain_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), ForeignKey("domains.id", ondelete="RESTRICT"), nullable=False, index=True
    )
    slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False, index=True)
    name: Mapped[str] = mapped_column(String(200), nullable=False)
    local_path: Mapped[str | None] = mapped_column(Text, nullable=True)
    host_paths: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
    remote_url: Mapped[str | None] = mapped_column(Text, nullable=True)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="active")
    topic_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("topics.id", ondelete="SET NULL"), nullable=True
    )
    git_fingerprint: Mapped[str | None] = mapped_column(String(40), nullable=True, index=True)
    sbom_source: Mapped[str | None] = mapped_column(Text, nullable=True)
    last_sbom_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    last_state_synced_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )

    category: Mapped[str | None] = mapped_column(String(50), nullable=True)
    secondary_domains: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
    capability_tags: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
    business_stake: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
    business_mechanics: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
    classified_at: Mapped[date | None] = mapped_column(Date, nullable=True)
    classified_by: Mapped[str | None] = mapped_column(String(50), nullable=True)
    standard_version: Mapped[str | None] = mapped_column(String(20), nullable=True)

    domain: Mapped["Domain"] = relationship(  # noqa: F821
        "Domain", back_populates="repos", lazy="selectin"
    )

    goals: Mapped[list["RepoGoal"]] = relationship(  # noqa: F821
        "RepoGoal", back_populates="repo", lazy="selectin"
    )

    @property
    def domain_slug(self) -> str:
        return self.domain.slug if self.domain is not None else ""
