import { existsSync } from 'fs';
import { GENERATOR_ANGULAR, GENERATOR_BOOTSTRAP_WORKSPACES, GENERATOR_GIT, GENERATOR_REACT } from '../generator-list.js';
import BaseWorkspacesGenerator from '../base-workspaces/index.js';
import { packageJson } from '../../lib/index.js';
export default class WorkspacesGenerator extends BaseWorkspacesGenerator {
    workspaces;
    generateApplications;
    generateWith;
    entrypointGenerator;
    dockerCompose;
    generateWorkspaces;
    workspacesConfig;
    async beforeQueue() {
        if (!this.fromBlueprint) {
            await this.composeWithBlueprints();
        }
        if (!this.delegateToBlueprint) {
            await this.dependsOnJHipster(GENERATOR_BOOTSTRAP_WORKSPACES, { generatorOptions: { customWorkspacesConfig: true } });
        }
    }
    get initializing() {
        return this.asInitializingTaskGroup({
            loadConfig() {
                this.generateWorkspaces = (this.workspaces ?? this.jhipsterConfig.monorepository) || Boolean(this.packageJson?.get('workspaces'));
                this.workspacesConfig = this.generateWorkspaces ? this.jhipsterConfig : {};
            },
        });
    }
    get [BaseWorkspacesGenerator.INITIALIZING]() {
        return this.delegateTasksToBlueprint(() => this.initializing);
    }
    get configuring() {
        return this.asConfiguringTaskGroup({
            async configure() {
                this.jhipsterConfig.baseName = this.jhipsterConfig.baseName || 'workspaces';
            },
            async configureUsingFiles() {
                if (!this.generateWorkspaces)
                    return;
                if (existsSync(this.destinationPath('docker-compose'))) {
                    this.workspacesConfig.dockerCompose = true;
                }
                this.workspacesConfig.appsFolders = [...new Set([...(this.workspacesConfig.packages ?? []), ...this.appsFolders])];
                delete this.workspacesConfig.packages;
            },
        });
    }
    get [BaseWorkspacesGenerator.CONFIGURING]() {
        return this.delegateTasksToBlueprint(() => this.configuring);
    }
    get composing() {
        return this.asComposingTaskGroup({
            async composeGit() {
                if (this.options.monorepository || this.jhipsterConfig.monorepository) {
                    const generatorOptions = { monorepositoryRoot: true };
                    await this.composeWithJHipster(GENERATOR_GIT, { generatorOptions });
                    await this.composeWithJHipster('begcode:javascript:prettier', { generatorOptions });
                }
            },
            async generateApplications() {
                if (!this.generateApplications) {
                    return;
                }
                if (typeof this.generateApplications === 'function') {
                    await this.generateApplications.call(this);
                }
                else {
                    for (const appName of this.appsFolders) {
                        await this.composeWithJHipster(this.entrypointGenerator ?? this.generateWith, {
                            generatorOptions: { destinationRoot: this.destinationPath(appName) },
                        });
                    }
                }
            },
        });
    }
    get [BaseWorkspacesGenerator.COMPOSING]() {
        return this.delegateTasksToBlueprint(() => this.composing);
    }
    get loading() {
        return this.asLoadingTaskGroup({
            checkWorkspaces() {
                if (this.generateWorkspaces && !this.jhipsterConfig.monorepository) {
                    throw new Error('Workspaces option is only supported with monorepositories.');
                }
            },
        });
    }
    get [BaseWorkspacesGenerator.LOADING]() {
        return this.delegateTasksToBlueprint(() => this.loading);
    }
    get loadingWorkspaces() {
        return this.asDefaultTaskGroup({
            configurePackageManager({ applications }) {
                if (this.workspacesConfig.clientPackageManager || !this.generateWorkspaces)
                    return;
                this.workspacesConfig.clientPackageManager =
                    this.options.clientPackageManager ?? applications.find(app => app.clientPackageManager)?.clientPackageManager ?? 'pnpm';
            },
            async loadConfig() {
                if (!this.generateWorkspaces)
                    return;
                this.dockerCompose = this.workspacesConfig.dockerCompose;
                this.env.options.nodePackageManager = this.workspacesConfig.clientPackageManager;
            },
        });
    }
    get [BaseWorkspacesGenerator.LOADING_WORKSPACES]() {
        return this.delegateTasksToBlueprint(() => this.loadingWorkspaces);
    }
    get writing() {
        return this.asWritingTaskGroup({
            async writing() {
                await this.writeFiles({
                    blocks: [{ templates: ['.prettierignore.jhi.workspaces'] }],
                    context: {},
                });
            },
        });
    }
    get [BaseWorkspacesGenerator.WRITING]() {
        return this.delegateTasksToBlueprint(() => this.writing);
    }
    get postWriting() {
        return this.asPostWritingTaskGroup({
            generatePackageJson({ applications }) {
                if (!this.generateWorkspaces)
                    return;
                const findDependencyVersion = dependency => applications.find(app => app.nodeDependencies[dependency])?.nodeDependencies[dependency];
                this.packageJson.merge({
                    workspaces: {
                        packages: this.appsFolders,
                    },
                    devDependencies: {
                        concurrently: findDependencyVersion('concurrently'),
                    },
                    scripts: {
                        'ci:e2e:package': 'npm run ci:docker:build --workspaces --if-present && npm run java:docker --workspaces --if-present',
                        'ci:e2e:run': 'npm run e2e:headless --workspaces --if-present',
                        ...this.getOtherScripts(),
                        ...this.createConcurrentlyScript('watch', 'backend:build-cache', 'java:docker', 'java:docker:arm64'),
                        ...this.createWorkspacesScript('ci:backend:test', 'ci:frontend:test', 'webapp:test'),
                    },
                });
                if (applications.some(app => app.clientFrameworkAngular)) {
                    const { dependencies: { rxjs }, devDependencies: { webpack: webpackVersion, 'browser-sync': browserSyncVersion }, } = this.fs.readJSON(this.fetchFromInstalledJHipster(GENERATOR_ANGULAR, 'resources', 'package.json'));
                    this.packageJson.merge({
                        devDependencies: {
                            rxjs,
                        },
                        overrides: {
                            'browser-sync': browserSyncVersion,
                            webpack: webpackVersion,
                        },
                    });
                }
                if (applications.some(app => app.clientFrameworkReact)) {
                    const { devDependencies: { 'browser-sync': browserSyncVersion }, } = this.fs.readJSON(this.fetchFromInstalledJHipster(GENERATOR_REACT, 'resources', 'package.json'));
                    this.packageJson.merge({
                        overrides: {
                            'browser-sync': browserSyncVersion,
                        },
                    });
                }
                if (applications.some(app => app.backendTypeJavaAny)) {
                    this.packageJson.merge({
                        devDependencies: {
                            'prettier-plugin-java': packageJson.dependencies['prettier-plugin-java'],
                        },
                    });
                }
            },
        });
    }
    get [BaseWorkspacesGenerator.POST_WRITING]() {
        return this.delegateTasksToBlueprint(() => this.postWriting);
    }
    getOtherScripts() {
        if (this.dockerCompose) {
            return {
                'docker-compose': 'docker compose -f docker-compose/docker-compose.yml up --wait',
                'ci:e2e:prepare': 'npm run docker-compose',
                'ci:e2e:teardown': 'docker compose -f docker-compose/docker-compose.yml down -v',
            };
        }
        return {};
    }
    createConcurrentlyScript(...scripts) {
        const scriptsList = scripts
            .map(script => {
            const packageScripts = this.appsFolders.map(packageName => [
                `${script}:${packageName}`,
                `npm run ${script} --workspace ${packageName} --if-present`,
            ]);
            packageScripts.push([script, `concurrently ${this.appsFolders.map(packageName => `npm:${script}:${packageName}`).join(' ')}`]);
            return packageScripts;
        })
            .flat();
        return Object.fromEntries(scriptsList);
    }
    createWorkspacesScript(...scripts) {
        return Object.fromEntries(scripts.map(script => [`${script}`, `npm run ${script} --workspaces --if-present`]));
    }
}
