import uuid
from datetime import datetime

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

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


class CapabilityRequest(Base, TimestampMixin):
    __tablename__ = "capability_requests"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=new_uuid
    )
    title: Mapped[str] = mapped_column(String(500), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    capability_type: Mapped[str] = mapped_column(String(50), nullable=False)
    priority: Mapped[str] = mapped_column(
        String(20), nullable=False, default="medium", server_default="medium"
    )
    status: Mapped[str] = mapped_column(
        String(20), nullable=False, default="requested", server_default="requested"
    )

    # Requester side
    requesting_domain_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("domains.id", ondelete="RESTRICT"),
        nullable=False,
        index=True,
    )
    requesting_workplan_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("workplans.id", ondelete="SET NULL"),
        nullable=True,
    )
    requesting_agent: Mapped[str] = mapped_column(String(100), nullable=False)

    # Fulfiller side (populated on accept / auto-route)
    fulfilling_domain_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("domains.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )
    fulfilling_workplan_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("workplans.id", ondelete="SET NULL"),
        nullable=True,
    )
    fulfilling_agent: Mapped[str | None] = mapped_column(String(100), nullable=True)

    # Links
    blocking_task_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("tasks.id", ondelete="SET NULL"),
        nullable=True,
    )
    catalog_entry_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("capability_catalog.id", ondelete="SET NULL"),
        nullable=True,
    )

    resolution_note: Mapped[str | None] = mapped_column(Text, nullable=True)
    routing_note: Mapped[str | None] = mapped_column(Text, nullable=True)

    # Dispute fields (populated when status = routing_disputed)
    dispute_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    disputed_by: Mapped[str | None] = mapped_column(String(100), nullable=True)
    dispute_suggested_domain: Mapped[str | None] = mapped_column(String(100), nullable=True)
    disputed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    accepted_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    completed_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )

    # Relationships
    requesting_domain: Mapped["Domain"] = relationship(  # noqa: F821
        "Domain", foreign_keys=[requesting_domain_id], lazy="selectin"
    )
    fulfilling_domain: Mapped["Domain | None"] = relationship(  # noqa: F821
        "Domain", foreign_keys=[fulfilling_domain_id], lazy="selectin"
    )
    blocking_task: Mapped["Task | None"] = relationship("Task", lazy="selectin")  # noqa: F821
    catalog_entry: Mapped["CapabilityCatalog | None"] = relationship(  # noqa: F821
        "CapabilityCatalog", lazy="selectin"
    )

    @property
    def requesting_domain_slug(self) -> str:
        return self.requesting_domain.slug if self.requesting_domain else ""

    @property
    def fulfilling_domain_slug(self) -> str | None:
        return self.fulfilling_domain.slug if self.fulfilling_domain else None
