#!/usr/bin/env node

import { access, lstat, mkdir, readFile, readdir, rename, rm } from 'node:fs/promises';
import { execFile, spawn } from 'node:child_process';
import { promisify } from 'node:util';
import { fileURLToPath } from 'node:url';
import path from 'node:path';

const execFileAsync = promisify(execFile);

function run(command, args, options) {
  return new Promise((resolve, reject) => {
    const child = spawn(command, args, options);
    child.once('error', reject);
    child.once('exit', (code, signal) => {
      if (code === 0) resolve();
      else reject(new Error(signal ? `husky terminated by ${signal}` : `husky exited ${code}`));
    });
  });
}

async function pathExists(target) {
  try {
    await access(target);
    return true;
  } catch (error) {
    if (error.code === 'ENOENT') return false;
    throw error;
  }
}

async function directorySnapshot(root) {
  const snapshot = [];
  async function walk(current) {
    const children = await readdir(current, { withFileTypes: true });
    for (const child of children.sort((left, right) => left.name.localeCompare(right.name))) {
      const target = path.join(current, child.name);
      const relative = path.relative(root, target);
      const stats = await lstat(target);
      if (child.isDirectory()) {
        snapshot.push([relative, 'directory', stats.mode & 0o777]);
        await walk(target);
      } else {
        snapshot.push([
          relative,
          'file',
          stats.mode & 0o777,
          (await readFile(target)).toString('base64'),
        ]);
      }
    }
  }
  await walk(root);
  return JSON.stringify(snapshot);
}

async function directoriesMatch(left, right) {
  return (await directorySnapshot(left)) === (await directorySnapshot(right));
}

export async function installHooks({
  root = process.cwd(),
  disabled = process.env.HUSKY === '0',
  quarantineRoot = path.join(root, '.mosaic-test-work', 'husky-quarantine'),
  runHusky = async (_stagingHooks, stagingRepo) => {
    await execFileAsync('git', ['init', '--quiet', stagingRepo]);
    await run(path.join(root, 'node_modules', '.bin', 'husky'), ['.husky'], {
      cwd: stagingRepo,
      stdio: 'inherit',
    });
  },
  activateHooks = async () => {
    await run('git', ['config', 'core.hooksPath', '.husky/_'], { cwd: root, stdio: 'inherit' });
  },
} = {}) {
  if (disabled) return;

  try {
    await execFileAsync('git', ['--version']);
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.warn('git not found; skipping hook installation');
      return;
    }
    throw error;
  }

  const huskyDir = path.join(root, '.husky');
  const active = path.join(huskyDir, '_');
  const nonce = `${Date.now()}-${process.pid}`;
  const stagingRepo = path.join(root, '.mosaic-test-work', `husky-stage-${nonce}`);
  const stagingHooks = path.join(stagingRepo, '.husky');
  const quarantined = path.join(quarantineRoot, `${path.basename(root)}-${nonce}`);
  await mkdir(huskyDir, { recursive: true });
  await mkdir(quarantineRoot, { recursive: true });

  const previousComplete = (await pathExists(active)) && (await pathExists(path.join(active, 'h')));
  let previousQuarantined = false;
  try {
    if ((await pathExists(active)) && !previousComplete) {
      await rename(active, quarantined);
      previousQuarantined = true;
    }
    await mkdir(stagingRepo, { recursive: true });
    await runHusky(stagingHooks, stagingRepo);
    const staged = path.join(stagingHooks, '_');
    if (!(await pathExists(path.join(staged, 'h')))) {
      throw new Error('husky did not produce its required h shim');
    }
    if (previousComplete) {
      if (!(await directoriesMatch(active, staged))) {
        throw new Error('existing complete hook set differs from the installed Husky version');
      }
      await rm(stagingRepo, { recursive: true, force: true });
    } else {
      await rename(staged, active);
      await rm(stagingRepo, { recursive: true, force: true });
    }
    await activateHooks();
    if (previousQuarantined) {
      try {
        await rm(quarantined, { recursive: true, force: true });
      } catch {
        console.warn(
          `Previous hook state was deactivated but remains quarantined at ${quarantined}`,
        );
      }
    }
  } catch (error) {
    const cleanupFailures = [];
    try {
      if (await pathExists(stagingRepo)) {
        await rename(stagingRepo, `${quarantined}-staging`);
      }
    } catch (cleanupError) {
      cleanupFailures.push(`staging hooks: ${cleanupError.message}`);
    }
    const cleanup =
      cleanupFailures.length === 0
        ? 'No partial hook set was activated.'
        : `Automatic cleanup was incomplete (${cleanupFailures.join('; ')}).`;
    throw new Error(
      `Hook installation failed: ${error.message}. ${cleanup} Fix: rm -rf .husky/_ && git config core.hooksPath .husky/_ && pnpm install --frozen-lockfile`,
      { cause: error },
    );
  }
}

if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
  try {
    await installHooks();
  } catch (error) {
    console.error(error.message);
    process.exitCode = 1;
  }
}
