from sqlalchemy import CheckConstraint, ForeignKey, Integer, Text
from sqlalchemy.orm import Mapped, mapped_column

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


class ProjectShare(Base, TimestampMixin):
    __tablename__ = "project_shares"
    __table_args__ = (
        CheckConstraint(
            "(shared_with_user_id IS NOT NULL) != (shared_with_group_id IS NOT NULL)",
            name="ck_ps_exclusive_target",
        ),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    project_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("projects.id", ondelete="CASCADE"), nullable=False
    )
    shared_with_user_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("users.id", ondelete="CASCADE")
    )
    shared_with_group_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("groups.id", ondelete="CASCADE")
    )
    permission: Mapped[str] = mapped_column(Text, nullable=False)
    invited_by: Mapped[int] = mapped_column(
        Integer, ForeignKey("users.id"), nullable=False
    )

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "project_id": self.project_id,
            "shared_with_user_id": self.shared_with_user_id,
            "shared_with_group_id": self.shared_with_group_id,
            "permission": self.permission,
            "invited_by": self.invited_by,
            "created_at": iso(self.created_at),
            "updated_at": iso(self.updated_at),
        }


class NoteShare(Base, TimestampMixin):
    __tablename__ = "note_shares"
    __table_args__ = (
        CheckConstraint(
            "(shared_with_user_id IS NOT NULL) != (shared_with_group_id IS NOT NULL)",
            name="ck_ns_exclusive_target",
        ),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    note_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("notes.id", ondelete="CASCADE"), nullable=False
    )
    shared_with_user_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("users.id", ondelete="CASCADE")
    )
    shared_with_group_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("groups.id", ondelete="CASCADE")
    )
    permission: Mapped[str] = mapped_column(Text, nullable=False)
    invited_by: Mapped[int] = mapped_column(
        Integer, ForeignKey("users.id"), nullable=False
    )

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "note_id": self.note_id,
            "shared_with_user_id": self.shared_with_user_id,
            "shared_with_group_id": self.shared_with_group_id,
            "permission": self.permission,
            "invited_by": self.invited_by,
            "created_at": iso(self.created_at),
            "updated_at": iso(self.updated_at),
        }
