-- =============================================
-- Education 模块 — 答案保存幂等性 DDL
-- Ticket #7: 答案命令幂等、乐观锁并发控制、答案恢复
-- Migration: 003
-- Prerequisites: 002-education-practice-session.sql (session + question snapshots)
-- =============================================

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

-- =============================================
-- 答案命令幂等表
-- =============================================
-- Purpose: Provide durable idempotency for answer save commands.
--   Same (tenant, user, operation, idempotency_key) + same request_hash → replay original response.
--   Same key + different request_hash → conflict.
--   Concurrent same-key inserts are resolved by unique constraint race handling.
--
-- Indexes:
--   uk_answer_idempotency — per-tenant, per-actor, per-operation uniqueness for idempotency key.
--     INSERT during answer save. DuplicateKeyException catch for concurrent-create race resolution.
--   idx_tenant_session — covers lookup by session for audit/debug.
--
-- response_json: Stores the serialized answer response for replay after network timeout/retry.
-- request_hash: SHA-256 of canonical payload (sorted JSON fields) for content-based dedup.
CREATE TABLE `education_answer_idempotency` (
    `id`               BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
    `tenant_id`        BIGINT       NOT NULL              COMMENT '租户编号',
    `user_id`          BIGINT       NOT NULL              COMMENT '答题用户编号',
    `operation`        VARCHAR(32)  NOT NULL DEFAULT 'SUBMIT_ANSWER'
        COMMENT '操作类型：SUBMIT_ANSWER',
    `idempotency_key`  VARCHAR(64)  NOT NULL              COMMENT '客户端幂等键（UUID）',
    `request_hash`     VARCHAR(64)  NOT NULL              COMMENT '请求载荷 SHA-256 哈希',
    `session_id`       BIGINT       NOT NULL              COMMENT '会话 ID',
    `question_id`      VARCHAR(64)  NOT NULL              COMMENT '题目 ID',
    `selected_answer`  TEXT         DEFAULT NULL           COMMENT '学生已选答案',
    `status`           VARCHAR(20)  NOT NULL DEFAULT 'ACCEPTED'
        COMMENT '状态：ACCEPTED-已接受, CONFLICT-冲突',
    `response_json`    TEXT         NOT NULL              COMMENT '首次成功响应 JSON（用于重试重放）',
    `creator`          VARCHAR(64)  DEFAULT ''            COMMENT '创建者',
    `create_time`      DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updater`          VARCHAR(64)  DEFAULT ''            COMMENT '更新者',
    `update_time`      DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    `deleted`          BIT(1)       NOT NULL DEFAULT b'0' COMMENT '是否删除',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_answer_idempotency` (`tenant_id`, `user_id`, `operation`, `idempotency_key`),
    KEY `idx_tenant_session` (`tenant_id`, `session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='教育-答案命令幂等记录';

-- =============================================
-- PracticeQuestionDO: add client_sequence column
-- =============================================
-- Purpose: Track the last accepted client command sequence per question.
--   Rejects stale clientSequence: only sequences strictly greater than the
--   stored value are accepted (monotonic forward progression).
--   NULL means no answer has been accepted yet.
ALTER TABLE `education_practice_question`
    ADD COLUMN `client_sequence` INT DEFAULT NULL COMMENT '最后接受的客户端命令序号',
    ADD INDEX `idx_client_sequence` (`client_sequence`);

-- =============================================
-- PracticeSessionDO: add last_client_sequence column
-- =============================================
-- Purpose: Session-wide monotonic counter for client commands.
--   Rejects stale clientSequence across questions (not just per-question).
--   CAS incrementVersion now updates this column alongside version.
--   NULL means no answer has been accepted yet for this session.
ALTER TABLE `education_practice_session`
    ADD COLUMN `last_client_sequence` INT DEFAULT NULL COMMENT '会话级最后接受的客户端命令序号（跨题目）';

-- =============================================
-- Post-migration verification queries
-- =============================================
-- Verify new table exists:
--   SHOW CREATE TABLE education_answer_idempotency;
-- Verify unique key is enforced:
--   SHOW INDEX FROM education_answer_idempotency WHERE Key_name = 'uk_answer_idempotency';
-- Verify column added to question table:
--   SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT
--     FROM information_schema.COLUMNS
--    WHERE TABLE_SCHEMA = DATABASE()
--      AND TABLE_NAME = 'education_practice_question'
--      AND COLUMN_NAME = 'client_sequence';
-- Verify no orphan data (should be 0 after fresh migration):
--   SELECT COUNT(*) FROM education_answer_idempotency;
