from typing import TYPE_CHECKING, Any

from sqlalchemy import Integer, String, Text
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

from src.models.base import Base, UUIDMixin

if TYPE_CHECKING:
    from src.models.question import Question


class Pattern(Base, UUIDMixin):
    """Algorithmic pattern (e.g., Two Pointers, Sliding Window)."""

    __tablename__ = "patterns"

    # Core fields
    name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    when_to_use: Mapped[str | None] = mapped_column(Text, nullable=True)

    # Tutorial content fields
    metaphor: Mapped[str | None] = mapped_column(Text, nullable=True)
    core_concept: Mapped[str | None] = mapped_column(Text, nullable=True)
    visualization: Mapped[str | None] = mapped_column(Text, nullable=True)
    code_template: Mapped[str | None] = mapped_column(Text, nullable=True)

    # Structured data fields (JSONB)
    recognition_signals: Mapped[list[str] | None] = mapped_column(JSONB, nullable=True)
    common_mistakes: Mapped[list[dict[str, Any]] | None] = mapped_column(JSONB, nullable=True)
    variations: Mapped[list[dict[str, Any]] | None] = mapped_column(JSONB, nullable=True)
    related_patterns: Mapped[list[str] | None] = mapped_column(JSONB, nullable=True)
    prerequisite_patterns: Mapped[list[str] | None] = mapped_column(JSONB, nullable=True)

    # Difficulty level (1-5 learning curve)
    difficulty_level: Mapped[int | None] = mapped_column(Integer, nullable=True)

    # Pattern classification
    pattern_type: Mapped[str | None] = mapped_column(String(50), nullable=True)
    display_order: Mapped[int | None] = mapped_column(Integer, nullable=True)

    # Interactive visualization examples
    visualization_examples: Mapped[list[dict[str, Any]] | None] = mapped_column(
        JSONB, nullable=True
    )

    # Relationships
    questions: Mapped[list["Question"]] = relationship(
        secondary="question_patterns",
        back_populates="patterns",
    )
