"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fs = __importStar(require("fs"));
const readline = __importStar(require("readline"));
const utils_1 = require("../utils");
const { execSync } = require('child_process');
const loadingSpinner = require('loading-spinner');
const workingDir = path_1.default.resolve(process.cwd());
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
const ANSWERS = {};
const QUESTIONS = [
    {
        text: 'Brand name',
        optional: false,
        answerKey: 'brandName',
        hint: 'eg. Project Zero'
    },
    {
        text: 'Project description',
        optional: true,
        answerKey: 'projectDescription'
    },
    {
        text: 'Commerce URL (SERVICE_BACKEND_URL)',
        optional: true,
        answerKey: 'commerceUrl',
        hint: 'Can be changed later'
    }
];
const getAnswers = () => {
    return new Promise((resolve) => {
        const question = QUESTIONS[Object.keys(ANSWERS).length];
        if (!question) {
            rl.close();
            resolve(ANSWERS);
            return;
        }
        let questionText = question.text;
        if (question.hint) {
            questionText += ` (${question.hint})`;
        }
        if (question.optional) {
            questionText += ` (optional)`;
        }
        rl.question(`${questionText}: `, (answer) => {
            if (!question.optional && !answer.length) {
                console.log('\x1b[31m%s\x1b[0m', `* This field is required\n`);
                resolve(getAnswers());
            }
            else {
                ANSWERS[question.answerKey] = answer;
                resolve(getAnswers());
            }
        });
    });
};
const updateFileContents = (filePath, replacements) => {
    let content = fs.readFileSync(filePath, { encoding: 'utf8' });
    Object.entries(replacements).forEach(([key, value]) => {
        if (filePath.endsWith('.json')) {
            content = content.replace(new RegExp(`"${key}":\\s*".*?"`, 'g'), `"${key}": "${value}"`);
        }
        else {
            content = content.replace(new RegExp(`^${key}=.*$`, 'gm'), `${key}=${value}`);
        }
    });
    fs.writeFileSync(filePath, content, { encoding: 'utf8' });
};
function updatePluginsFile(projectDir) {
    const pluginsFilePath = path_1.default.join(projectDir, 'src', 'plugins.js');
    const content = 'module.exports = [];';
    fs.writeFileSync(pluginsFilePath, content, { encoding: 'utf8' });
}
function createEnvironmentFile(projectDir) {
    fs.copyFileSync(`${projectDir}/.env.example`, `${projectDir}/.env`);
}
function checkGitignore(projectDir) {
    const gitignorePath = path_1.default.join(projectDir, '.gitignore');
    const npmignorePath = path_1.default.join(projectDir, '.npmignore');
    if (!fs.existsSync(gitignorePath)) {
        fs.renameSync(npmignorePath, gitignorePath);
    }
    else if (fs.existsSync(npmignorePath)) {
        fs.rmSync(npmignorePath);
    }
}
exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
    const minNodeVersion = 18;
    const currentNodeVersion = parseInt(process.version.replace('v', '').split('.')[0]);
    if (currentNodeVersion < minNodeVersion) {
        console.log('\x1b[31m%s\x1b[0m', `Node version must be ${minNodeVersion} or higher.\n`.concat(`Current version is ${currentNodeVersion}. Please update your Node version.`));
        process.exit(1);
    }
    const answers = yield getAnswers();
    const brandName = answers.brandName === '.' ? path_1.default.basename(workingDir) : answers.brandName;
    const projectDir = answers.brandName === '.' ? workingDir : path_1.default.resolve(workingDir, (0, utils_1.slugify)(brandName));
    const relativeProjectDir = answers.brandName === '.' ? '.' : (0, utils_1.slugify)(brandName);
    if (!fs.existsSync(projectDir)) {
        fs.mkdirSync(projectDir, { recursive: true });
    }
    const templatesDir = path_1.default.resolve(__dirname, '../../../projectzero/app-template');
    fs.cpSync(templatesDir, projectDir, { recursive: true });
    updatePluginsFile(projectDir);
    createEnvironmentFile(projectDir);
    checkGitignore(projectDir);
    fs.chmodSync(path_1.default.join(projectDir, 'build.sh'), 0o711);
    if (answers.projectDescription) {
        updateFileContents(path_1.default.join(projectDir, 'akinon.json'), {
            description: answers.projectDescription
        });
    }
    if (answers.commerceUrl) {
        updateFileContents(path_1.default.join(projectDir, '.env'), {
            SERVICE_BACKEND_URL: answers.commerceUrl
        });
    }
    updateFileContents(path_1.default.join(projectDir, 'package.json'), {
        name: (0, utils_1.slugify)(brandName)
    });
    console.log('\x1b[34m%s\x1b[0m', '\n🚀 Installing packages...\n');
    execSync(`cd ${relativeProjectDir} && yarn install`, { stdio: 'ignore' });
    loadingSpinner.stop();
    const successMessage = `
✨ ${brandName} project is ready at \x1b[4m${projectDir}\x1b[0m

Within the directory, the following commands are available:

  \x1b[35m$ yarn dev\x1b[0m
    \x1b[32mLaunches the development server.\x1b[0m

  \x1b[35m$ yarn build\x1b[0m
    \x1b[32mCompiles the app into static files for production.\x1b[0m

  \x1b[35m$ yarn start\x1b[0m
    \x1b[32mRuns the production server.\x1b[0m
`;
    const getStartedMessage = answers.brandName === '.'
        ? 'To get started, you can type:\n\n  \x1b[35m$ yarn dev\x1b[0m\n'
        : `To get started, you can type:\n\n  \x1b[35m$ cd ${relativeProjectDir}\x1b[0m\n  \x1b[35m$ yarn dev\x1b[0m\n`;
    console.log('\x1b[32m%s\x1b[0m', successMessage);
    console.log('\x1b[36m%s\x1b[0m', getStartedMessage);
    console.log('\x1b[33m%s\x1b[0m', 'Project setup is complete\n');
    console.log('\x1b[33m%s\x1b[0m', 'Project Zero - Akinon\n');
});
