import fs from 'fs/promises';
import os from 'os';
import path from 'path';
import { VLProjectContext } from './src/vl/project-context.js';

let passed = 0;
let failed = 0;

function test(name, fn) {
  return Promise.resolve()
    .then(fn)
    .then(() => {
      console.log(`  ✓ ${name}`);
      passed++;
    })
    .catch((err) => {
      console.log(`  ✗ ${name}: ${err.message}`);
      failed++;
    });
}

function assertEqual(actual, expected, msg) {
  if (actual !== expected) {
    throw new Error(msg || `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
  }
}

function assert(cond, msg) {
  if (!cond) throw new Error(msg || 'Assertion failed');
}

console.log('\n── Project Context Regression ──');

const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'vlcode-project-context-'));
const populatedDir = path.join(tmpRoot, 'PopulatedProject');
const emptyDir = path.join(tmpRoot, 'EmptyProject');

await fs.mkdir(path.join(populatedDir, 'Apps'), { recursive: true });
await fs.mkdir(path.join(populatedDir, '.vl-code', 'rules'), { recursive: true });
await fs.mkdir(path.join(emptyDir, 'Theme'), { recursive: true });
await fs.mkdir(path.join(emptyDir, '.vl-code'), { recursive: true });

await fs.writeFile(
  path.join(populatedDir, 'Apps', 'OrdersApp.vx'),
  '// VL_VERSION:3.5\n<App_OrdersApp>\n',
  'utf8'
);
await fs.writeFile(
  path.join(populatedDir, '.vl-code', 'rules', 'naming.md'),
  '# naming rule\n',
  'utf8'
);
await fs.writeFile(
  path.join(emptyDir, 'Theme', 'Theme.vth'),
  '// VL_VERSION:3.5\n<Theme_Enterprise>\n',
  'utf8'
);
await fs.writeFile(
  path.join(emptyDir, '.vl-code', 'ProjectMeta.json'),
  JSON.stringify({ projectName: 'EmptyProject' }, null, 2),
  'utf8'
);

await test('load resets stale project identity when switching workspaces', async () => {
  const ctx = new VLProjectContext(populatedDir);
  await ctx.load();
  assertEqual(ctx.getSummary()?.projectName, 'Orders');
  assert(ctx.getRules().length > 0, 'expected rules from populated project');

  ctx.workDir = emptyDir;
  await ctx.load();

  assertEqual(ctx.getSummary()?.projectName, null, 'projectName should reset when new workspace has no app/db');
  assertEqual(ctx.getRules().length, 0, 'rules should reset when switching workspaces');
  assertEqual(ctx.getAllFiles().some((f) => f.path === 'Apps/OrdersApp.vx'), false, 'previous files should not persist');
});

await test('ProjectMeta projectName overrides generic database file names', async () => {
  const metaNamedDir = path.join(tmpRoot, 'MetaNamedProject');
  await fs.mkdir(path.join(metaNamedDir, 'Apps'), { recursive: true });
  await fs.mkdir(path.join(metaNamedDir, 'Database'), { recursive: true });
  await fs.mkdir(path.join(metaNamedDir, '.vl-code'), { recursive: true });

  await fs.writeFile(
    path.join(metaNamedDir, 'Apps', 'TodoApp.vx'),
    '// VL_VERSION:3.5\n<App_TodoApp>\n',
    'utf8'
  );
  await fs.writeFile(
    path.join(metaNamedDir, 'Database', 'main.vdb'),
    '// VL_VERSION:3.5\n<Database_Main>\n',
    'utf8'
  );
  await fs.writeFile(
    path.join(metaNamedDir, '.vl-code', 'ProjectMeta.json'),
    JSON.stringify({
      projectName: 'TodoTest',
      apps: [{ name: 'TodoApp', filePath: 'Apps/TodoApp.vx' }],
    }, null, 2),
    'utf8'
  );

  const ctx = new VLProjectContext(metaNamedDir);
  await ctx.load();
  assertEqual(ctx.getSummary()?.projectName, 'TodoTest');
});

console.log(`\n── Results ──\n\n  ${passed} passed, ${failed} failed\n`);
process.exit(failed > 0 ? 1 : 0);
