import { existsSync, readdirSync, readFileSync, writeFileSync, statSync } from 'fs';
import { join, extname, relative } from 'path';
import { fileURLToPath } from 'url';

const MIME: Record<string, string> = {
  '.html': 'text/html',
  '.css': 'text/css',
  '.js': 'text/javascript',
  '.mjs': 'text/javascript',
  '.json': 'application/json',
  '.png': 'image/png',
  '.jpg': 'image/jpeg',
  '.gif': 'image/gif',
  '.svg': 'image/svg+xml',
  '.ico': 'image/x-icon',
  '.woff': 'font/woff',
  '.woff2': 'font/woff2',
};

export type AssetEntry = { content: string; mime: string };
export type AssetMap = Record<string, AssetEntry>;

function collectFiles(dir: string, acc: string[]): void {
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    if (statSync(full).isDirectory()) {
      collectFiles(full, acc);
    } else {
      acc.push(full);
    }
  }
}

export function generateAssetMap(webDir: string): AssetMap {
  if (!existsSync(webDir)) {
    throw new Error(
      `dist/web directory not found at: ${webDir}\nRun npm run build:web first.`
    );
  }

  const files: string[] = [];
  collectFiles(webDir, files);

  const map: AssetMap = {};
  for (const filePath of files) {
    const rel = relative(webDir, filePath);
    const urlKey = '/' + rel.replace(/\\/g, '/');
    const ext = extname(filePath).toLowerCase();
    const mime = MIME[ext] ?? 'application/octet-stream';
    const content = readFileSync(filePath).toString('base64');
    map[urlKey] = { content, mime };
  }
  return map;
}

// Only run as a script (not when imported by tests)
const isMain =
  typeof process !== 'undefined' &&
  process.argv[1] !== undefined &&
  (process.argv[1].endsWith('embed-web-assets.ts') ||
    process.argv[1].endsWith('embed-web-assets.js'));

if (isMain) {
  const repoRoot = join(fileURLToPath(import.meta.url), '..', '..');
  const webDir = join(repoRoot, 'dist', 'web');
  const outFile = join(repoRoot, 'src', 'cli', 'playground', 'embedded-assets.ts');

  console.log(`Embedding ${webDir} -> ${outFile}`);

  const map = generateAssetMap(webDir);
  const entries = Object.entries(map)
    .map(
      ([k, v]) =>
        `  ${JSON.stringify(k)}: { content: ${JSON.stringify(v.content)}, mime: ${JSON.stringify(v.mime)} }`
    )
    .join(',\n');

  const output = [
    '// AUTO-GENERATED by scripts/embed-web-assets.ts - do not edit manually.',
    '// Restored to empty stub by git checkout after binary compilation.',
    'export type AssetEntry = { content: string; mime: string };',
    'export type AssetMap = Record<string, AssetEntry>;',
    'export const EMBEDDED_WEB_ASSETS: AssetMap = {',
    entries,
    '};',
    '',
  ].join('\n');

  writeFileSync(outFile, output, 'utf8');
  console.log(`Done. Embedded ${Object.keys(map).length} file(s).`);
}
