#!/usr/bin/env node

"use strict";
const path = require("path");
const { execSync } = require("child_process");

const userAgent = process.env.npm_config_user_agent ?? "";
const packageManager = /pnpm/.test(userAgent)
    ? "pnpm"
    : /yarn/.test(userAgent)
        ? "yarn"
        : "npm";

console.log(`Initializing...\n`);
execSync(packageManager === "yarn" ? "yarn" : `${packageManager} install`, { cwd: __dirname });

const DEFAULT_PROJECT_NAME = "actindo-plugin";

async function init() {
  const minimist = require("minimist");
  const prompts = require("prompts");
  const { red, green, bold } = require("kolorist");
  const { isValidPluginName, toValidPluginName } = require("./utils/validators");
  const { copyFolder, ifEmpty, prepareFolder, renameFile } = require("./utils/folders");
  const {
    printHelpContent,
    parseCommand,
    patchPackageFile,
  } = require("./utils/helpers");

  const argv = minimist(process.argv.slice(2), {
    alias: {
      "folder-name": ["n"],
      "plugin-name": ["p"],
      "force-overwrite": ["f"],
      "sample": ["s"],
      help: ["h"],
    },
    booleanValue: true,
  });

  if (argv.h) {
    printHelpContent();
    process.exit(0);
  }

  const targetBase = process.cwd();

  let responses;
  try {
    responses = await prompts(
      [
        {
          name: "folderName",
          type: argv.n ? null : "text",
          message: "Folder name:",
          initial: DEFAULT_PROJECT_NAME,
        },
        {
          name: "shouldOverwrite",
          type: (folderName) =>
            argv.f ||
            ifEmpty(
              path.resolve(
                targetBase,
                folderName ?? argv.n ?? DEFAULT_PROJECT_NAME,
              ),
            )
              ? null
              : "confirm",
          message: (folderName) => {
            const targetPath = path.resolve(targetBase, folderName);
            const dirForPrompt =
              targetPath === "."
                ? "Current directory"
                : `Target directory "${targetPath}"`;

            return `${dirForPrompt} is not empty. Remove existing files and continue?`;
          },
        },
        {
          name: "overwriteChecker",
          type: (prev, values) => {
            if (values.shouldOverwrite === false) {
              throw new Error(red("✖") + " Operation cancelled");
            }
            return null;
          },
        },
        {
          name: "pluginName",
          type: () => (isValidPluginName(argv.p) ? null : "text"),
          message: "Plugin name:",
          initial: () => toValidPluginName(argv.p ?? DEFAULT_PROJECT_NAME),
          validate: (dir) => isValidPluginName(dir) || "Invalid plugin name",
        },
        {
          name: "sample",
          type: () => argv.s ? null : "confirm",
          message: "Copy sample code?",
          initial: true
        },
      ],
      {
        onCancel: () => {
          throw new Error(red("✖") + " Operation cancelled");
        },
      },
    );
  } catch (error) {
    console.log(error.message);
    process.exit(1);
  }

  const {
    folderName = argv.n ?? DEFAULT_PROJECT_NAME,
    pluginName = argv.p ?? DEFAULT_PROJECT_NAME,
    shouldOverwrite,
    sample = argv.s,
  } = responses;

  const templateFolder = sample ? "template" : "template1";
  const sourcePath = path.join(__dirname, templateFolder);
  const targetFolder = path.resolve(targetBase, folderName);

  prepareFolder(targetFolder, shouldOverwrite);

  console.log(`\nScaffolding project in ${targetFolder}...`);

  copyFolder(sourcePath, targetFolder);
  renameFile(targetFolder, "_gitignore", ".gitignore");
  renameFile(targetFolder, "_env", ".env");

  patchPackageFile(
    pluginName,
    path.join(__dirname, templateFolder, "package.json"),
    path.resolve(targetFolder, "package.json"),
  );

  console.log(`\nDone. Now run:\n`);

  if (targetFolder !== targetBase) {
    const cdProjectName = path.relative(targetBase, targetFolder);
    console.log(
      `  ${bold(
        green(
          `cd ${
            cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName
          }`,
        ),
      )}`,
    );
  }

  console.log(`  ${bold(green(parseCommand(packageManager, "install")))}`);
  console.log(`  ${bold(green(parseCommand(packageManager, "dev")))}`);
  console.log(
    `\n${bold(green("Check the instructions in the file README.md"))}\n`,
  );
}

init().catch((e) => console.error(e));