import type { VonaMetaFlavor } from '@cabloy/module-info';

import boxen from 'boxen';
import chalk from 'chalk';
import { createRequire } from 'node:module';
import path from 'node:path';
import semver from 'semver';
import urllib from 'urllib';

import { getRegistry } from './registry.ts';

const boxenOptions = {
  padding: 1,
  margin: 1,
  align: 'center',
  borderColor: 'yellow',
  borderStyle: 'round',
};

export async function checkForUpdates(packageName: string) {
  try {
    // version old
    const require = createRequire(import.meta.url);
    const pkg = require(`${packageName}/package.json`);
    const versionOld = pkg.version;
    // version new
    const info = await getPackageInfo(packageName);
    const versionNew = info.version;
    // check
    const lt = semver.lt(versionOld, versionNew);
    if (!lt) return;
    // log
    let message = `[${chalk.keyword('cyan')(packageName)}] new version available: ${chalk.keyword(
      'yellow',
    )(versionOld)} → ${chalk.keyword('orange')(versionNew)}`;
    message += `\nRun ${chalk.keyword('orange')(`> pnpm add -g ${packageName} <`)} to update!`;
    // eslint-disable-next-line
    console.log('\n' + boxen(message, boxenOptions as any));
  } catch (_err) {
    // donothing
  }
}

export async function getPackageInfo(packageName: string) {
  const registry = await getRegistry();
  const result = await urllib.request(`${registry}${packageName}/latest`, {
    dataType: 'json',
    followRedirect: true,
    maxRedirects: 5,
  });
  if (result.status !== 200) {
    const message = `npm info ${packageName} got error: ${result.status}, ${result.data.reason}`;
    throw new Error(message);
  }
  return result.data;
}

export function patchFlavor(
  flavor?: VonaMetaFlavor | VonaMetaFlavor[],
): VonaMetaFlavor | undefined {
  return Array.isArray(flavor) ? flavor[flavor.length - 1] : flavor;
}

export function parseProjectPath(projectPath?: string) {
  const projectPathDefault = process.cwd();
  if (!projectPath) return projectPathDefault;
  if (path.isAbsolute(projectPath)) return projectPath;
  return path.join(projectPathDefault, projectPath);
}
