import { fileURLToPath } from 'node:url';
import { dirname, join, resolve, sep } from 'node:path';
import { sep as posixSep } from 'node:path/posix';
import { readdir, mkdir } from 'node:fs/promises';
import { styleText } from 'node:util';

// Fetch latest version

console.log(`Getting latest version of ${styleText('cyan', '@types/chrome')}`);
await Bun.$`bun install --ignore-scripts -D @types/chrome@latest`;

// Generate new package.json

console.log(`Generating new ${styleText('cyan', 'package.json')}`);

const pkgJsonPath = fileURLToPath(
  import.meta.resolve('@types/chrome/package.json'),
);
const pkgDir = dirname(pkgJsonPath);
const pkgJson = await Bun.file(pkgJsonPath).json();
const pkgJsonTemplate = await Bun.file('templates/package.json').text();
const newPkgJson = JSON.parse(
  pkgJsonTemplate.replaceAll('{{chromeTypesVersion}}', pkgJson.version),
);
newPkgJson.dependencies = pkgJson.dependencies;
newPkgJson.peerDependencies = pkgJson.peerDependencies;
newPkgJson.peerDependenciesMeta = pkgJson.peerDependenciesMeta;

const outPkgJsonPath = resolve('package.json');
await Bun.write(outPkgJsonPath, JSON.stringify(newPkgJson));
await Bun.$`bun run --cwd ../.. prettier --write "${outPkgJsonPath}"`;

// Generate declaration files

console.log('Generating declaration files');
const outDir = resolve('src/gen');
const declarationFileMapping = (
  await readdir(pkgDir, {
    recursive: true,
    encoding: 'utf8',
  })
)
  // Filter to .d.ts files
  .filter((file) => file.endsWith('.d.ts'))
  // Map to usable paths
  .map((file) => ({
    file: file.replaceAll(sep, posixSep),
    srcPath: join(pkgDir, file),
    destPath: join(outDir, file),
  }));

for (const { file, srcPath, destPath } of declarationFileMapping) {
  const content = await Bun.file(srcPath).text();
  const transformedContent = transformFile(file, content);
  const destDir = dirname(destPath);
  await mkdir(destDir, { recursive: true });
  await Bun.write(destPath, transformedContent);
  console.log(`  ${styleText('dim', '-')} ${styleText('cyan', file)}`);
}

await Bun.$`bun install --ignore-scripts`;

// Done!

console.log(
  `${styleText('green', '✔')} Done in ${performance.now().toFixed(0)} ms`,
);

// Transformations

function transformFile(file: string, content: string): string {
  return (
    // Add prefix
    `/* DO NOT EDIT - generated by scripts/generate.ts */\n\n${content}\n`
      // Remove global type declaration
      .replaceAll('chrome: typeof chrome;', '// chrome: typeof chrome;')
      // Rename `chrome` namespace to `Browser` and export it
      .replaceAll('declare namespace chrome', 'export namespace Browser')
      // Update references to `chrome` namespace to `Browser`
      .replaceAll('chrome.', 'Browser.')
      // Fix links to developer.chrome.com
      .replaceAll('developer.Browser.com', 'developer.chrome.com')
  );
}
