/* This file is a part of @mdn/browser-compat-data
 * See LICENSE file for more information. */

/** @import {InternalSupportStatement, InternalIdentifier, BrowserName} from '../types/index.js' */

import { styleText } from 'node:util';

import deepDiff from 'deep-diff';
import esMain from 'es-main';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';

import { query } from '../utils/index.js';

import { getMergeBase, getFileContent, getGitDiffStatuses } from './lib/git.js';
import mirror from './build/mirror.js';

/**
 * @typedef {object} Contents
 * @property {string} base The file contents at the base commit
 * @property {string} head The file contents at the head commit
 */

/**
 * @typedef {object} DiffItem
 * @property {string} name The name of the changed feature
 * @property {string} description The description of the change
 */

/**
 * Get contents from base and head commits
 * Note: This does not detect renamed files
 * @param {string} baseCommit - Base commit
 * @param {string} basePath - Base path
 * @param {string} headCommit - Head commit
 * @param {string} headPath - Head path
 * @returns {Contents} The contents of both commits
 */
const getBaseAndHeadContents = (baseCommit, basePath, headCommit, headPath) => {
  const base = JSON.parse(getFileContent(baseCommit, basePath));
  const head = JSON.parse(getFileContent(headCommit, headPath));
  return { base, head };
};

/**
 * Returns a formatted string of before-and-after changes
 * @param {any} lhs - Left-hand (before) side
 * @param {any} rhs - Right-hand (after) side
 * @returns {string} Formatted string
 */
const stringifyChange = (lhs, rhs) =>
  `${JSON.stringify(lhs)} → ${JSON.stringify(rhs)}`;

/**
 * Perform mirroring on specified diff statement
 * @param {object} diff - The diff to perform mirroring on
 * @param {InternalSupportStatement} diff.base - The support statement of the base side
 * @param {InternalSupportStatement} diff.head - The support statement of the head side
 * @param {object} contents - The contents to mirror from
 * @param {InternalIdentifier} contents.base - The identifier of the base side
 * @param {InternalIdentifier} contents.head - The identifier of the head side
 * @param {string[]} path - The feature path to mirror
 * @param {'base' | 'head'} direction - Whether to mirror 'base' or 'head'
 */
const doMirror = (diff, contents, path, direction) => {
  const browser = /** @type {BrowserName} */ (path[path.length - 1]);
  const dataPath = path.slice(0, path.length - 3).join('.');
  const data = contents[direction];
  const queried = /** @type {InternalIdentifier} */ (query(dataPath, data));

  if (queried.__compat?.support) {
    diff[direction] = mirror(browser, queried.__compat.support);
  }
};

/**
 * Describe the diff in text form (internal function)
 * @param {import('deep-diff').Diff<string, string>} diffItem - The diff to describe
 * @param {Contents} contents - The contents of the diff
 * @returns {string} A human-readable diff description
 */
const describeByKind = (diffItem, contents) => {
  const diff = {
    base: /** @type {any} */ (diffItem).lhs,
    head: /** @type {any} */ (diffItem).rhs,
  };

  // Handle mirroring
  let doesMirror = '';
  if (diff.base === 'mirror') {
    doesMirror = 'No longer mirrors';
    doMirror(
      diff,
      /** @type {any} */ (contents),
      /** @type {string[]} */ (diffItem.path),
      'base',
    );
  } else if (diff.head === 'mirror') {
    doesMirror = 'Now mirrors';
    doMirror(
      diff,
      /** @type {any} */ (contents),
      /** @type {string[]} */ (diffItem.path),
      'head',
    );
  }

  switch (diffItem.kind) {
    case 'N':
      return 'added';
    case 'D':
      return 'deleted';
    case 'A':
    case 'E':
      return `edited (${stringifyChange(diff.base, diff.head)})${
        doesMirror && ` - ${doesMirror}`
      }`;
    default:
      return '';
  }
};

/**
 * Describe the diff in text form
 * @param {import('deep-diff').Diff<string, string>} diffItem - The diff to describe
 * @param {Contents} contents - The contents of the diff
 * @returns {DiffItem} A human-readable diff description
 */
const describeDiffItem = (diffItem, contents) => {
  const path = /** @type {string[]} */ (diffItem.path).join('.');
  if (path.includes('.__compat.')) {
    const [name, member] = path.split('.__compat.');
    if (path.endsWith('.notes') && diffItem.kind === 'E') {
      return { name, description: `${member} is edited (prose change)` };
    }
    return {
      name,
      description: `${member} is ${describeByKind(diffItem, contents)}`,
    };
  }
  return {
    name: /** @type {string[]} */ (diffItem.path).slice(0, -1).join('.'),
    description: `${path} is ${describeByKind(diffItem, contents)}`,
  };
};

/**
 * Merge diff together as a map
 * @param {DiffItem[]} items - Diff items to merge
 * @returns {Map<string, string[]>} A map of the diff items
 */
const mergeAsMap = (items) => {
  const map = new Map();
  for (const item of items) {
    const descriptions = map.get(item.name) || [];
    descriptions.push(item.description);
    map.set(item.name, descriptions);
  }
  return map;
};

/**
 * Get the diffs as a map
 * @param {string} base - Base ref
 * @param {string} [head] - Head ref
 * @returns {Map<string, string[]>} A map of the diff items
 */
const getDiffs = (base, head = '') => {
  /** @type {{ name: string; description: string }[]} */
  const namedDescriptions = [];
  for (const status of getGitDiffStatuses(base, head)) {
    if (!status.headPath.endsWith('.json') || !status.headPath.includes('/')) {
      continue;
    }

    // Note that A means Added for git while it means Array for deep-diff
    if (status.value === 'A' || status.value === 'D') {
      namedDescriptions.push({
        name: status.basePath.replace(/\//g, '.').slice(0, -5), // trim file extension
        description: status.value === 'A' ? 'Newly added' : 'Entirely removed',
      });
    } else {
      const contents = getBaseAndHeadContents(
        base,
        status.basePath,
        head,
        status.headPath,
      );
      const diff = deepDiff.diff(contents.base, contents.head);
      if (diff) {
        namedDescriptions.push(
          ...diff.map((item) => describeDiffItem(item, contents)),
        );
      }
    }
  }
  return mergeAsMap(namedDescriptions);
};

if (esMain(import.meta)) {
  const argv = yargs(hideBin(process.argv))
    .command(
      '$0 [base] [head]',
      'Print a formatted diff for changes between base and head commits',
    )
    .positional('base', {
      describe:
        'The base commit; may be commit hash or other git ref (e.g. "origin/main")',
      type: 'string',
      default: 'origin/main',
    })
    .positional('head', {
      describe:
        'The head commit that changes are applied to; may be commit hash or other git ref (e.g. "origin/main")',
      type: 'string',
      default: 'HEAD',
    })
    .parseSync();

  const { base, head } = argv;
  for (const [key, values] of getDiffs(getMergeBase(base, head), head)) {
    console.log(`${styleText('bold', key)}:`);
    for (const value of values) {
      console.log(` → ${value}`);
    }
  }
}
