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

describe('BrowserSessionRepo', () => {
  let tempDir = '';
  let repository: Repository;
  let db: Database.Database;
  let repo: BrowserSessionRepo;

  beforeEach(() => {
    tempDir = mkdtempSync(join(tmpdir(), 'maestro-bsr-'));
    const dbPath = join(tempDir, 'orchestrator.db');
    repository = new Repository(dbPath);
    db = repository.getDb();
    // Seed a user
    db.prepare(`INSERT INTO users (id, email, role, status, created_at, updated_at)
                VALUES (?, ?, 'active', 'active', datetime('now'), datetime('now'))`)
      .run('u1', 'u1@test');
    repo = new BrowserSessionRepo(db);
  });

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

  it('upserts and reads a user DEK', () => {
    repo.setUserDek('u1', Buffer.from('a'.repeat(48)));
    const out = repo.getUserDek('u1');
    expect(out?.toString()).toBe('a'.repeat(48));
  });

  it('creates a profile then loads it by id with owner check', () => {
    const id = repo.createProfile({
      ownerId: 'u1', label: 'GitHub', startUrl: 'https://github.com',
      matchPatterns: ['https://github.com/**'], storageOrigins: ['https://github.com'],
      loggedInSelector: 'header [aria-label*="View profile"]',
      loginUrlPatterns: ['https://github.com/login**'],
    });
    const profile = repo.getProfileById(id, 'u1');
    expect(profile?.label).toBe('GitHub');
    expect(profile?.matchPatterns).toEqual(['https://github.com/**']);
    expect(repo.getProfileById(id, 'someone-else')).toBeNull();
  });

  it('lists only the caller’s profiles', () => {
    repo.createProfile({ ownerId: 'u1', label: 'A', startUrl: 'https://a.com', matchPatterns: [], storageOrigins: [], loginUrlPatterns: [] });
    db.prepare(`INSERT INTO users (id, email, role, status, created_at, updated_at)
                VALUES ('u2','u2@test','active','active',datetime('now'),datetime('now'))`).run();
    repo.createProfile({ ownerId: 'u2', label: 'B', startUrl: 'https://b.com', matchPatterns: [], storageOrigins: [], loginUrlPatterns: [] });
    expect(repo.listProfilesByOwner('u1').length).toBe(1);
    expect(repo.listProfilesByOwner('u1')[0]!.label).toBe('A');
  });

  it('saves an encrypted blob and bumps state_version', () => {
    const id = repo.createProfile({ ownerId: 'u1', label: 'X', startUrl: 'https://x.com', matchPatterns: [], storageOrigins: [], loginUrlPatterns: [] });
    repo.saveProfileBlob(id, Buffer.from('encrypted'), '1.40.0');
    const p = repo.getProfileById(id, 'u1');
    expect(p?.encryptedStateBlob?.toString()).toBe('encrypted');
    expect(p?.stateVersion).toBe(1);
    expect(p?.status).toBe('active');
    repo.saveProfileBlob(id, Buffer.from('encrypted2'), '1.40.0');
    expect(repo.getProfileById(id, 'u1')?.stateVersion).toBe(2);
  });

  it('marks profile expired with reason', () => {
    const id = repo.createProfile({ ownerId: 'u1', label: 'X', startUrl: 'https://x.com', matchPatterns: [], storageOrigins: [], loginUrlPatterns: [] });
    repo.markProfileStatus(id, 'expired', 'redirected to /login');
    const p = repo.getProfileById(id, 'u1');
    expect(p?.status).toBe('expired');
    expect(p?.lastError).toBe('redirected to /login');
  });

  it('writes audit entries', () => {
    const id = repo.createProfile({ ownerId: 'u1', label: 'X', startUrl: 'https://x.com', matchPatterns: [], storageOrigins: [], loginUrlPatterns: [] });
    repo.audit({ actorUserId: 'u1', ownerId: 'u1', profileId: id, action: 'create', result: 'success' });
    const rows = db.prepare('SELECT * FROM browser_session_audit').all() as Array<{ action: string; result: string }>;
    expect(rows.length).toBe(1);
    expect(rows[0]!.action).toBe('create');
  });
});
