-- 164_study_sessions.sql
-- iPad 손글씨 학습 세션 + 모바일 암기노트/퀴즈 — Phase 1 MVP
-- plan: ~/.claude/plans/scalable-chasing-stonebraker.md
--
-- 목적: 자격증(산업안전기사 등) + 어학(일본어/한자 우선) 두 도메인을 모두 받는 일반 학습 세션.
-- iPad write 모드(필사) / 모바일 review 모드(암기노트) / quiz 모드(SRS) 가 같은 데이터를 공유.
--
-- 핵심 원칙:
--   - study_sessions: 학습 메타 + stroke JSON 원본 + 도메인별 자유 metadata
--   - study_session_assets: documents 의 스캔/필기PNG/오디오/영상/자막을 연결 (단일 *_id 컬럼 금지)
--   - documents 원본은 절대 삭제하지 않음 (assets 만 cascade)
--   - Phase 1 미사용 필드 (review_state / quiz / ocr / ai_summary / prompt) 는 NULL 허용, 자동 로직 X
--
-- 인덱스 전략:
--   - 자격증/어학 카드 그룹: partial index (study_type 별)
--   - SRS 복습 큐: review_state IS NOT NULL 만
--   - assets join: study_session_id, document_id, asset_type 별

CREATE TABLE IF NOT EXISTS study_sessions (
    id              BIGSERIAL PRIMARY KEY,
    user_id         BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,

    -- 도메인 분기
    study_type      VARCHAR(30) NOT NULL DEFAULT 'certification',
                    -- 'certification' | 'language' (Phase 2+ 'general' 등 확장 여지)

    -- 자격증 메타
    certification   VARCHAR(120),                  -- 예: "산업안전기사" (study_type='certification' 시)
    -- 어학 메타
    language_code   VARCHAR(20),                   -- 'ja' | 'en' | 'zh' (study_type='language' 시)
    -- 공통: 학습 레벨 (도메인 무관)
    learning_level  VARCHAR(80),                   -- 예: "JLPT N3", "TOEIC 750", "산업안전기사 1차"

    -- 공통: 과목/주제
    subject         VARCHAR(120),                  -- 예: "산업안전보건법" / "漢字"
    topic           VARCHAR(200),                  -- 예: "안전보건관리책임자의 직무" / "安全"

    -- 원문 텍스트 snapshot (assets 의 source_scan 과 별개로 발췌 텍스트만 보존)
    source_text     TEXT,                          -- 예: "安全" / 법령 본문 발췌
    source_page     INTEGER,

    -- 학습 모드
    mode            VARCHAR(30) NOT NULL DEFAULT 'copy',
                    -- 공통: 'copy'(필사)/'trace'(트레이싱)/'blank-repeat'(깜지)
                    -- 어학: 'dictation'(받아쓰기)/'shadowing'(쉐도잉)
                    -- Phase 2+: 'quiz'/'flashcard'
    prompt_question TEXT,                          -- Phase 2: AI 역질문
    expected_answer TEXT,                          -- Phase 2: 기대 정답

    -- 도메인별 자유 메타
    -- 어학 예: {"reading":"あんぜん","meaning":"안전","romaji":"anzen","furigana":"...",
    --          "example_sentence":"安全第一です。","grammar_point":"...","unit_type":"kanji"}
    --   unit_type: 'kanji' | 'vocabulary' | 'sentence' | 'listening' | 'shadowing'
    -- 자격증 예: {"law_article":"산업안전보건법 제15조","formula":"...","keywords":[...]}
    metadata        JSONB,

    -- 횟수 카운트 (보조)
    target_count        INTEGER,
    repetition_count    INTEGER NOT NULL DEFAULT 0,

    -- 필기 데이터 (원본) — Phase 1 핵심
    strokes_json    JSONB,                         -- perfect-freehand input points + style
    canvas_width    INTEGER,
    canvas_height   INTEGER,
    schema_version  INTEGER NOT NULL DEFAULT 1,

    -- 필기 파생 텍스트 — Phase 2 채움 (Phase 1 NULL)
    ocr_text                 TEXT,
    user_corrected_text      TEXT,
    ai_summary               TEXT,                 -- 모바일 카드 view 용 (classify worker 동기화)

    -- SRS / 퀴즈 통계 — Phase 4 활성, Phase 1 NULL
    review_state    VARCHAR(20),                   -- 'new' | 'learning' | 'weak' | 'mastered'
    next_review_at  TIMESTAMPTZ,
    last_quiz_at    TIMESTAMPTZ,
    correct_count   INTEGER NOT NULL DEFAULT 0,
    incorrect_count INTEGER NOT NULL DEFAULT 0,

    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- 도메인+사용자별 최근 세션 조회 (자격증/어학 공통 목록)
CREATE INDEX IF NOT EXISTS idx_study_sessions_type_user_created
    ON study_sessions (user_id, study_type, created_at DESC);

-- 자격증 카드 그룹 (Phase 3)
CREATE INDEX IF NOT EXISTS idx_study_sessions_cert
    ON study_sessions (user_id, certification, subject, topic)
    WHERE study_type = 'certification';

-- 어학 카드 그룹 (Phase 3)
CREATE INDEX IF NOT EXISTS idx_study_sessions_lang
    ON study_sessions (user_id, language_code, learning_level, subject, topic)
    WHERE study_type = 'language';

-- SRS 복습 큐 (Phase 4) — review_state 가 있는 행만
CREATE INDEX IF NOT EXISTS idx_study_sessions_review
    ON study_sessions (user_id, review_state, next_review_at)
    WHERE review_state IS NOT NULL;

-- 퀴즈 통계 (Phase 4) — last_quiz_at 가 있는 행만
CREATE INDEX IF NOT EXISTS idx_study_sessions_quiz_stats
    ON study_sessions (user_id, study_type, last_quiz_at)
    WHERE last_quiz_at IS NOT NULL;


CREATE TABLE IF NOT EXISTS study_session_assets (
    id                  BIGSERIAL PRIMARY KEY,
    study_session_id    BIGINT NOT NULL REFERENCES study_sessions(id) ON DELETE CASCADE,
    document_id         BIGINT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,

    -- asset_type: 'source_scan' | 'handwriting_png' | 'audio' | 'video' | 'transcript' | 'reference'
    asset_type  VARCHAR(30) NOT NULL,
    -- role: 'prompt' | 'answer' | 'pronunciation' | 'lecture' | 'listening_source'
    --        | 'shadowing_source' | 'reference'
    role        VARCHAR(40),
    sort_order  INTEGER NOT NULL DEFAULT 0,

    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- 같은 (세션, 문서, asset_type, role) 조합 중복 금지 → POST /assets 의 409 근거
    -- role 이 NULL 인 경우 NULL 끼리는 unique 비교 시 다른 값으로 취급 (Postgres 기본). 의도된 동작.
    UNIQUE (study_session_id, document_id, asset_type, role)
);

-- 세션별 assets 정렬 조회
CREATE INDEX IF NOT EXISTS idx_session_assets_session
    ON study_session_assets (study_session_id, sort_order);

-- 문서가 어느 세션에 연결됐는지 역참조 (filter ?document_id=...)
CREATE INDEX IF NOT EXISTS idx_session_assets_document
    ON study_session_assets (document_id);

-- 특정 asset_type 보유 세션 조회 (filter ?asset_type=audio)
CREATE INDEX IF NOT EXISTS idx_session_assets_type
    ON study_session_assets (study_session_id, asset_type);
