#!/usr/bin/env node

import chalk from 'chalk';
import path from 'path';
import fs from 'fs-extra';

import { PackageManager } from './types/packageManager';

import { projectNamePrompt } from './prompts/projectName';
import { packageManagerPrompt } from './prompts/packageManager';
import { createNextApp, defineAlias, nextJsPrompt } from './prompts/nextjs';

import {
    configureStorybook,
    installStorybook,
    storybookConfigsPrompt,
    storybookPrompt,
} from './prompts/storybook';

import { configureNpmRc } from './prompts/npmrc';
import { configureNvmRc } from './prompts/nvmrc';
import { configureEnv } from './prompts/env';
import { configureESLint } from './prompts/eslint';
import { configurePrettier } from './prompts/prettier';

import { installShadCN, shadcnPrompt } from './prompts/shadcn';

import {
    installDevDependencies,
    installDependencies,
} from './prompts/dependencies';

import { gitCommit } from './prompts/git';

async function main() {
    console.clear();
    console.log(
        chalk.hex('#633cff')('========================================'),
    );
    console.log('        Zenith Project Generator CLI');
    console.log(
        chalk.hex('#633cff')('========================================'),
    );

    const useDefault =
        process.argv.includes('--default') || process.argv.includes('-d');

    let packageManager: PackageManager = 'pnpm',
        useTs: boolean = true,
        useEslint: boolean = true,
        useSrc: boolean = true,
        useApp: boolean = true,
        useTurbo: boolean = true,
        customAlias: boolean = false,
        useShadcn: boolean = true,
        useStorybook: boolean = true,
        usePrettier: boolean = true,
        useStorybookDefaultConfig: boolean = false,
        useChromatic: boolean = true,
        alias = '@/*';

    const projectName: string = await projectNamePrompt();

    if (useDefault) console.log(chalk.yellow('Using default settings...'));
    else {
        packageManager = await packageManagerPrompt();

        console.log(chalk.blue('Creating Next.js project...'));

        ({
            useTs,
            useEslint,
            usePrettier,
            useSrc,
            useApp,
            useTurbo,
            customAlias,
        } = await nextJsPrompt());

        const alias: string = await defineAlias(useDefault, customAlias);

        useStorybook = await storybookPrompt();

        if (useStorybook) {
            ({ useStorybookDefaultConfig, useChromatic } =
                await storybookConfigsPrompt());
        }

        useShadcn = await shadcnPrompt();
    }

    const projectPath = path.join(process.cwd(), projectName);

    try {
        console.log(chalk.blue('Running Create Next App...'));
        createNextApp(
            projectName,
            packageManager,
            useTs,
            useSrc,
            useTurbo,
            useApp,
            useEslint,
            alias,
        );

        console.log(
            chalk.green(`Next.js project created using ${packageManager}`),
        );
    } catch (error) {
        console.log(
            chalk.red('Failed to create Next.js project\nError: '),
            error,
        );
        return;
    }

    try {
        fs.ensureDirSync(projectPath);
        process.chdir(projectPath);

        console.log(chalk.blue('Setting up configuration files...'));

        configureNpmRc(projectPath);
        configureNvmRc(projectPath);
        configureEnv(projectPath, useChromatic);

        installDevDependencies(
            packageManager,
            useEslint,
            useChromatic,
            useStorybook,
            usePrettier,
        );
        installDependencies(packageManager);

        if (useShadcn) installShadCN(packageManager);
        if (useStorybook) installStorybook(packageManager);
        if (useEslint) configureESLint(projectPath);
        if (usePrettier) configurePrettier(projectPath);

        if (!useStorybookDefaultConfig)
            configureStorybook(projectPath, useStorybook);

        gitCommit();

        console.log(chalk.green('Project setup completed successfully!'));
    } catch (error) {
        console.log(chalk.red('Failed to setup the project\nError: '), error);
    }
}

main().catch(err => console.error(chalk.red('Error: '), err));
