/**
 * @license
 * Copyright 2026 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import type {cliOptions} from '../bin/chrome-devtools-mcp-cli-options.js';
import {toSnakeCase} from '../utils/string.js';

import {stripUnderscoreBeforeNumber} from './transformation.js';
import type {FlagUsage} from './types.js';

type CliOptions = typeof cliOptions;

/**
 * For enums, log the value as uppercase.
 * We're going to have an enum for such flags with choices represented
 * as an `enum` where the keys of the enum will map to the uppercase `choice`.
 */
function formatEnumChoice(snakeCaseName: string, choice: string): string {
  return stripUnderscoreBeforeNumber(
    `${snakeCaseName}_${choice}`,
  ).toUpperCase();
}

/**
 * Computes telemetry flag usage from parsed arguments and CLI options.
 *
 * Iterates over the defined CLI options to construct a payload:
 * - Flag names are converted to snake_case (e.g. `browserUrl` -> `browser_url`).
 * - A flag is logged as `{flag_name}_present` if:
 *    - It has no default value, OR
 *    - The provided value differs from the default value.
 * - Boolean flags are logged with their literal value.
 * - String flags with defined `choices` (Enums) are logged as their uppercase value.
 *
 * IMPORTANT: keep getPossibleFlagMetrics() in sync with this function.
 */
export function computeFlagUsage(
  args: Record<string, unknown>,
  options: CliOptions,
): FlagUsage {
  const usage: FlagUsage = {};

  for (const [flagName, config] of Object.entries(options)) {
    const value = args[flagName];
    const snakeCaseName = stripUnderscoreBeforeNumber(toSnakeCase(flagName));

    // If there isn't a default value provided for the flag,
    // we're going to log whether it's present on the args user
    // provided or not. If there is a default value, we only log presence
    // if the value differs from the default, implying explicit user intent.
    if (!('default' in config) || value !== config.default) {
      usage[`${snakeCaseName}_present`] = value !== undefined && value !== null;
    }

    if (config.type === 'boolean' && typeof value === 'boolean') {
      // For boolean options, we're going to log the value directly.
      usage[snakeCaseName] = value;
    } else if (
      config.type === 'string' &&
      typeof value === 'string' &&
      'choices' in config &&
      config.choices
    ) {
      usage[snakeCaseName] = formatEnumChoice(snakeCaseName, value);
    }
  }

  return usage;
}

export interface FlagMetric {
  name: string;
  flagType: 'boolean' | 'enum';
  choices?: string[];
}

/**
 * Computes the list of possible flag metrics based on the CLI options.
 *
 * IMPORTANT: keep this function in sync with computeFlagUsage().
 */
export function getPossibleFlagMetrics(options: CliOptions): FlagMetric[] {
  const metrics: FlagMetric[] = [];

  for (const [flagName, config] of Object.entries(options)) {
    const snakeCaseName = stripUnderscoreBeforeNumber(toSnakeCase(flagName));

    // _present is always a possible metric
    metrics.push({
      name: `${snakeCaseName}_present`,
      flagType: 'boolean',
    });

    if (config.type === 'boolean') {
      metrics.push({
        name: snakeCaseName,
        flagType: 'boolean',
      });
    } else if (
      config.type === 'string' &&
      'choices' in config &&
      config.choices
    ) {
      metrics.push({
        name: snakeCaseName,
        flagType: 'enum',
        choices: [
          `${snakeCaseName.toUpperCase()}_UNSPECIFIED`,
          ...config.choices.map(choice =>
            formatEnumChoice(snakeCaseName, choice),
          ),
        ],
      });
    }
  }

  return metrics;
}
