/* This file is a part of @mdn/browser-compat-data
 * See LICENSE file for more information. */
import fs, { existsSync } from 'node:fs';
import path from 'node:path';

import esMain from 'es-main';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { temporaryDirectoryTask } from 'tempy';

import { spawn, spawnAsync } from '../utils/index.js';

/**
 * Compare two references and print diff as Markdown or JSON
 * @param {object} opts - Options
 * @param {string | undefined} opts.ref1 - First reference to compare
 * @param {string | undefined} opts.ref2 - Second reference to compare
 * @param {string} [opts.format] - Format to export data as (either 'markdown' or 'json', default 'json')
 * @param {boolean} [opts.github] - Whether to obtain artifacts from GitHub
 */
const main = async (opts) => {
  const { ref1, ref2, format, github } = opts;
  const results = await diff({ ref1, ref2, github });

  if (format === 'markdown') {
    printMarkdown(results.added, results.removed);
  } else {
    console.log(JSON.stringify(results, undefined, 2));
  }
};

/**
 * Compare two references and get feature diff
 * @param {object} opts - Options
 * @param {string} [opts.ref1] - First reference to compare
 * @param {string} [opts.ref2] - Second reference to compare
 * @param {boolean} [opts.github] - Whether to obtain artifacts from GitHub
 * @param {boolean} [opts.quiet] - If true, don't log to console
 * @returns {Promise<{ added: string[]; removed: string[] }>} Diff between two refs
 */
const diff = async (opts) => {
  const { ref1, ref2, github, quiet } = opts;
  let refA, refB;

  if (ref1 === undefined && ref2 === undefined) {
    // No refs: compare HEAD to parent commit
    refA = 'HEAD^';
    refB = 'HEAD';
  } else if (ref2 === undefined) {
    // One ref: compare ref to parent of ref
    refB = `${ref1}`;
    refA = `${ref1}^`;
  } else {
    // Two refs: compare ref2 to ref1
    refA = `${ref2}`;
    refB = `${ref1}`;
  }

  const aSide = await enumerate(refA, github === false, quiet);
  const bSide = await enumerate(refB, github === false, quiet);

  return {
    added: [...bSide].filter((feature) => !aSide.has(feature)),
    removed: [...aSide].filter((feature) => !bSide.has(feature)),
  };
};

/**
 * Enumerate features from GitHub or local checkout
 * @param {string} ref - Reference to obtain features for
 * @param {boolean} skipGithub - Skip fetching artifacts from GitHub
 * @param {boolean} [quiet] - If true, don't log to console
 * @returns {Promise<Set<string>>} Feature list from reference
 */
const enumerate = async (ref, skipGithub, quiet = false) => {
  if (!skipGithub) {
    try {
      return new Set(await getEnumerationFromGithub(ref));
    } catch (e) {
      if (!quiet) {
        console.error(
          `Fetching artifact from GitHub failed: ${e} Using fallback.`,
        );
      }
    }
  }

  return new Set(enumerateFeatures(ref, quiet));
};

/**
 * Enumerate features from GitHub
 * @param {string} ref - Reference to obtain features for
 * @returns {Promise<string[]>} Feature list from reference
 */
const getEnumerationFromGithub = async (ref) => {
  const ENUMERATE_WORKFLOW = '15595228';
  const ENUMERATE_WORKFLOW_ARTIFACT = 'enumerate-features';
  const ENUMERATE_WORKFLOW_FILE = 'features.json';

  const hash = await spawnAsync('git', ['rev-parse', ref]);
  const workflowRun = await spawnAsync('gh', [
    'api',
    `/repos/:owner/:repo/actions/workflows/${ENUMERATE_WORKFLOW}/runs?head_sha=${hash}&per_page=1`,
    '--jq',
    `[.workflow_runs[] | select(.head_sha=="${hash}") | .id] | first`,
  ]);

  if (!workflowRun) {
    throw Error('No workflow run found for commit.');
  }

  return await temporaryDirectoryTask(async (tempdir) => {
    await spawnAsync('gh', [
      'run',
      'download',
      workflowRun,
      '-n',
      ENUMERATE_WORKFLOW_ARTIFACT,
      '--dir',
      tempdir,
    ]);
    const file = path.join(tempdir, ENUMERATE_WORKFLOW_FILE);

    return JSON.parse(fs.readFileSync(file, { encoding: 'utf-8' }));
  });
};

/**
 * Enumerate features from local checkout
 * @param {string} [ref] - Reference to obtain features for
 * @param {boolean} [quiet] - If true, don't log to console
 * @returns {string[]} Feature list from reference
 */
const enumerateFeatures = (ref = 'HEAD', quiet = false) => {
  // GitHub API returns wrong merge commit for https://github.com/mdn/browser-compat-data/pull/25668.
  ref = ref.replace(
    '19d8ce0fd1016c3cd1cb6f7b98f72e99ae2f3f16',
    '3af3a24bdf71f5393893f3724bc47acdd23acfe0',
  );

  // Get the short hash for this ref.
  // Most of the time, you check out named references (a branch or a tag).
  // However, if `ref` is already checked out, then `git worktree add` fails. As
  // long as you haven't checked out a detached HEAD for `ref`, then
  // `git worktree add` for the hash succeeds.
  const hash = spawn('git', ['rev-parse', '--short', ref]);

  const worktree = `__enumerating__${hash}`;

  if (!quiet) {
    console.error(`Enumerating features for ${ref} (${hash})`);
  }

  try {
    spawn('git', ['worktree', 'add', worktree, hash]);

    try {
      spawn('npm', ['ci'], { cwd: worktree });
    } catch {
      // If the clean install fails, proceed anyways
    }
    if (existsSync(`${worktree}/index.js`)) {
      spawn('node', [
        './scripts/enumerate-features.js',
        `--data-from=${worktree}`,
      ]);
    } else if (existsSync(`${worktree}/index.ts`)) {
      spawn('npx', [
        '-y',
        'tsx@^4.19.2',
        `${worktree}/scripts/enumerate-features.ts`,
        `--data-from=${worktree}`,
      ]);
    } else {
      throw Error('Could not find index.{js,ts}!');
    }
    return JSON.parse(fs.readFileSync('.features.json', { encoding: 'utf-8' }));
  } finally {
    spawn('git', ['worktree', 'remove', worktree]);
  }
};

/**
 * Format feature for Markdown printing
 * @param {string} feat - Feature
 * @returns {string} Formatted feature
 */
const fmtFeature = (feat) => `- \`${feat}\``;

/**
 * Print feature diff as Markdown
 * @param {string[]} added - List of added features
 * @param {string[]} removed - List of removed features
 */
const printMarkdown = (added, removed) => {
  if (removed.length) {
    console.log('## Removed\n');
    console.log(removed.map(fmtFeature).join('\n'));
  }
  if (added.length) {
    if (removed.length) {
      console.log('');
    }
    console.log('## Added\n');
    console.log(added.map(fmtFeature).join('\n'));
  }
};

if (esMain(import.meta)) {
  const argv = yargs(hideBin(process.argv))
    .command('$0 [ref1] [ref2]', 'Compare the set of features at refA and refB')
    .positional('ref1', {
      type: 'string',
      description: 'A Git ref (branch, tag, or commit)',
      defaultDescription: 'ref1^',
    })
    .positional('ref2', {
      type: 'string',
      description: 'A Git ref (branch, tag, or commit)',
      defaultDescription: 'HEAD',
    })
    .option('format', {
      type: 'string',
      nargs: 1,
      choices: /** @type {const} */ (['json', 'markdown']),
      demandOption: 'a named format is required',
      default: 'markdown',
    })
    .option('github', {
      type: 'boolean',
      description: 'Fetch artifacts from GitHub.',
      default: true,
    })
    .example('$0', 'compare HEAD to parent commit')
    .example('$0 176d4ed', 'compare 176d4ed to its parent commit')
    .example('$0 topic-branch main', 'compare a branch to main')
    .parseSync();

  const { ref1, ref2, format, github } = argv;

  await main({ ref1, ref2, format, github });
}

export default diff;
