import { afterEach, describe, expect, it } from 'vitest';
import Database from 'better-sqlite3';
import { mkdtempSync, rmSync, readFileSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
import { Repository } from './repository.js';

describe('browser session persistence migrations', () => {
  let tempDir = '';

  afterEach(() => {
    if (tempDir) {
      rmSync(tempDir, { recursive: true, force: true });
      tempDir = '';
    }
  });

  it('creates the new tables and columns via Repository constructor', () => {
    tempDir = mkdtempSync(join(tmpdir(), 'maestro-bsm-'));
    const dbPath = join(tempDir, 'orchestrator.db');
    // Repository constructor runs schema.sql + idempotent migrations.
    new Repository(dbPath);

    const db = new Database(dbPath, { readonly: true });
    try {
      const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all() as Array<{ name: string }>;
      const names = new Set(tables.map(t => t.name));
      expect(names.has('user_deks')).toBe(true);
      expect(names.has('browser_session_profiles')).toBe(true);
      expect(names.has('browser_session_audit')).toBe(true);

      const localCols = db.prepare("PRAGMA table_info('local_tasks')").all() as Array<{ name: string }>;
      expect(localCols.some(c => c.name === 'browser_session_profile_id')).toBe(true);

      const scheduledCols = db.prepare("PRAGMA table_info('scheduled_tasks')").all() as Array<{ name: string }>;
      expect(scheduledCols.some(c => c.name === 'browser_session_profile_id')).toBe(true);

      const jobCols = db.prepare("PRAGMA table_info('jobs')").all() as Array<{ name: string }>;
      expect(jobCols.some(c => c.name === 'browser_session_profile_id')).toBe(true);
    } finally {
      db.close();
    }
  });

  it('schema.sql alone (without migrations) creates the new tables', () => {
    const db = new Database(':memory:');
    try {
      const schema = readFileSync(new URL('./schema.sql', import.meta.url), 'utf-8');
      db.exec(schema);

      const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all() as Array<{ name: string }>;
      const names = new Set(tables.map(t => t.name));
      expect(names.has('user_deks')).toBe(true);
      expect(names.has('browser_session_profiles')).toBe(true);
      expect(names.has('browser_session_audit')).toBe(true);
    } finally {
      db.close();
    }
  });

  it('rejects invalid status / action / result values', () => {
    const tmp = mkdtempSync(join(tmpdir(), 'crg-mig-'));
    const dbPath = join(tmp, 'test.db');
    new Repository(dbPath);
    const db = new Database(dbPath);

    expect(() => db.prepare(
      `INSERT INTO browser_session_profiles (owner_id, label, start_url, status)
       VALUES ('u1','x','https://x.com','garbage')`
    ).run()).toThrow();

    expect(() => db.prepare(
      `INSERT INTO browser_session_audit (action, result) VALUES ('garbage','success')`
    ).run()).toThrow();

    expect(() => db.prepare(
      `INSERT INTO browser_session_audit (action, result) VALUES ('create','garbage')`
    ).run()).toThrow();

    db.close();
    rmSync(tmp, { recursive: true, force: true });
  });
});
