/**
 * Copyright 2013-2026 the original author or authors from the JHipster project.
 *
 * This file is part of the JHipster project, see https://www.jhipster.tech/
 * for more information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import chalk from 'chalk';
import { CheckRepoActions } from 'simple-git';
import BaseGenerator from "../base/index.js";
import { files } from "./files.js";
export default class GitGenerator extends BaseGenerator {
    gitInitialized;
    existingRepository;
    skipGit;
    forceGit;
    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) {
                    // Force write .yo-rc.json to disk, it's used to check if the application is regenerated
                    this.jhipsterConfig.monorepository ??= undefined;
                }
            },
        });
    }
    get [BaseGenerator.PREPARING]() {
        return this.delegateTasksToBlueprint(() => this.preparing);
    }
    get writing() {
        return this.asWritingTaskGroup({
            async writeFiles() {
                await this.writeFiles({ sections: files, context: {} });
            },
        });
    }
    get [BaseGenerator.WRITING]() {
        return this.delegateTasksToBlueprint(() => this.writing);
    }
    get postWriting() {
        return this.asPostWritingTaskGroup({
            /** Husky commit hook install at install priority requires git to be initialized */
            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({
            /** Initial commit to git repository after package manager install for package-lock.json */
            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-jhipster@${this.jhipsterConfig.jhipsterVersion}`
                                : `Initial version of ${this.jhipsterConfig.baseName} generated by generator-jhipster@${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}`;
                        }
                        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})`));
                    }
                };
                // @ts-expect-error keep compatibility with other adapters
                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(CheckRepoActions.IS_REPO_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}`);
        }
    }
}
