import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import Database from 'better-sqlite3';
import { up } from '../../src/main/db/migrations/m007_fts.js';

describe('m007 migration — notes_fts virtual table + triggers', () => {
  let db: Database.Database;

  beforeEach(() => {
    db = new Database(':memory:');
    db.pragma('foreign_keys = ON');
    db.exec(`
      CREATE TABLE notes (
        id TEXT PRIMARY KEY, raw_text TEXT NOT NULL,
        ai_title TEXT, ai_summary TEXT,
        ai_status TEXT NOT NULL CHECK (ai_status IN ('pending','done','failed','disabled')),
        ai_error TEXT, ai_provider TEXT, ai_generated_at TEXT,
        title_edited_by_user INTEGER NOT NULL DEFAULT 0,
        summary_edited_by_user INTEGER NOT NULL DEFAULT 0,
        user_intent TEXT, intent_prompted_at TEXT,
        created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
        due_date TEXT, due_date_edited_by_user INTEGER NOT NULL DEFAULT 0,
        deleted_at TEXT, last_recalled_at TEXT, recall_dismissed_at TEXT,
        status TEXT NOT NULL DEFAULT 'active', status_changed_at TEXT, move_reason TEXT
      );
      CREATE TABLE tags (id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE COLLATE NOCASE);
      CREATE TABLE note_tags (
        note_id TEXT NOT NULL, tag_id INTEGER NOT NULL, source TEXT NOT NULL,
        PRIMARY KEY(note_id, tag_id),
        FOREIGN KEY(note_id) REFERENCES notes(id) ON DELETE CASCADE,
        FOREIGN KEY(tag_id) REFERENCES tags(id) ON DELETE CASCADE
      );
      INSERT INTO notes (id, raw_text, ai_title, ai_summary, ai_status, created_at, updated_at, status)
        VALUES
          ('a', '오늘 회의 정리', '회의록', '월요일 회의', 'done', '2026-05-01T00:00:00Z', '2026-05-01T00:00:00Z', 'active'),
          ('b', '예전 메모', '예전 제목', '예전 요약', 'done', '2026-04-01T00:00:00Z', '2026-04-01T00:00:00Z', 'completed'),
          ('c', '버려진 메모', '버린 제목', '버린 요약', 'done', '2026-03-01T00:00:00Z', '2026-03-01T00:00:00Z', 'trashed');
      INSERT INTO tags (id, name) VALUES (1, '기획'), (2, '회의');
      INSERT INTO note_tags (note_id, tag_id, source) VALUES ('a', 1, 'ai'), ('a', 2, 'user');
    `);
  });

  afterEach(() => { db.close(); });

  it('creates notes_fts virtual table with FTS5 columns', () => {
    up(db);
    const rows = db.prepare(`SELECT sql FROM sqlite_master WHERE name='notes_fts'`).all() as Array<{ sql: string }>;
    expect(rows).toHaveLength(1);
    expect(rows[0]!.sql.toLowerCase()).toContain('using fts5');
  });

  it('backfills active/completed notes; excludes trashed', () => {
    up(db);
    const rows = db
      .prepare(`SELECT note_id, ai_title, tags FROM notes_fts ORDER BY note_id`)
      .all() as Array<{ note_id: string; ai_title: string; tags: string }>;
    expect(rows.map((r) => r.note_id)).toEqual(['a', 'b']);
    const a = rows.find((r) => r.note_id === 'a')!;
    expect(a.ai_title).toBe('회의록');
    expect(a.tags.split(' ').sort()).toEqual(['기획', '회의']);
    const b = rows.find((r) => r.note_id === 'b')!;
    expect(b.tags).toBe('');
  });

  it('AFTER INSERT trigger syncs new note', () => {
    up(db);
    db.prepare(`INSERT INTO notes (id, raw_text, ai_title, ai_summary, ai_status, created_at, updated_at, status)
                VALUES ('d', '새 메모', '새 제목', '새 요약', 'pending', '2026-05-09T00:00:00Z', '2026-05-09T00:00:00Z', 'active')`).run();
    const r = db.prepare(`SELECT raw_text, ai_title FROM notes_fts WHERE note_id=?`).get('d') as { raw_text: string; ai_title: string };
    expect(r.raw_text).toBe('새 메모');
    expect(r.ai_title).toBe('새 제목');
  });

  it('AFTER UPDATE trigger syncs raw_text + ai_title + ai_summary', () => {
    up(db);
    db.prepare(`UPDATE notes SET raw_text=?, ai_title=?, ai_summary=?, updated_at=? WHERE id=?`)
      .run('수정한 본문', '수정 제목', '수정 요약', '2026-05-10T00:00:00Z', 'a');
    const r = db.prepare(`SELECT raw_text, ai_title, ai_summary FROM notes_fts WHERE note_id=?`).get('a') as {
      raw_text: string; ai_title: string; ai_summary: string;
    };
    expect(r.raw_text).toBe('수정한 본문');
    expect(r.ai_title).toBe('수정 제목');
    expect(r.ai_summary).toBe('수정 요약');
  });

  it('AFTER DELETE trigger removes FTS row', () => {
    up(db);
    db.prepare(`DELETE FROM notes WHERE id=?`).run('a');
    const r = db.prepare(`SELECT * FROM notes_fts WHERE note_id=?`).all('a');
    expect(r).toHaveLength(0);
  });

  it('exports version=7', async () => {
    const mod = await import('../../src/main/db/migrations/m007_fts.js');
    expect(mod.version).toBe(7);
  });
});
