#!/usr/bin/env node

import { cli } from 'cleye';

import packageJSON from '../package.json';
import { commit } from './commands/commit';
import { commitlintConfigCommand } from './commands/commitlint';
import { configCommand, getConfig } from './commands/config';
import { hookCommand, isHookCalled } from './commands/githook.js';
import { prepareCommitMessageHook } from './commands/prepare-commit-msg-hook';
import { resolveProxy, setupProxy } from './utils/proxy';
import {
  setupCommand,
  isFirstRun,
  runSetup,
  promptForMissingApiKey
} from './commands/setup';
import { modelsCommand } from './commands/models';
import { checkIsLatestVersion } from './utils/checkIsLatestVersion';
import { runMigrations } from './migrations/_run.js';

const config = getConfig();
setupProxy(resolveProxy(config.OCO_PROXY));

const OCO_FLAGS_WITH_VALUE = new Set(['-c', '--context']);
const OCO_BOOLEAN_FLAGS = new Set(['-y', '--yes', '--fgm']);
const OCO_EQUALS_PREFIXES = ['-c=', '--context=', '-y=', '--yes=', '--fgm='];

const stripOcoFlags = (argv: string[]): string[] => {
  const out: string[] = [];
  for (let i = 0; i < argv.length; i++) {
    const a = argv[i];
    // String flags with a separate value token: -c <val>, --context <val>
    if (OCO_FLAGS_WITH_VALUE.has(a)) {
      i++; // skip the value token too
      continue;
    }
    // Boolean flags: -y, --yes, --fgm
    if (OCO_BOOLEAN_FLAGS.has(a)) {
      continue;
    }
    // Equals form: -c=…, --context=…, -y=…, --yes=…, --fgm=…
    if (OCO_EQUALS_PREFIXES.some((prefix) => a.startsWith(prefix))) {
      continue;
    }
    out.push(a);
  }
  return out;
};

const rawArgv = process.argv.slice(2);
const extraArgs = stripOcoFlags(rawArgv);

cli(
  {
    version: packageJSON.version,
    name: 'opencommit',
    commands: [
      configCommand,
      hookCommand,
      commitlintConfigCommand,
      setupCommand,
      modelsCommand
    ],
    flags: {
      fgm: {
        type: Boolean,
        description: 'Use full GitMoji specification',
        default: false
      },
      context: {
        type: String,
        alias: 'c',
        description: 'Additional user input context for the commit message',
        default: ''
      },
      yes: {
        type: Boolean,
        alias: 'y',
        description: 'Skip commit confirmation prompt',
        default: false
      }
    },
    ignoreArgv: (type) => type === 'unknown-flag' || type === 'argument',
    help: { description: packageJSON.description }
  },
  async ({ flags }) => {
    if (await isHookCalled()) {
      await prepareCommitMessageHook();
      return;
    }

    await runMigrations();
    await checkIsLatestVersion();

    // Check for first run and trigger setup wizard
    if (isFirstRun()) {
      const setupComplete = await runSetup();
      if (!setupComplete) {
        process.exit(1);
      }
    }

    // Check for missing API key and prompt if needed
    const hasApiKey = await promptForMissingApiKey();
    if (!hasApiKey) {
      process.exit(1);
    }

    commit(extraArgs, flags.context, false, flags.fgm, flags.yes);
  },
  rawArgv
);
