#!/usr/bin/env node
import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

import { ProductDefinitionError, resolveProductDefinition } from './resolver.mjs';

export function extractProductConfigArg(args) {
  const forwardArgs = [];
  let productConfig;
  for (let index = 0; index < args.length; index += 1) {
    const argument = args[index];
    const inline = argument.startsWith('--product-config=')
      ? argument.slice('--product-config='.length)
      : undefined;
    if (argument === '--product-config' || inline !== undefined) {
      const value = inline ?? args[++index];
      if (!value || value === '--') {
        throw new ProductDefinitionError(
          'missing_product_config_value',
          '--product-config requires a file path.',
          'Pass --product-config products/example/product.jsonc.',
        );
      }
      if (productConfig !== undefined) {
        throw new ProductDefinitionError(
          'duplicate_product_config',
          '--product-config was provided more than once.',
          'Keep one explicit product-definition path.',
        );
      }
      productConfig = value;
    } else {
      forwardArgs.push(argument);
    }
  }
  return { productConfig, forwardArgs };
}

function diagnosticArgs(args) {
  const { productConfig, forwardArgs } = extractProductConfigArg(args);
  let member = 'desktop';
  for (let index = 0; index < forwardArgs.length; index += 1) {
    const argument = forwardArgs[index];
    if (argument === '--' && index === 0) continue;
    if (argument === '--member') member = forwardArgs[++index];
    else if (argument.startsWith('--member=')) member = argument.slice('--member='.length);
    else throw new ProductDefinitionError('unknown_diagnostic_option', `Unsupported option: ${argument}`, 'Use only --product-config and --member.');
  }
  return { productConfig, member };
}

export function explainProduct(resolution) {
  return {
    definition: resolution.sourcePath,
    member: resolution.assembly.member,
    binaryName: resolution.assembly.binaryName,
    bundleId: resolution.assembly.bundleId,
    localizedNames: resolution.productNames,
    localeDigest: resolution.assembly.localeDigest,
    assemblyDigest: resolution.assembly.assemblyDigest,
    implementedScope: 'identity-and-localized-name-c0a',
  };
}

async function main() {
  const rootDir = resolve(import.meta.dirname, '..', '..');
  const [command = 'check', ...args] = process.argv.slice(2);
  const { productConfig, member } = diagnosticArgs(args);
  const resolution = resolveProductDefinition({ rootDir, productConfig, member });
  if (command === 'check') {
    console.log(JSON.stringify({
      ok: true,
      member,
      assemblyDigest: resolution.assembly.assemblyDigest,
    }));
    return;
  }
  if (command === 'explain') {
    console.log(JSON.stringify(explainProduct(resolution), null, 2));
    return;
  }
  throw new ProductDefinitionError('unknown_product_command', `Unknown command: ${command}`, 'Use check or explain.');
}

if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
  main().catch((error) => {
    if (error instanceof ProductDefinitionError) {
      console.error(JSON.stringify({ ok: false, code: error.code, message: error.message, action: error.action }));
    } else {
      console.error(error?.stack || error);
    }
    process.exitCode = 1;
  });
}