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

import chalk from 'chalk-template';
import esMain from 'es-main';
import { markdownTable } from 'markdown-table';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';

import bcdData from '../index.js';
import {
  BrowserName,
  CompatStatement,
  SupportStatement,
  Identifier,
} from '../types/types.js';

import { getRefDate } from './release/utils.js';

interface VersionStatsEntry {
  all: number;
  exact: number;
  range: number;
}

type VersionStats = Record<string, VersionStatsEntry>;

const webextensionsBrowsers: BrowserName[] = [
  'chrome',
  'edge',
  'firefox',
  'opera',
  'safari',
  'firefox_android',
  'safari_ios',
];

/**
 * Check whether a support statement is a specified type
 * @param supportData The support statement to check
 * @param type What type of support (true, null, ranged)
 * @returns If the support statement has the type
 */
const checkSupport = (
  supportData: SupportStatement | undefined,
  type: string | boolean | null,
): boolean => {
  if (!supportData) {
    return type === null;
  }
  if (Array.isArray(supportData)) {
    return supportData.some((s) => checkSupport(s, type));
  }
  if (type == '≤') {
    return (
      (typeof supportData.version_added == 'string' &&
        supportData.version_added.startsWith('≤')) ||
      (typeof supportData.version_removed == 'string' &&
        supportData.version_removed.startsWith('≤'))
    );
  }
  return (
    supportData.version_added === type || supportData.version_removed === type
  );
};

/**
 * Iterate through all of the browsers and count the number of exact ranged values for each browser
 * @param data The data to process and count stats for
 * @param browsers The browsers to test
 * @param stats The stats object to update
 */
const processData = (
  data: CompatStatement,
  browsers: BrowserName[],
  stats: VersionStats,
): void => {
  if (data.support) {
    browsers.forEach((browser) => {
      stats[browser].all++;
      stats.total.all++;
      if (checkSupport(data.support[browser], '≤')) {
        stats[browser].range++;
        stats.total.range++;
      } else {
        stats[browser].exact++;
        stats.total.exact++;
      }
    });
  }
};

/**
 * Iterate through all of the data and process statistics
 * @param data The compat data to iterate
 * @param browsers The browsers to test
 * @param stats The stats object to update
 */
const iterateData = (
  data: Identifier,
  browsers: BrowserName[],
  stats: VersionStats,
) => {
  for (const key in data) {
    if (key === '__compat') {
      // "as CompatStatement" needed because TypeScript doesn't realize key is in data
      processData(data[key] as CompatStatement, browsers, stats);
    } else {
      iterateData(data[key], browsers, stats);
    }
  }
};

/**
 * Get all of the stats
 * @param folder The folder to show statistics for (or all folders if blank)
 * @param allBrowsers If true, get stats for all browsers, not just main eight
 * @param bcd The BCD data to use. Defaults to the main BCD data.
 * @returns The statistics
 */
const getStats = (
  folder: string,
  allBrowsers: boolean,
  bcd = bcdData,
): VersionStats | null => {
  const browsers: BrowserName[] = allBrowsers
    ? (Object.keys(bcd.browsers) as (keyof typeof bcd.browsers)[])
    : folder === 'webextensions'
      ? webextensionsBrowsers
      : ([
          'chrome',
          'chrome_android',
          'edge',
          'firefox',
          'safari',
          'safari_ios',
          'webview_android',
        ] as BrowserName[]);

  const stats: VersionStats = {
    total: { all: 0, range: 0, exact: 0 },
  };
  browsers.forEach((browser) => {
    stats[browser] = { all: 0, range: 0, exact: 0 };
  });

  if (folder) {
    if (folder === 'webextensions') {
      iterateData(bcd[folder], webextensionsBrowsers, stats);
    } else if (bcd[folder]) {
      iterateData(bcd[folder], browsers, stats);
    } else {
      if (process.env.NODE_ENV !== 'test') {
        console.error(chalk`{red.bold Folder "${folder}/" doesn't exist!}`);
      }
      return null;
    }
  } else {
    for (const data in bcd) {
      if (data === 'webextensions') {
        iterateData(
          bcd[data],
          browsers.filter((b) => webextensionsBrowsers.includes(b)),
          stats,
        );
      } else if (data !== 'browsers') {
        iterateData(bcd[data], browsers, stats);
      }
    }
  }

  return stats;
};

/**
 * Get value as either percentage or number as requested
 * @param stats The stats object to get data from
 * @param type The type of statistic to obtain
 * @param counts Whether to return the integer itself
 * @returns The percentage or count
 */
const getStat = (
  stats: VersionStatsEntry,
  type: keyof VersionStatsEntry,
  counts: boolean,
): string | number =>
  counts ? stats[type] : `${((stats[type] / stats.all) * 100).toFixed(2)}%`;

/**
 * Print statistics of BCD
 * @param stats The stats object to print from
 * @param folder The folder to show statistics for (or all folders if blank)
 * @param counts Whether to display a count vs. a percentage
 */
const printStats = (
  stats: VersionStats | null,
  folder: string,
  counts: boolean,
): void => {
  if (!stats) {
    console.error(`No stats${folder ? ` for folder ${folder}` : ''}!`);
    return;
  }

  const releaseDate = getRefDate('v' + process.env.npm_package_version).slice(
    0,
    'YYYY-MM-DD'.length,
  );

  console.log(
    chalk`{bold Status as of version ${
      process.env.npm_package_version
    } (released on ${releaseDate}) for ${
      folder ? `the \`${folder}/\` directory` : 'web platform features'
    }}: \n`,
  );

  const header = ['browser', 'exact', 'ranged'];
  const align = ['l', 'r', 'r'];
  const rows = Object.keys(stats).map((entry) =>
    [
      entry,
      getStat(stats[entry], 'exact', counts),
      getStat(stats[entry], 'range', counts),
    ].map(String),
  );

  const table = markdownTable([header, ...rows], { align });

  console.log(table);
};

if (esMain(import.meta)) {
  const { argv }: { argv } = yargs(hideBin(process.argv)).command(
    '$0 [folder]',
    'Print a markdown-formatted table displaying the statistics of exact and values for each browser',
    (yargs) => {
      yargs
        .positional('folder', {
          describe: 'Limit the statistics to a specific folder',
          type: 'string',
          default: '',
        })
        .option('all', {
          alias: 'a',
          describe: 'Show statistics for all browsers within BCD',
          type: 'boolean',
          nargs: 0,
        })
        .option('counts', {
          alias: 'c',
          describe: 'Show feature count rather than percentages',
          type: 'boolean',
          nargs: 0,
        });
    },
  );

  printStats(getStats(argv.folder, argv.all), argv.folder, argv.counts);
}

export default getStats;
