import uuid
from typing import TYPE_CHECKING

from sqlalchemy import (
    Boolean,
    ForeignKey,
    JSON,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy import Uuid as UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin

if TYPE_CHECKING:
    from src.models.project import Project
    from src.models import ToolType
    from src.models.user import User


class ConfigProfile(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    __tablename__ = "config_profiles"
    __table_args__ = (
        UniqueConstraint("user_id", "name", name="uq_config_profiles_user_name"),
    )

    user_id: Mapped[uuid.UUID] = mapped_column(
        UUID(), ForeignKey("users.id", ondelete="CASCADE"), nullable=False
    )
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    project_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(), ForeignKey("projects.id", ondelete="CASCADE"), nullable=True
    )
    tool_type_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(), ForeignKey("tool_types.id", ondelete="CASCADE"), nullable=True
    )
    env_vars: Mapped[dict] = mapped_column(
        JSON, default=dict, nullable=False
    )  # {"VAR_NAME": "value", ...}
    runtime_hints: Mapped[dict] = mapped_column(
        JSON, default=dict, nullable=False
    )  # {"start_command": "...", "working_dir": "...", ...}
    mounts: Mapped[list] = mapped_column(
        JSON, default=list, nullable=False
    )  # [{"target": "/path", "mode": "rw", "files": {"rel/path": "content"}}, ...]
    files: Mapped[dict] = mapped_column(
        JSON, default=dict, nullable=False
    )  # {"rel/path": "content", ...}
    git_mounts: Mapped[list] = mapped_column(
        JSON, default=list, nullable=False
    )  # [{"remote_url": "https://github.com/user/repo.git", "source_path": ".", "target_path": "/path", "branch": "main"}, ...]
    is_default: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)

    user: Mapped["User"] = relationship()
    project: Mapped["Project | None"] = relationship()
    tool_type: Mapped["ToolType | None"] = relationship()
    includes: Mapped[list["ConfigProfileInclude"]] = relationship(
        "ConfigProfileInclude",
        foreign_keys="ConfigProfileInclude.profile_id",
        order_by="ConfigProfileInclude.order_index",
        cascade="all, delete-orphan",
    )


class ConfigProfileInclude(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    __tablename__ = "config_profile_includes"

    profile_id: Mapped[uuid.UUID] = mapped_column(
        UUID(), ForeignKey("config_profiles.id", ondelete="CASCADE"), nullable=False
    )
    included_profile_id: Mapped[uuid.UUID] = mapped_column(
        UUID(), ForeignKey("config_profiles.id", ondelete="CASCADE"), nullable=False
    )
    order_index: Mapped[int] = mapped_column(Integer, nullable=False, default=0)

    profile: Mapped["ConfigProfile"] = relationship(
        "ConfigProfile",
        foreign_keys=[profile_id],
        back_populates="includes",
    )
    included_profile: Mapped["ConfigProfile"] = relationship(
        "ConfigProfile",
        foreign_keys=[included_profile_id],
    )
