import { getConfigPath } from '@mintlify/prebuild';
import { MintConfigUpdater } from '@mintlify/prebuild';
import { upgradeToDocsConfig } from '@mintlify/validation';
import Chalk from 'chalk';
import detect from 'detect-port';
import fse from 'fs-extra';
import fs from 'fs/promises';
import inquirer from 'inquirer';
import Ora, { Ora as OraType } from 'ora';
import path from 'path';
import type { ArgumentsCamelCase } from 'yargs';

import { CMD_EXEC_PATH } from './constants.js';

export const checkPort = async (argv: ArgumentsCamelCase): Promise<number | undefined> => {
  const initialPort = typeof argv.port === 'number' ? argv.port : 3000;
  if (initialPort === (await detect(initialPort))) return initialPort;

  for (let port = initialPort + 1; port < initialPort + 10; port++) {
    console.log(`Port ${port - 1} is already in use. Trying ${port} instead.`);
    if (port === (await detect(port))) return port;
  }
};

export const checkNodeVersion = async () => {
  let nodeVersionString = process.version;
  if (nodeVersionString.charAt(0) === 'v') {
    nodeVersionString = nodeVersionString.slice(1);
  }
  const versionArr = nodeVersionString.split('.');
  const majorVersion = parseInt(versionArr[0]!, 10);

  if (majorVersion < 18) {
    const logger = buildLogger();
    logger.fail(
      `Mintlify requires a node version >= 18.0.0 (current version ${nodeVersionString}). Try removing the mintlify package, upgrading node, reinstalling mintlify, and running again.`
    );
    process.exit(1);
  }
};

export const buildLogger = (startText = ''): OraType => {
  const logger = Ora().start(startText);
  return logger;
};

export const checkForMintJson = async () => {
  return !!(await getConfigPath(CMD_EXEC_PATH, 'mint'));
};

export const checkForDocsJson = async () => {
  const docsJsonPath = path.join(CMD_EXEC_PATH, 'docs.json');
  if (!(await fse.pathExists(docsJsonPath))) {
    console.log('New docs.json file is available.');
    const promptResult = await inquirer.prompt([
      {
        type: 'list',
        name: 'action',
        message: 'Would you like to upgrade your mint.json to docs.json?',
        choices: [
          { name: 'Continue (use existing mint.json)', value: 'continue' },
          { name: 'Upgrade (migrate from mint.json -> docs.json)', value: 'upgrade' },
        ],
      },
    ]);

    const { action } = promptResult;

    if (action === 'continue') {
      console.log('Proceeding with the existing mint.json...');
    }

    if (action === 'upgrade') {
      console.log('Upgrading docs.json...');
      await upgradeConfig();
    }
  }
};

export const upgradeConfig = async () => {
  try {
    const mintJsonPath = path.join(CMD_EXEC_PATH, 'mint.json');
    const docsJsonPath = path.join(CMD_EXEC_PATH, 'docs.json');
    const mintJsonFileContent = await fs.readFile(mintJsonPath, 'utf8');
    const validationResult = await MintConfigUpdater.validateConfigJsonString(mintJsonFileContent);
    const mintConfig = validationResult.data;
    const upgradedDocsConfig = upgradeToDocsConfig(mintConfig, {
      shouldUpgradeTheme: true,
    });
    await fs.writeFile(docsJsonPath, JSON.stringify(upgradedDocsConfig, null, 2));
    console.log(Chalk.green('✅ Your mint.json file has been upgraded to v2 (docs.json).'));
  } catch (err) {
    console.error(Chalk.red(err));
    process.exit(1);
  }
};
