-- 301_eid_study_weakness.sql
-- 이드 학습 약점 스냅샷 (append-only derived-fact). eid_study_weakness 워커가 study_question_progress
-- + study_quiz_sessions 집계로 산출(LLM 0). study_diagnosis 표면이 최신 행을 읽어 코치 발화.
--
-- ★ append-only 구조강제 (project_eid_persona_substrate 불변식 #8) — 2중:
--   (1) INSERT 스탬프 누락 거부: actor·source_generated_at = NOT NULL·DEFAULT 없음
--       → 스탬프 없는 INSERT 를 DB 가 거부. NOT NULL 은 owner 포함 모든 role 에 적용(role 독립).
--   (2) UPDATE/DELETE 차단: CREATE RULE ... DO INSTEAD NOTHING → 행 불변(owner·superuser 독립).
--
-- ★ 설계 원안 'REVOKE UPDATE,DELETE' 정정(load-bearing): 단일 DB role `pkm` 이 테이블 OWNER 라
--   REVOKE 가 무효(owner 는 GRANT/REVOKE 우회). plpgsql trigger(RAISE)는 migration 검증기가
--   본문의 BEGIN 키워드를 거부(_validate_sql_content)해 불가. → RULE 이 owner 독립 + 검증기 통과하는
--   유일한 구조 enforcement(silent no-op, 행은 구조적으로 불변). 별도 read-only role 미존재.
--
-- ★ '현재' 스냅샷 = 최신 created_at 행(WHERE status='active'). 상태전이 UPDATE 없음(append-only).
--   dispute = status='disputed' + supersedes_id 로 특정 스냅샷 무효화(새 INSERT). 표면이 disputed 제외.
--
-- runner = exec_driver_sql(simple protocol) → multi-statement 처리(001_initial_schema 선례, 18 stmt).
-- BEGIN/COMMIT/ROLLBACK 없음(검증기 통과). CREATE RULE 은 IF NOT EXISTS 미지원 → OR REPLACE 로 idempotent.

CREATE TABLE IF NOT EXISTS eid_study_weakness (
    id                   BIGSERIAL   PRIMARY KEY,
    user_id              BIGINT      NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    weaknesses           JSONB       NOT NULL,   -- [{topic_id,topic,chronic,relapsed,leech,coverage_gap,unsure,overdue,trend,tier}]
    habit_signals        JSONB       NOT NULL,   -- {avoidance_topics,session_abandon_rate,stale_due_count,skew_topics}
    trend_label          VARCHAR(20) NOT NULL,   -- overall 개선|정체|악화 (코드 산출)
    sample_attempts      INTEGER     NOT NULL DEFAULT 0,
    is_shallow_sample    BOOLEAN     NOT NULL DEFAULT false,
    status               VARCHAR(20) NOT NULL DEFAULT 'active',  -- 'active' | 'disputed'(dispute marker)
    supersedes_id        BIGINT      REFERENCES eid_study_weakness(id) ON DELETE SET NULL,
    actor                VARCHAR(20) NOT NULL,   -- 스탬프(no default) = 'eid'
    source_generated_at  TIMESTAMPTZ NOT NULL,   -- 스탬프(no default) = 집계 시점
    created_at           TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE OR REPLACE RULE eid_study_weakness_no_update AS ON UPDATE TO eid_study_weakness DO INSTEAD NOTHING;
CREATE OR REPLACE RULE eid_study_weakness_no_delete AS ON DELETE TO eid_study_weakness DO INSTEAD NOTHING;

CREATE INDEX IF NOT EXISTS idx_eid_weakness_user_current
    ON eid_study_weakness (user_id, created_at DESC) WHERE status = 'active';
