-- =============================================
-- Education 模块 — 错题本 DDL
-- Ticket #9: 错题自动收集、复习练习创建
-- Migration: 005
-- Prerequisites: 004-education-submit-report.sql (report + detail tables)
-- =============================================

-- =============================================
-- Preconditions
-- =============================================
-- Operator is expected to verify:
--   SELECT COUNT(*) FROM information_schema.tables
--     WHERE table_schema = current_database()
--       AND table_name IN ('education_wrong_question',
--                          'education_wrong_question_idempotency');
-- Result MUST be 0 before executing this migration.
--
-- Verify prerequisite tables exist:
--   SELECT COUNT(*) FROM information_schema.tables
--     WHERE table_schema = current_database()
--       AND table_name IN ('education_practice_report',
--                          'education_practice_report_detail');
-- Result MUST be 2.

-- =============================================
-- PracticeReportDetailDO: add content_version + options snapshot columns
-- =============================================
-- Purpose: At submit time, snapshot question content version and options
--   (without isCorrect) so wrong-question book and review sessions have
--   stable display data. The options are already stripped of isCorrect
--   by the submit flow.
ALTER TABLE education_practice_report_detail
    ADD COLUMN content_version VARCHAR(64) NOT NULL DEFAULT '' /* 题目内容版本快照 */,
    ADD COLUMN options          TEXT        DEFAULT NULL        /* 选项快照 JSON（不含 isCorrect） */;

-- =============================================
-- PracticeSessionDO: add review fingerprint column
-- =============================================
-- Purpose: Persist the canonical fingerprint of wrong-question IDs used
--   to create a review session. On idempotent replay, the fingerprint
--   is compared: same tenant+clientSessionId+sameUser+sortedIDs match
--   returns the existing session; different ID set returns
--   SESSION_IDEMPOTENCY_MISMATCH.
ALTER TABLE education_practice_session
    ADD COLUMN review_fingerprint VARCHAR(64) DEFAULT NULL /* 复习会话题目指纹（SHA-256 of sorted unique wrongQuestionIds） */;

-- 错题表
-- =============================================
-- Purpose: Persistent wrong-question book per student.
--   Each (tenant, user, question) is a unique entry.
--   Repeated wrong answers on the SAME question increment wrong_count
--   and update last_wrong_time. The idempotency guard table ensures
--   each (tenant, user, question, report) can upsert at most once.
--
-- master_status values: 'PENDING' (default) | 'MASTERED'
--   Marking mastered retains the full history and count; it does NOT
--   delete or archive the record. Students can optionally un-master.
--
-- Snapshot fields (stem, type, difficulty, options, content_version):
--   populated from the latest report detail that touched this question.
--   These are for listing/detail display without joining report details.
--
-- latest_correct_answer, latest_explanation:
--   also from the latest report detail; available for detail display
--   post-submit (not exposed in review session creation pre-submit).
--
-- Indexes:
--   uk_tenant_user_question — per-tenant, per-user, per-question uniqueness.
--     INSERT ... ON CONFLICT ... DO UPDATE is the primary write path.
--   idx_tenant_user_status — covers filtered list queries (page with status filter).
--   idx_tenant_user_last_wrong — covers time-sorted listing.
CREATE TABLE education_wrong_question (
    id                    BIGINT       GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY /* 主键 */,
    tenant_id             BIGINT       NOT NULL              /* 租户编号 */,
    user_id               BIGINT       NOT NULL              /* 学生用户编号 */,
    question_id           VARCHAR(64)  NOT NULL              /* 原始题目 ID */,
    -- snapshot fields for listing / detail (from latest report detail)
    stem                  TEXT         NOT NULL              /* 题干快照（最新） */,
    type                  VARCHAR(32)  NOT NULL              /* 题型快照 */,
    difficulty            VARCHAR(32)  DEFAULT NULL           /* 难度快照 */,
    options               JSONB        NOT NULL              /* 选项快照 JSON（不含 isCorrect） */,
    content_version       VARCHAR(64)  NOT NULL DEFAULT ''   /* 题目内容版本 */,
    latest_correct_answer TEXT         DEFAULT NULL           /* 正确答案快照（最新，供详情展示） */,
    latest_explanation    TEXT         DEFAULT NULL           /* 解析快照（最新，供详情展示） */,
    -- timing & count
    first_wrong_time      TIMESTAMP    NOT NULL              /* 首次错误时间 */,
    last_wrong_time       TIMESTAMP    NOT NULL              /* 最近错误时间 */,
    wrong_count           INT          NOT NULL DEFAULT 1    /* 累计错误次数 */,
    -- mastery
    master_status         VARCHAR(20)  NOT NULL DEFAULT 'PENDING'
        /* 掌握状态：PENDING-待掌握, MASTERED-已掌握 */,
    mastered_time         TIMESTAMP    DEFAULT NULL           /* 标记掌握时间 */,
    -- provenance
    last_report_id        BIGINT       DEFAULT NULL           /* 最近关联的报告 ID */,
    last_session_id       BIGINT       DEFAULT NULL           /* 最近关联的会话 ID */,
    -- audit
    creator               VARCHAR(64)  DEFAULT ''            /* 创建者 */,
    create_time           TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP /* 创建时间 */,
    updater               VARCHAR(64)  DEFAULT ''            /* 更新者 */,
    update_time           TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP /* 更新时间 */,
    deleted               BOOLEAN      NOT NULL DEFAULT false /* 是否删除 */
);
COMMENT ON TABLE education_wrong_question IS '教育-错题本';

CREATE UNIQUE INDEX uk_tenant_user_question ON education_wrong_question (tenant_id, user_id, question_id);
CREATE INDEX idx_tenant_user_status ON education_wrong_question (tenant_id, user_id, master_status);
CREATE INDEX idx_tenant_user_last_wrong ON education_wrong_question (tenant_id, user_id, last_wrong_time);

-- =============================================
-- 错题流水幂等表
-- =============================================
-- Purpose: Ensure each (tenant, user, question, report) upserts the
--   wrong-question book exactly once. The submitSession transaction
--   INSERT ... ON CONFLICT DO NOTHING into this table BEFORE the
--   wrong question upsert; a duplicate means this report already
--   contributed to the count. This guards against:
--     - Replayed submit (idempotent resubmit) double-counting
--     - Concurrent submit races where both threads evaluate the
--       same report details
--
-- Indexes:
--   uk_tenant_user_question_report — per (tenant, user, question, report) uniqueness.
--     INSERT ... ON CONFLICT DO NOTHING provides the idempotency guard
--     BEFORE upserting. wrong_question_id is filled after upsert for
--     audit purposes.
--   idx_report — fast lookup by report for audit/debug.
CREATE TABLE education_wrong_question_idempotency (
    id                 BIGINT       GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY /* 主键 */,
    tenant_id          BIGINT       NOT NULL              /* 租户编号 */,
    user_id            BIGINT       NOT NULL              /* 学生用户编号 */,
    wrong_question_id  BIGINT       DEFAULT NULL           /* 错题记录 ID（upsert 后填充） */,
    report_id          BIGINT       NOT NULL              /* 报告 ID */,
    question_id        VARCHAR(64)  NOT NULL              /* 题目 ID */,
    creator            VARCHAR(64)  DEFAULT ''            /* 创建者 */,
    create_time        TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP /* 创建时间 */,
    updater            VARCHAR(64)  DEFAULT ''            /* 更新者 */,
    update_time        TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP /* 更新时间 */,
    deleted            BOOLEAN      NOT NULL DEFAULT false /* 是否删除 */
);
COMMENT ON TABLE education_wrong_question_idempotency IS '教育-错题流水幂等';

CREATE UNIQUE INDEX uk_tenant_user_question_report ON education_wrong_question_idempotency (tenant_id, user_id, question_id, report_id);
CREATE INDEX idx_report ON education_wrong_question_idempotency (report_id);

-- =============================================
-- Post-migration verification queries
-- =============================================
-- Verify new tables exist:
--   \d education_wrong_question
--   \d education_wrong_question_idempotency
-- Verify unique keys are enforced:
--   SELECT * FROM pg_indexes WHERE tablename = 'education_wrong_question' AND indexname = 'uk_tenant_user_question';
--   SELECT * FROM pg_indexes WHERE tablename = 'education_wrong_question_idempotency' AND indexname = 'uk_tenant_user_question_report';
-- Verify no orphan data (should be 0 after fresh migration):
--   SELECT COUNT(*) FROM education_wrong_question;
--   SELECT COUNT(*) FROM education_wrong_question_idempotency;
