import path from 'path';
import fs from 'fs';
import JDLObject from '../models/jdl-object.js';
import mergeJDLObjects from '../models/jdl-object-merger.js';
import { doesFileExist, doesDirectoryExist } from '../utils/file-utils.js';
import { readJSONFile } from '../readers/json-file-reader.js';
import { convertApplicationToJDL } from './json-to-jdl-application-converter.js';
import { convertEntitiesToJDL } from './json-to-jdl-entity-converter.js';
import exportJDLObject from '../exporters/jdl-exporter.js';
import { removeFieldsWithNullishValues } from '../../generators/base/support/config.js';
import { GENERATOR_JHIPSTER } from '../../generators/generator-constants.js';
export default {
    convertToJDL,
    convertSingleContentToJDL,
};
export function convertToJDL(directory = '.', output = 'app.jdl') {
    let jdlObject;
    if (doesFileExist(path.join(directory, '.yo-rc.json'))) {
        const yoRcFileContent = readJSONFile(path.join(directory, '.yo-rc.json'));
        let entities;
        if (doesDirectoryExist(path.join(directory, '.jhipster'))) {
            entities = getJSONEntityFiles(directory);
        }
        jdlObject = getJDLObjectFromSingleApplication(yoRcFileContent, entities);
    }
    else {
        try {
            jdlObject = getJDLObjectFromMultipleApplications(directory);
        }
        catch (error) {
            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) {
    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 = readJSONFile(path.join(applicationDirectory, '.yo-rc.json'));
        let entities = new Map();
        if (doesDirectoryExist(path.join(applicationDirectory, '.jhipster'))) {
            entities = getJSONEntityFiles(applicationDirectory);
        }
        jdlObject = getJDLObjectFromSingleApplication(yoRcFileContent, entities, jdlObject);
    });
    return jdlObject;
}
export function getJDLObjectFromSingleApplication(yoRcFileContent, entities, existingJDLObject = new JDLObject()) {
    const cleanedYoRcFileContent = cleanYoRcFileContent(yoRcFileContent);
    const jdlApplication = convertApplicationToJDL({ application: cleanedYoRcFileContent });
    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[GENERATOR_JHIPSTER].promptValues;
    const result = structuredClone(yoRcFileContent);
    if (yoRcFileContent[GENERATOR_JHIPSTER].blueprints) {
        result[GENERATOR_JHIPSTER].blueprints = yoRcFileContent[GENERATOR_JHIPSTER].blueprints.map(blueprint => blueprint.name);
    }
    if (yoRcFileContent[GENERATOR_JHIPSTER].microfrontends) {
        result[GENERATOR_JHIPSTER].microfrontends = yoRcFileContent[GENERATOR_JHIPSTER].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'));
        const jsonFilePath = path.join(applicationDirectory, '.jhipster', file);
        if (fs.statSync(jsonFilePath).isFile() && file.endsWith('.json')) {
            entities.set(entityName, readJSONFile(jsonFilePath));
        }
    });
    return entities;
}
function getSubdirectories(rootDirectory) {
    return fs.readdirSync(path.join(rootDirectory)).filter(file => doesDirectoryExist(path.join(rootDirectory, file)));
}
