import { join } from 'path';
import { existsSync, promises as fs } from 'fs';
import { simpleGit } from 'simple-git';
import { input } from '@inquirer/prompts';
import { EMULSIFY_PROJECT_CONFIG_FILE, EMULSIFY_PROJECT_HOOK_INIT, EMULSIFY_PROJECT_HOOK_FOLDER, } from '../lib/constants.js';
import getPlatformInfo from '../util/platform/getPlatformInfo.js';
import getAvailableStarters from '../util/getAvailableStarters.js';
import writeToJsonFile from '../util/fs/writeToJsonFile.js';
import strToMachineName from '../util/strToMachineName.js';
import installDependencies from '../util/project/installDependencies.js';
import executeScript from '../util/fs/executeScript.js';
import getInitSuccessMessageForPlatform from '../util/platform/getInitSuccessMessageForPlatform.js';
import log from '../lib/log.js';
import CliError from '../lib/CliError.js';
const git = simpleGit();
export const DIRECTORY = 1;
const DEFAULT_PROJECT_NAME = 'emulsifyTheme';
const DEFAULT_PLATFORM = 'drupal';
export default function init(progress) {
    return async (name, targetDirectory, options) => {
        const { name: autoPlatformName, emulsifyParentDirectory } = (await getPlatformInfo()) || {};
        const canPrompt = process.stdin.isTTY === true;
        const acceptDefaults = options?.yes === true;
        let projectName = name || options?.machineName;
        if (!projectName) {
            if (acceptDefaults) {
                projectName = DEFAULT_PROJECT_NAME;
            }
            else if (canPrompt) {
                projectName = await input({
                    message: 'Project name:',
                    default: DEFAULT_PROJECT_NAME,
                });
            }
        }
        if (!projectName) {
            throw new CliError('Unable to determine the project name. Please provide a valid project name.');
        }
        let targetParent = targetDirectory || emulsifyParentDirectory;
        if (!targetParent) {
            if (acceptDefaults) {
                targetParent = './';
            }
            else if (canPrompt) {
                targetParent = await input({
                    message: 'Target directory:',
                    default: './',
                });
            }
        }
        let platformName = (options?.platform || autoPlatformName);
        if (!platformName) {
            if (acceptDefaults) {
                platformName = DEFAULT_PLATFORM;
            }
            else if (canPrompt) {
                platformName = (await input({
                    message: 'Platform:',
                    default: DEFAULT_PLATFORM,
                }));
            }
        }
        if (!platformName) {
            throw new CliError('Unable to determine which platform you are installing Emulsify within. Please specify a platform (such as "drupal" or "wordpress") by passing a -p or --platform flag with your init command.');
        }
        progress.tick(10, {
            message: `using starter for ${platformName} as the selected platform, validating config`,
        });
        const machineName = options?.machineName || strToMachineName(projectName, platformName);
        const starters = getAvailableStarters();
        const starter = starters.find((s) => s.platform === platformName);
        const target = targetParent ? join(targetParent, machineName) : undefined;
        const repository = options?.starter || starter?.repository;
        const checkout = options?.checkout || starter?.checkout;
        if (!target) {
            throw new CliError('Unable to find a directory to put Emulsify in. Please specify a directory using the "path" argument: emulsify init myTheme ./themes');
        }
        if (!repository) {
            throw new CliError(`Unable to find an Emulsify starter for your project. Please specify one using the --starter flag: emulsify init myTheme --starter ${getAvailableStarters()[0].repository}`);
        }
        if (existsSync(target)) {
            throw new CliError(`The intended target is already occupied: ${target}`);
        }
        try {
            progress.tick(10, { message: 'validation complete, cloning starter' });
            await git.clone(repository, target, checkout
                ? {
                    '--branch': checkout,
                }
                : {});
            await writeToJsonFile(join(target, EMULSIFY_PROJECT_CONFIG_FILE), {
                project: {
                    platform: platformName,
                    name: projectName,
                    machineName,
                },
                starter: { repository },
            });
            progress.tick(30, {
                message: 'starter cloned, installing dependencies (this will take a moment)',
            });
            await installDependencies(target);
            progress.tick(40, {
                message: 'dependencies installed, executing init script',
            });
            const initPath = join(target, EMULSIFY_PROJECT_HOOK_FOLDER, EMULSIFY_PROJECT_HOOK_INIT);
            if (existsSync(initPath)) {
                await executeScript(initPath);
            }
            await fs.rm(join(target, '.git'), { recursive: true });
            progress.tick(10, {
                message: 'init script executed, initialization complete',
            });
            log('success', `Created an Emulsify project in ${target}.`);
            getInitSuccessMessageForPlatform(platformName, target).map(({ method, message }) => log(method, message));
        }
        catch (e) {
            throw new CliError(`Unable to pull down ${repository}: ${String(e)}`);
        }
    };
}
