from sqlalchemy import ForeignKey, Index, Integer, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column

from scribe.models import Base
from scribe.models.base import CreatedAtMixin, SoftDeleteMixin, TimestampMixin, iso


class System(Base, TimestampMixin, SoftDeleteMixin):
    """A per-project, reusable, self-describing subsystem/area.

    Any record (note, task, or issue) can be associated with one or more
    systems via record_systems, so research notes, build-tasks, and corrective
    work line up under the same area — and recurring problem-areas become
    filterable. Self-describing (name + description) because a bare name is
    never enough to convey what a system is or how it's used.
    """
    __tablename__ = "systems"

    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("users.id", ondelete="CASCADE")
    )
    project_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("projects.id", ondelete="CASCADE")
    )
    name: Mapped[str] = mapped_column(Text, default="", server_default="")
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    color: Mapped[str | None] = mapped_column(Text, nullable=True)
    # active | archived — systems accumulate; archive rather than delete.
    status: Mapped[str] = mapped_column(Text, default="active", server_default="active")
    order_index: Mapped[int] = mapped_column(Integer, default=0, server_default="0")

    __table_args__ = (
        Index("ix_systems_project_id", "project_id"),
    )

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "user_id": self.user_id,
            "project_id": self.project_id,
            "name": self.name,
            "description": self.description,
            "color": self.color,
            "status": self.status,
            "order_index": self.order_index,
            "created_at": iso(self.created_at),
            "updated_at": iso(self.updated_at),
        }


class RecordSystem(Base, CreatedAtMixin):
    """M2M association: a record (notes.id — any note/task/issue) <-> a System.

    Mutable over time; uniqueness keeps a record from linking the same system
    twice. Cascades on both sides, so deleting a record or a system clears its
    associations.
    """
    __tablename__ = "record_systems"

    id: Mapped[int] = mapped_column(primary_key=True)
    note_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("notes.id", ondelete="CASCADE")
    )
    system_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("systems.id", ondelete="CASCADE")
    )

    __table_args__ = (
        UniqueConstraint("note_id", "system_id", name="uq_record_systems_note_system"),
        Index("ix_record_systems_note_id", "note_id"),
        Index("ix_record_systems_system_id", "system_id"),
    )
