import path from 'path';
import fs from 'fs';
import JDLObject from '../core/models/jdl-object.js';
import mergeJDLObjects from '../core/models/jdl-object-merger.js';
import { doesDirectoryExist, doesFileExist } from '../core/utils/file-utils.js';
import { removeFieldsWithNullishValues } from '../../utils/object.js';
import { createRuntime, getDefaultRuntime } from '../core/runtime.js';
import { YO_RC_CONFIG_KEY, readEntityFile, readYoRcFile } from '../../utils/yo-rc.js';
import exportJDLObject from './exporters/jdl-exporter.js';
import { convertEntitiesToJDL } from './json-to-jdl-entity-converter.js';
import { convertApplicationToJDL } from './json-to-jdl-application-converter.js';
export default {
    convertToJDL,
    convertSingleContentToJDL,
};
export function convertToJDL(directory = '.', output = 'app.jdl', definition) {
    let jdlObject;
    const runtime = definition ? createRuntime(definition) : getDefaultRuntime();
    if (doesFileExist(path.join(directory, '.yo-rc.json'))) {
        const yoRcFileContent = readYoRcFile(directory);
        let entities;
        if (doesDirectoryExist(path.join(directory, '.jhipster'))) {
            entities = getJSONEntityFiles(directory);
        }
        jdlObject = getJDLObjectFromSingleApplication(yoRcFileContent, entities, undefined, runtime);
    }
    else {
        try {
            jdlObject = getJDLObjectFromMultipleApplications(directory, runtime);
        }
        catch {
            return undefined;
        }
    }
    if (output) {
        output = path.isAbsolute(output) ? output : path.join(directory, output);
        exportJDLObject(jdlObject, output);
    }
    return jdlObject;
}
export function convertSingleContentToJDL(yoRcFileContent, entities) {
    return getJDLObjectFromSingleApplication(yoRcFileContent, entities).toString();
}
function getJDLObjectFromMultipleApplications(directory, runtime) {
    const subDirectories = getSubdirectories(directory);
    if (subDirectories.length === 0) {
        throw new Error('There are no subdirectories.');
    }
    let jdlObject = new JDLObject();
    subDirectories.forEach(subDirectory => {
        const applicationDirectory = path.join(directory, subDirectory);
        const yoRcFileContent = readYoRcFile(applicationDirectory);
        let entities = new Map();
        if (doesDirectoryExist(path.join(applicationDirectory, '.jhipster'))) {
            entities = getJSONEntityFiles(applicationDirectory);
        }
        jdlObject = getJDLObjectFromSingleApplication(yoRcFileContent, entities, jdlObject, runtime);
    });
    return jdlObject;
}
export function getJDLObjectFromSingleApplication(yoRcFileContent, entities, existingJDLObject = new JDLObject(), runtime = getDefaultRuntime()) {
    const cleanedYoRcFileContent = cleanYoRcFileContent(yoRcFileContent);
    const jdlApplication = convertApplicationToJDL({ application: cleanedYoRcFileContent }, runtime);
    if (!entities) {
        existingJDLObject.addApplication(jdlApplication);
        return existingJDLObject;
    }
    const jdlObject = convertEntitiesToJDL(entities);
    entities.forEach((entity, entityName) => jdlApplication.addEntityName(entityName));
    jdlObject.addApplication(jdlApplication);
    return mergeJDLObjects(existingJDLObject, jdlObject);
}
function cleanYoRcFileContent(yoRcFileContent) {
    for (const key of Object.keys(yoRcFileContent)) {
        yoRcFileContent[key] = removeFieldsWithNullishValues(yoRcFileContent[key]);
    }
    delete yoRcFileContent[YO_RC_CONFIG_KEY].promptValues;
    const result = structuredClone(yoRcFileContent);
    if (yoRcFileContent[YO_RC_CONFIG_KEY].blueprints) {
        result[YO_RC_CONFIG_KEY].blueprints = yoRcFileContent[YO_RC_CONFIG_KEY].blueprints.map(blueprint => blueprint.name);
    }
    if (yoRcFileContent[YO_RC_CONFIG_KEY].microfrontends) {
        result[YO_RC_CONFIG_KEY].microfrontends = yoRcFileContent[YO_RC_CONFIG_KEY].microfrontends.map(({ baseName }) => baseName);
    }
    return result;
}
function getJSONEntityFiles(applicationDirectory) {
    const entities = new Map();
    fs.readdirSync(path.join(applicationDirectory, '.jhipster')).forEach(file => {
        const entityName = file.slice(0, file.indexOf('.json'));
        try {
            entities.set(entityName, readEntityFile(applicationDirectory, entityName));
        }
        catch {
        }
    });
    return entities;
}
function getSubdirectories(rootDirectory) {
    return fs.readdirSync(path.join(rootDirectory)).filter(file => doesDirectoryExist(path.join(rootDirectory, file)));
}
