import chalk from 'chalk';
import BaseGenerator from '../base/index.js';
import { files } from './files.js';
export default class GitGenerator extends BaseGenerator {
    gitInitialized;
    skipGit;
    forceGit;
    existingRepository;
    commitMsg;
    async beforeQueue() {
        if (!this.fromBlueprint) {
            await this.composeWithBlueprints();
        }
    }
    get initializing() {
        return this.asInitializingTaskGroup({
            async checkGit() {
                if (!this.skipGit) {
                    const gitInstalled = (await this.createGit().version()).installed;
                    if (!gitInstalled) {
                        this.log.warn('Git repository will not be created, as Git is not installed on your system');
                        this.skipGit = true;
                    }
                }
            },
            async initializeMonorepository() {
                if (!this.skipGit && this.jhipsterConfig.monorepository) {
                    await this.initializeGitRepository();
                }
            },
        });
    }
    get [BaseGenerator.INITIALIZING]() {
        return this.delegateTasksToBlueprint(() => this.initializing);
    }
    get preparing() {
        return this.asPreparingTaskGroup({
            async preparing() {
                if (!this.skipGit) {
                    this.jhipsterConfig.skipGit = undefined;
                }
            },
        });
    }
    get [BaseGenerator.PREPARING]() {
        return this.delegateTasksToBlueprint(() => this.preparing);
    }
    get writing() {
        return this.asWritingTaskGroup({
            async writeFiles() {
                if (this.skipGit)
                    return undefined;
                await this.writeFiles({ sections: files, context: {} });
            },
        });
    }
    get [BaseGenerator.WRITING]() {
        return this.delegateTasksToBlueprint(() => this.writing);
    }
    get postWriting() {
        return this.asPostWritingTaskGroup({
            async initGitRepo() {
                if (!this.skipGit && !this.jhipsterConfig.monorepository) {
                    await this.initializeGitRepository();
                }
            },
        });
    }
    get [BaseGenerator.POST_WRITING]() {
        return this.delegateTasksToBlueprint(() => this.postWriting);
    }
    get end() {
        return this.asEndTaskGroup({
            async gitCommit() {
                if (this.skipGit)
                    return;
                if (!this.gitInitialized) {
                    this.log.warn('The generated application could not be committed to Git, as a Git repository could not be initialized.');
                    return;
                }
                const commitFiles = async () => {
                    this.debug('Committing files to git');
                    const git = this.createGit();
                    const repositoryRoot = await git.revparse(['--show-toplevel']);
                    const result = await git.log(['-n', '1', '--', '.yo-rc.json']).catch(() => ({ total: 0 }));
                    const existingApplication = result.total > 0;
                    if (existingApplication && !this.forceGit) {
                        this.log.info(`Found .yo-rc.json in Git from ${repositoryRoot}. So we assume this is application regeneration. Therefore automatic Git commit is not done. You can do Git commit manually.`);
                        return;
                    }
                    if (!this.forceGit) {
                        const statusResult = await git.status();
                        if (statusResult.staged.length > 0) {
                            this.log.verboseInfo(`The repository ${repositoryRoot} has staged files, skipping commit.`);
                            return;
                        }
                    }
                    try {
                        let commitMsg = this.commitMsg ??
                            (existingApplication
                                ? `Regenerated ${this.jhipsterConfig.baseName} using generator-begcode@${this.jhipsterConfig.jhipsterVersion}`
                                : `Initial version of ${this.jhipsterConfig.baseName} generated by generator-begcode@${this.jhipsterConfig.jhipsterVersion}`);
                        if (this.jhipsterConfig.blueprints && this.jhipsterConfig.blueprints.length > 0) {
                            const bpInfo = this.jhipsterConfig.blueprints.map(bp => `${bp.name}@${bp.version}`).join(', ');
                            commitMsg += ` with blueprints ${bpInfo}`;
                        }
                        this.log.ok(`committing to Git from ${repositoryRoot}...`);
                        await git.add(['.']).commit(commitMsg, { '--allow-empty': null, '--no-verify': null });
                        this.log.ok(`Application successfully committed to Git from ${repositoryRoot}.`);
                    }
                    catch (e) {
                        this.log.warn(chalk.red.bold(`Application commit to Git failed from ${repositoryRoot}. Try to commit manually. (${e.message})`));
                    }
                };
                if (this.env.adapter.queue) {
                    await this.env.adapter.queue(commitFiles);
                }
                else {
                    await commitFiles();
                }
            },
        });
    }
    get [BaseGenerator.END]() {
        return this.delegateTasksToBlueprint(() => this.end);
    }
    async initializeGitRepository() {
        try {
            const git = this.createGit();
            if (await git.checkIsRepo()) {
                if (await git.checkIsRepo('root')) {
                    this.log.info('Using existing git repository.');
                }
                else {
                    this.log.info('Using existing git repository at parent folder.');
                }
                this.existingRepository = true;
            }
            else if (await git.init()) {
                this.log.ok('Git repository initialized.');
            }
            this.gitInitialized = true;
        }
        catch (error) {
            this.log.warn(`Failed to initialize Git repository.\n ${error}`);
        }
    }
}
