import fs from 'fs/promises';
import os from 'os';
import path from 'path';
import { execFile } from 'child_process';
import { promisify } from 'util';
import { createZipFromDir, extractZipToDir } from './src/utils/zip-extract.js';

const execFileAsync = promisify(execFile);

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 assert(cond, msg) {
  if (!cond) throw new Error(msg || 'Assertion failed');
}

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

console.log('\n── ZIP Import/Export Regression ──');

const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'vlcode-zip-'));
const wrappedRoot = path.join(tmpRoot, 'wrapped');
const targetDir = path.join(tmpRoot, 'imported');
const archivePath = path.join(tmpRoot, 'wrapped.zip');

await fs.mkdir(path.join(wrappedRoot, 'EduSystem', 'Apps'), { recursive: true });
await fs.mkdir(path.join(wrappedRoot, 'EduSystem', 'Sections'), { recursive: true });
await fs.mkdir(path.join(wrappedRoot, 'EduSystem', '.vl-code'), { recursive: true });

await fs.writeFile(path.join(wrappedRoot, 'EduSystem', 'Apps', 'StudentApp.vx'), '// VL_VERSION:3.5\n<App_StudentApp>\n', 'utf8');
await fs.writeFile(path.join(wrappedRoot, 'EduSystem', 'Sections', 'Home.sc'), '// VL_VERSION:3.5\n<Section_Home>\n', 'utf8');
await fs.writeFile(path.join(wrappedRoot, 'EduSystem', '.vl-code', 'project.json'), JSON.stringify({ projectName: 'EduSystem' }, null, 2), 'utf8');

await test('createZipFromDir packages project files including .vl-code metadata', async () => {
  const buf = await createZipFromDir(path.join(wrappedRoot, 'EduSystem'));
  await fs.writeFile(archivePath, buf);
  const { stdout } = await execFileAsync('unzip', ['-Z1', archivePath]);
  assert(stdout.includes('Apps/StudentApp.vx'), 'archive should include app files');
  assert(stdout.includes('.vl-code/project.json'), 'archive should include .vl-code metadata');
});

await test('extractZipToDir strips a single root wrapper directory on import', async () => {
  const wrappedArchive = await createZipFromDir(wrappedRoot);
  await fs.writeFile(archivePath, wrappedArchive);

  await fs.mkdir(targetDir, { recursive: true });
  await extractZipToDir(archivePath, targetDir);

  const importedApp = await fs.readFile(path.join(targetDir, 'Apps', 'StudentApp.vx'), 'utf8');
  assert(importedApp.includes('App_StudentApp'), 'expected app file at stripped path');
  let wrappedExists = true;
  try {
    await fs.access(path.join(targetDir, 'EduSystem', 'Apps', 'StudentApp.vx'));
  } catch {
    wrappedExists = false;
  }
  assertEqual(wrappedExists, false, 'wrapper directory should not be preserved');
});

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