import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, rmSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
import { Repository } from './repository.js';
import { bootstrapSystemDek, getOrCreateUserDek } from '../ssh/crypto.js';

// Regression: SSH connection creation in no-auth mode returned `create_failed`.
// Root cause — `ssh_user_deks.user_id REFERENCES users(id)` with foreign keys
// ON (Repository enables the pragma). No-auth owns rows under the synthetic
// 'local' id, but no `users` row with id='local' exists, so the lazy DEK insert
// hit a FK violation and getOrCreateUserDek threw → create_failed. Seeding the
// 'local' user row satisfies the FK (and the whole class of users(id) FKs).
const VALID_KEY = 'a'.repeat(64);

describe('Repository.ensureLocalUser (no-auth SSH create_failed fix)', () => {
  let tmpDir = '';
  let repo: Repository;

  beforeEach(() => {
    process.env.MCP_ENCRYPTION_KEY = VALID_KEY;
    tmpDir = mkdtempSync(join(tmpdir(), 'ensure-local-'));
    repo = new Repository(join(tmpDir, 'db.sqlite')); // constructor enables foreign_keys=ON
    bootstrapSystemDek(repo.getDb());
  });

  afterEach(() => {
    repo.close();
    rmSync(tmpDir, { recursive: true, force: true });
    delete process.env.MCP_ENCRYPTION_KEY;
  });

  it('reproduces the bug: creating a DEK for owner "local" throws when the user row is absent', () => {
    expect(() => getOrCreateUserDek(repo.getDb(), 'local')).toThrow();
  });

  it('after ensureLocalUser the per-user DEK insert (and thus SSH create) succeeds', () => {
    repo.ensureLocalUser();
    const dek = getOrCreateUserDek(repo.getDb(), 'local');
    expect(Buffer.isBuffer(dek)).toBe(true);
    expect(dek.length).toBe(32);
  });

  it('is idempotent — repeated calls keep a single "local" user', () => {
    repo.ensureLocalUser();
    repo.ensureLocalUser();
    const u = repo.getUserById('local');
    expect(u?.id).toBe('local');
    expect(u?.name).toBe('local');
  });
});
