"""study_sessions / study_session_assets 테이블 ORM — Phase 1 MVP

목적: iPad 손글씨 학습 세션 (자격증 + 어학) + 모바일 암기노트/퀴즈를 위한 일반 학습 세션.

설계 원칙:
  - study_type 으로 certification / language 분기. metadata jsonb 가 도메인별 자유 메타.
  - 단일 audio_document_id / video_document_id / source_document_id / handwriting_document_id
    컬럼 만들지 ❌. 모든 미디어 연결은 study_session_assets 로 통일.
  - documents 본체는 절대 삭제하지 않음. assets cascade 는 sessions 또는 documents 삭제 시.
  - Phase 1 미사용 필드 (review_state / quiz / ocr / ai_summary / prompt) 는 NULL 허용,
    자동 로직은 Phase 2~4 에서 별도 PR 로 활성.
"""

from datetime import datetime
from typing import Any

from sqlalchemy import (
    BigInteger,
    DateTime,
    ForeignKey,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

from core.database import Base


class StudySession(Base):
    __tablename__ = "study_sessions"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
    user_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
    )

    # 도메인 분기: 'certification' | 'language'
    study_type: Mapped[str] = mapped_column(
        String(30), default="certification", nullable=False
    )

    # 자격증/어학 메타
    certification: Mapped[str | None] = mapped_column(String(120))
    language_code: Mapped[str | None] = mapped_column(String(20))
    learning_level: Mapped[str | None] = mapped_column(String(80))

    # 공통 과목/주제
    subject: Mapped[str | None] = mapped_column(String(120))
    topic: Mapped[str | None] = mapped_column(String(200))

    # 원문 텍스트 snapshot (assets 의 source_scan 과 별개로 발췌 텍스트만 보존)
    source_text: Mapped[str | None] = mapped_column(Text)
    source_page: Mapped[int | None] = mapped_column(Integer)

    # 학습 모드: 'copy'/'trace'/'blank-repeat'/'dictation'/'shadowing'/'quiz'/'flashcard'
    mode: Mapped[str] = mapped_column(String(30), default="copy", nullable=False)
    prompt_question: Mapped[str | None] = mapped_column(Text)
    expected_answer: Mapped[str | None] = mapped_column(Text)

    # 도메인별 자유 메타 (어학 reading/meaning, 자격증 law_article 등)
    metadata_json: Mapped[dict[str, Any] | None] = mapped_column(
        "metadata", JSONB
    )

    # 횟수 카운트 (보조)
    target_count: Mapped[int | None] = mapped_column(Integer)
    repetition_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)

    # 필기 데이터 (원본) — Phase 1 핵심
    strokes_json: Mapped[dict[str, Any] | None] = mapped_column(JSONB)
    canvas_width: Mapped[int | None] = mapped_column(Integer)
    canvas_height: Mapped[int | None] = mapped_column(Integer)
    schema_version: Mapped[int] = mapped_column(Integer, default=1, nullable=False)

    # 필기 파생 텍스트 — Phase 2 채움 (Phase 1 NULL)
    ocr_text: Mapped[str | None] = mapped_column(Text)
    user_corrected_text: Mapped[str | None] = mapped_column(Text)
    ai_summary: Mapped[str | None] = mapped_column(Text)

    # SRS / 퀴즈 통계 — Phase 4 활성, Phase 1 NULL
    review_state: Mapped[str | None] = mapped_column(String(20))
    next_review_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    last_quiz_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    correct_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    incorrect_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)

    # 학습 워크스페이스(study_topic) 1:N. NULL 허용 — 미분류 세션이 정상 상태.
    study_topic_id: Mapped[int | None] = mapped_column(
        BigInteger, ForeignKey("study_topics.id", ondelete="SET NULL")
    )

    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=datetime.now, nullable=False
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=datetime.now, onupdate=datetime.now, nullable=False
    )

    # 연관 assets — 세션 삭제 시 함께 삭제 (DB ON DELETE CASCADE 와 일치)
    assets: Mapped[list["StudySessionAsset"]] = relationship(
        back_populates="session",
        cascade="all, delete-orphan",
        order_by="StudySessionAsset.sort_order",
    )

    # 연관 학습 워크스페이스
    study_topic: Mapped["StudyTopic | None"] = relationship(
        "StudyTopic", back_populates="sessions", lazy="noload"
    )


class StudySessionAsset(Base):
    __tablename__ = "study_session_assets"
    __table_args__ = (
        # POST /assets 의 409 근거. NULL role 끼리는 Postgres 기본대로 다른 값으로 취급.
        UniqueConstraint(
            "study_session_id", "document_id", "asset_type", "role",
            name="study_session_assets_session_id_document_id_asset_type_rol_key",
        ),
    )

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
    study_session_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("study_sessions.id", ondelete="CASCADE"), nullable=False
    )
    document_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("documents.id", ondelete="CASCADE"), nullable=False
    )

    # 'source_scan' | 'handwriting_png' | 'audio' | 'video' | 'transcript' | 'reference'
    asset_type: Mapped[str] = mapped_column(String(30), nullable=False)
    # 'prompt' | 'answer' | 'pronunciation' | 'lecture' | 'listening_source'
    # | 'shadowing_source' | 'reference'
    role: Mapped[str | None] = mapped_column(String(40))
    sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False)

    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=datetime.now, nullable=False
    )

    session: Mapped["StudySession"] = relationship(back_populates="assets")
