-- Migration 004: Full schema reset
-- Drops legacy flat tables (questions, vocab, user_progress)
-- Creates new hierarchical schema from supabase/create/ files
-- Adapted for Supabase: users(id) → auth.users(id) UUID
-- Tables kept intact: writing_submissions, user_gamification, xu_transactions, weekly_leaderboard

-- ============================================================
-- DROP LEGACY TABLES
-- ============================================================
DROP TABLE IF EXISTS user_progress CASCADE;
DROP TABLE IF EXISTS vocab CASCADE;
DROP TABLE IF EXISTS questions CASCADE;

-- ============================================================
-- TEST STRUCTURE
-- (from create/test.sql + create/update.sql merged)
-- ============================================================

CREATE TABLE test_category (
  id    SERIAL PRIMARY KEY,
  name  VARCHAR(100) NOT NULL,
  slug  VARCHAR(100) UNIQUE
);

CREATE TABLE test (
  id                SERIAL PRIMARY KEY,
  title             VARCHAR(255) NOT NULL,
  description       TEXT,
  total_questions   INT DEFAULT 0,
  duration_minutes  INT DEFAULT 120,
  category_id       INT REFERENCES test_category(id),
  created_at        TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE part (
  id              SERIAL PRIMARY KEY,
  test_id         INT NOT NULL REFERENCES test(id) ON DELETE CASCADE,
  part_number     INT NOT NULL,
  title           VARCHAR(100) NOT NULL,
  question_count  INT DEFAULT 0,
  display_order   INT DEFAULT 0,
  UNIQUE (test_id, part_number)
);

CREATE TABLE tag (
  id    SERIAL PRIMARY KEY,
  name  VARCHAR(255) NOT NULL UNIQUE
);

CREATE TABLE part_tag (
  part_id  INT NOT NULL REFERENCES part(id) ON DELETE CASCADE,
  tag_id   INT NOT NULL REFERENCES tag(id) ON DELETE CASCADE,
  PRIMARY KEY (part_id, tag_id)
);

CREATE TABLE question_group (
  id             SERIAL PRIMARY KEY,
  part_id        INT NOT NULL REFERENCES part(id) ON DELETE CASCADE,
  audio_url      VARCHAR(500),
  image_url      VARCHAR(500),
  passage_text   TEXT,
  display_order  INT DEFAULT 0
);

CREATE TABLE question (
  id               SERIAL PRIMARY KEY,
  group_id         INT NOT NULL REFERENCES question_group(id) ON DELETE CASCADE,
  question_number  INT NOT NULL,
  question_text    TEXT,
  explanation      TEXT,
  display_order    INT DEFAULT 0
);

CREATE TABLE answer_choice (
  id           SERIAL PRIMARY KEY,
  question_id  INT NOT NULL REFERENCES question(id) ON DELETE CASCADE,
  value        CHAR(1) NOT NULL CHECK (value IN ('A', 'B', 'C', 'D')),
  label_text   TEXT,
  is_correct   BOOLEAN NOT NULL DEFAULT FALSE
);

-- ============================================================
-- FLASHCARD SYSTEM
-- (from create/flash_card.sql)
-- adapted: user_id / created_by → auth.users(id) UUID
-- ============================================================

CREATE TABLE flashcard_list (
  id           SERIAL PRIMARY KEY,
  title        VARCHAR(255) NOT NULL,
  description  TEXT,
  total_words  INT DEFAULT 0,
  is_public    BOOLEAN DEFAULT TRUE,
  created_by   UUID REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE flashcard_term (
  id              SERIAL PRIMARY KEY,
  list_id         INT NOT NULL REFERENCES flashcard_list(id) ON DELETE CASCADE,
  word            VARCHAR(255) NOT NULL,
  part_of_speech  VARCHAR(50),
  phonetic        VARCHAR(100),
  definition      TEXT,
  example         TEXT,
  image_url       VARCHAR(500),
  audio_tts_text  VARCHAR(255),
  audio_lang      VARCHAR(10) DEFAULT 'en-US',
  display_order   INT DEFAULT 0,
  created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE user_flashcard_list (
  user_id      UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  list_id      INT NOT NULL REFERENCES flashcard_list(id) ON DELETE CASCADE,
  enrolled_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (user_id, list_id)
);

CREATE TABLE user_flashcard_progress (
  id                SERIAL PRIMARY KEY,
  user_id           UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  term_id           INT NOT NULL REFERENCES flashcard_term(id) ON DELETE CASCADE,
  list_id           INT NOT NULL REFERENCES flashcard_list(id) ON DELETE CASCADE,
  status            VARCHAR(20) NOT NULL DEFAULT 'new',  -- new | learning | known | ignored
  ease_factor       DECIMAL(4,2) DEFAULT 1.0,            -- 1.0=easy | 0.65=medium | 0.1=hard | -1=known/ignored
  review_count      INT DEFAULT 0,
  last_reviewed_at  TIMESTAMP,
  next_review_at    TIMESTAMP,
  UNIQUE (user_id, term_id, list_id)
);

CREATE TABLE user_flashcard_session (
  id              SERIAL PRIMARY KEY,
  user_id         UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  list_id         INT NOT NULL REFERENCES flashcard_list(id) ON DELETE CASCADE,
  started_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  ended_at        TIMESTAMP,
  terms_reviewed  INT DEFAULT 0,
  terms_new       INT DEFAULT 0
);

CREATE TABLE user_flashcard_review_log (
  id            SERIAL PRIMARY KEY,
  session_id    INT NOT NULL REFERENCES user_flashcard_session(id) ON DELETE CASCADE,
  term_id       INT NOT NULL REFERENCES flashcard_term(id) ON DELETE CASCADE,
  user_id       UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  action_value  DECIMAL(4,2) NOT NULL,  -- 1 | 0.65 | 0.1 | -1
  reviewed_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE user_flashcard_settings (
  user_id          UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  list_id          INT NOT NULL REFERENCES flashcard_list(id) ON DELETE CASCADE,
  daily_new_limit  INT DEFAULT 20,
  shuffle          BOOLEAN DEFAULT TRUE,
  front_side       VARCHAR(10) DEFAULT 'word',  -- 'word' | 'definition'
  show_all_terms   BOOLEAN DEFAULT FALSE,
  PRIMARY KEY (user_id, list_id)
);

-- ============================================================
-- USER TEST HISTORY
-- (from create/user_test_history.sql)
-- adapted: user_id → auth.users(id) UUID
-- ============================================================

CREATE TABLE user_test_attempt (
  id                  SERIAL PRIMARY KEY,
  user_id             UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  test_id             INT NOT NULL REFERENCES test(id) ON DELETE CASCADE,
  selected_parts      INT[],
  time_limit_minutes  INT,
  started_at          TIMESTAMP,
  submitted_at        TIMESTAMP,
  time_spent_seconds  INT,
  total_correct       INT DEFAULT 0,
  total_questions     INT DEFAULT 0,
  score               DECIMAL(5,2),
  created_at          TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE user_answer (
  id              SERIAL PRIMARY KEY,
  attempt_id      INT NOT NULL REFERENCES user_test_attempt(id) ON DELETE CASCADE,
  question_id     INT NOT NULL REFERENCES question(id),
  selected_value  CHAR(1),
  is_correct      BOOLEAN,
  UNIQUE (attempt_id, question_id)
);

-- ============================================================
-- INDEXES
-- ============================================================

-- test structure
CREATE INDEX idx_part_test_id        ON part(test_id);
CREATE INDEX idx_qgroup_part_id      ON question_group(part_id);
CREATE INDEX idx_question_group_id   ON question(group_id);
CREATE INDEX idx_answer_question_id  ON answer_choice(question_id);
CREATE INDEX idx_test_category_id    ON test(category_id);

-- flashcard
CREATE INDEX idx_term_list_id           ON flashcard_term(list_id);
CREATE INDEX idx_term_display_order     ON flashcard_term(list_id, display_order);
CREATE INDEX idx_progress_user          ON user_flashcard_progress(user_id);
CREATE INDEX idx_progress_next_review   ON user_flashcard_progress(user_id, next_review_at);
CREATE INDEX idx_progress_status        ON user_flashcard_progress(user_id, list_id, status);
CREATE INDEX idx_review_log_session     ON user_flashcard_review_log(session_id);
CREATE INDEX idx_enrolled_user          ON user_flashcard_list(user_id);

-- test history
CREATE INDEX idx_attempt_user_id   ON user_test_attempt(user_id);
CREATE INDEX idx_attempt_test_id   ON user_test_attempt(test_id);
CREATE INDEX idx_answer_attempt_id ON user_answer(attempt_id);

-- ============================================================
-- ROW LEVEL SECURITY
-- ============================================================

-- test content: public read, no direct user writes
ALTER TABLE test_category   ENABLE ROW LEVEL SECURITY;
ALTER TABLE test             ENABLE ROW LEVEL SECURITY;
ALTER TABLE part             ENABLE ROW LEVEL SECURITY;
ALTER TABLE tag              ENABLE ROW LEVEL SECURITY;
ALTER TABLE part_tag         ENABLE ROW LEVEL SECURITY;
ALTER TABLE question_group   ENABLE ROW LEVEL SECURITY;
ALTER TABLE question         ENABLE ROW LEVEL SECURITY;
ALTER TABLE answer_choice    ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Public read test_category"  ON test_category  FOR SELECT USING (true);
CREATE POLICY "Public read test"           ON test           FOR SELECT USING (true);
CREATE POLICY "Public read part"           ON part           FOR SELECT USING (true);
CREATE POLICY "Public read tag"            ON tag            FOR SELECT USING (true);
CREATE POLICY "Public read part_tag"       ON part_tag       FOR SELECT USING (true);
CREATE POLICY "Public read question_group" ON question_group FOR SELECT USING (true);
CREATE POLICY "Public read question"       ON question       FOR SELECT USING (true);
CREATE POLICY "Public read answer_choice"  ON answer_choice  FOR SELECT USING (true);

-- flashcard lists/terms: public lists readable by all, private by owner only
ALTER TABLE flashcard_list ENABLE ROW LEVEL SECURITY;
ALTER TABLE flashcard_term ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Public read public lists"
  ON flashcard_list FOR SELECT
  USING (is_public = true OR auth.uid() = created_by);

CREATE POLICY "Owners can insert lists"
  ON flashcard_list FOR INSERT
  WITH CHECK (auth.uid() = created_by);

CREATE POLICY "Public read terms of public lists"
  ON flashcard_term FOR SELECT
  USING (
    EXISTS (
      SELECT 1 FROM flashcard_list fl
      WHERE fl.id = flashcard_term.list_id
        AND (fl.is_public = true OR fl.created_by = auth.uid())
    )
  );

-- flashcard user data: users own their rows
ALTER TABLE user_flashcard_list        ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_flashcard_progress    ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_flashcard_session     ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_flashcard_review_log  ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_flashcard_settings    ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users own flashcard_list enrollment"   ON user_flashcard_list       FOR ALL USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users own flashcard progress"          ON user_flashcard_progress   FOR ALL USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users own flashcard sessions"          ON user_flashcard_session    FOR ALL USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users own review logs"                 ON user_flashcard_review_log FOR ALL USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users own flashcard settings"          ON user_flashcard_settings   FOR ALL USING (auth.uid() = user_id) WITH CHECK (auth.uid() = user_id);

-- test attempt history: users own their rows
ALTER TABLE user_test_attempt  ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_answer        ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users own test attempts"
  ON user_test_attempt FOR ALL
  USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can read own answers"
  ON user_answer FOR SELECT
  USING (
    EXISTS (
      SELECT 1 FROM user_test_attempt uta
      WHERE uta.id = user_answer.attempt_id
        AND uta.user_id = auth.uid()
    )
  );

CREATE POLICY "Users can insert own answers"
  ON user_answer FOR INSERT
  WITH CHECK (
    EXISTS (
      SELECT 1 FROM user_test_attempt uta
      WHERE uta.id = user_answer.attempt_id
        AND uta.user_id = auth.uid()
    )
  );
