import * as fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import semver from 'semver';
import { checkbox } from '@inquirer/prompts';

const rootDir = path.resolve(process.cwd());

interface PackageInfo {
  'dist-tags': {
    latest: string;
  };
}

interface PackageJson {
  dependencies: {
    [key: string]: string;
  };
}

async function checkVersion(pkg: PackageJson) {
  const packageName = '@akinon/next';
  const registryUrl = `https://registry.npmjs.org/${packageName}`;

  try {
    const response = await fetch(registryUrl);
    const pkgInfo = (await response.json()) as PackageInfo;
    const latestVersion = pkgInfo['dist-tags'].latest;

    if (!semver.satisfies(pkg.dependencies['@akinon/next'], latestVersion)) {
      console.warn(
        `\x1b[43m Warning: The "${packageName}" package is currently at`,
        `\x1b[41m version ${pkg.dependencies['@akinon/next']}`,
        `\x1b[43m Please upgrade it to the latest version (${latestVersion}) to ensure plugin compatibility.`,
        '\x1b[0m\n'
      );
    } else {
      console.log(
        `\x1b[42m Info: The package "${packageName}" is currently in the current version (${latestVersion}).`,
        '\x1b[0m\n'
      );
    }
  } catch (error: any) {
    console.error(`\x1b[41mError: ${error?.message}`, '\x1b[0m\n');
  }
}

export default async () => {
  function findPluginsFilePath() {
    const option1 = path.resolve(rootDir, './src/plugins.js');
    const option2 = path.resolve(rootDir, './packages/akinon-next/plugins.js');

    if (fs.existsSync(option1)) {
      return option1;
    } else if (fs.existsSync(option2)) {
      return option2;
    } else {
      throw new Error(
        'plugins.js was not found in either of the expected locations.'
      );
    }
  }

  function findPackageJson(): PackageJson {
    const packageJsonPaths = [
      path.resolve(rootDir, './package.json'),
      path.resolve(rootDir, './apps/projectzeronext/package.json')
    ];

    for (const packageJsonPath of packageJsonPaths) {
      try {
        const pkg = require(packageJsonPath);
        if (pkg.dependencies['@akinon/next']) {
          return pkg;
        }
      } catch (error) {
        continue;
      }
    }

    throw new Error('Could not find package.json with @akinon/next dependency');
  }

  const pkg = findPackageJson();
  await checkVersion(pkg);

  const pluginsFilePath = findPluginsFilePath();

  let installedPlugins: Array<string> = [];

  try {
    installedPlugins = require(pluginsFilePath);
  } catch (error) {
    console.error('Error loading installed plugins:', error);
    process.exit(1);
  }

  const definedPlugins = [
    {
      name: 'Akifast',
      value: 'pz-akifast'
    },
    {
      name: 'Apple Pay',
      value: 'pz-apple-pay'
    },
    {
      name: 'B2B',
      value: 'pz-b2b'
    },
    {
      name: 'Basket Gift Pack',
      value: 'pz-basket-gift-pack'
    },
    {
      name: 'BKM Express',
      value: 'pz-bkm'
    },
    {
      name: 'Checkout Gift Pack',
      value: 'pz-checkout-gift-pack'
    },
    {
      name: 'Click & Collect',
      value: 'pz-click-collect'
    },
    {
      name: 'Credit Payment',
      value: 'pz-credit-payment'
    },
    {
      name: 'Garanti Pay',
      value: 'pz-gpay'
    },
    {
      name: 'Masterpass',
      value: 'pz-masterpass'
    },
    {
      name: 'Multi Basket',
      value: 'pz-multi-basket'
    },
    {
      name: 'One Click Checkout',
      value: 'pz-one-click-checkout'
    },
    {
      name: 'Otp',
      value: 'pz-otp'
    },
    {
      name: 'Pay On Delivery',
      value: 'pz-pay-on-delivery'
    },
    {
      name: 'Saved Card',
      value: 'pz-saved-card'
    },
    {
      name: 'Tabby Payment Extension',
      value: 'pz-tabby-extension'
    },
    {
      name: 'Tamara Payment Extension',
      value: 'pz-tamara-extension'
    },
    {
      name: 'Hepsipay',
      value: 'pz-hepsipay'
    },
    {
      name: 'Flow Payment',
      value: 'pz-flow-payment'
    },
    {
      name: 'Virtual Try-On',
      value: 'pz-virtual-try-on'
    },
    {
      name: 'Masterpass Rest',
      value: 'pz-masterpass-rest'
    },
    {
      name: 'Similar Products',
      value: 'pz-similar-products'
    },
    {
      name: 'Haso Payment Gateway',
      value: 'pz-haso'
    },
    {
      name: 'Google Pay',
      value: 'pz-google-pay'
    }
  ];

  try {
    const answers = await checkbox({
      message: 'Please check/uncheck plugins to install/uninstall.',
      choices: definedPlugins.map((plugin) => ({
        name: plugin.name,
        value: plugin.value,
        checked: installedPlugins.includes(plugin.value)
      }))
    });

    if (!answers.length) {
      console.log('\x1b[33m%s\x1b[0m', `\nUninstalling all plugins.`);
    }

    console.log('\x1b[36m%s\x1b[0m', `\nPlease wait...`);

    fs.writeFileSync(
      pluginsFilePath,
      `module.exports = ${JSON.stringify(answers)};\n`,
      {
        encoding: 'utf-8'
      }
    );

    execSync('yarn install', { stdio: 'pipe' });

    console.log(
      '\x1b[32m%s\x1b[0m',
      `\n✓ ${
        answers.length
          ? 'Installed selected plugins'
          : 'Uninstalled all plugins'
      }.\n`
    );
  } catch (error) {
    process.exit(1);
  }
};
