/*!
 * Copyright (C) Microsoft Corporation. All rights reserved.
 */
import { processDataSourceInfo } from '../CodeGen/dataSourceInfoProcessor.js';
import { clearAndRegenerateModelService } from '../CodeGen/modelServiceGenerator.js';
import { DataSources } from '../Config/Config.types.js';
import { readRepoConfig, writeRepoConfig } from '../Config/ConfigManager.js';
import { getVfs, setVfs } from '../VfsManager.js';
import { normalizeParam } from './DataUtils.js';
export async function deleteDataSourceAsync(config) {
    let apiId = await normalizeParam(config.actionsParams.apiId);
    const { schemaPath: schemaFolder, codeGenPath: codeGenDirectory, powerConfigPath, } = config.localFilePaths;
    // validate parameters, cleanup, and throw errors where necessary
    if (!apiId) {
        throw new Error('Argument apiId is required. Use --apiId or -a to specify it.');
    }
    // remove the "shared_" prefix from the apiId if it exists
    if (apiId.startsWith('shared_')) {
        apiId = apiId.substring('shared_'.length);
    }
    apiId = apiId.toLowerCase();
    let dataSourceName;
    let sqlStoredProcedure;
    if (apiId === 'sql') {
        sqlStoredProcedure = await normalizeParam(config.actionsParams.sqlStoredProcedure); // optional
    }
    if (!sqlStoredProcedure) {
        dataSourceName = await normalizeParam(config.actionsParams.dataSourceName);
    }
    if (!dataSourceName && !sqlStoredProcedure) {
        throw new Error('Argument dataSourceName or sqlStoredProcedure is required for delete data sources. Use --dataSourceName or --sqlStoredProcedure to specify it.');
    }
    if (!schemaFolder || !codeGenDirectory) {
        throw new Error('Schema path and code generation path must be provided in the config');
    }
    setVfs(config.vfs);
    const vfs = getVfs();
    if (!powerConfigPath || !(await vfs.exists(powerConfigPath))) {
        throw new Error('Power configuration file must exist');
    }
    // Start of the delete operation
    {
        // Construct the directory path based on the schemaPath, apiId, and dataSourceName
        let directoryPath = vfs.join(schemaFolder, apiId);
        let updated = false;
        if (sqlStoredProcedure && sqlStoredProcedure.length > 0) {
            directoryPath = vfs.join(directoryPath, sqlStoredProcedure);
            try {
                await vfs.rmdir(directoryPath);
            }
            catch (error) {
                // Could not remove directory. Not an issue and can proceed
            }
            updated = true;
        }
        else {
            const schemaFilePath = vfs.join(directoryPath, `${dataSourceName}.Schema.json`);
            const schemaFileExists = await vfs.exists(schemaFilePath);
            let dataSourceDirectoryIsEmpty = false;
            if (schemaFileExists) {
                // delete the file
                await vfs.unlink(schemaFilePath);
                // check if the directory is empty after deleting the schema file
                if (await vfs.exists(directoryPath)) {
                    const files = await vfs.readdir(directoryPath);
                    dataSourceDirectoryIsEmpty = files.length === 0;
                    if (dataSourceDirectoryIsEmpty) {
                        try {
                            await vfs.rmdir(directoryPath);
                        }
                        catch (error) {
                            // Could not clean up empty directory. Not an issue and can proceed
                        }
                    }
                }
                updated = true;
            }
        }
        const configUpdated = await _cleanupPowerConfig(powerConfigPath, (sqlStoredProcedure ?? dataSourceName), apiId === DataSources.Dataverse.toLowerCase());
        // Always call processDataSourceInfo and ModelServiceGenerator for Dataverse or when files were updated
        if (updated || configUpdated) {
            // Ensure that the datasource info file is updated
            // Pass the deleted schema file so it can be excluded from processing
            await processDataSourceInfo(schemaFolder, config.logger);
            await clearAndRegenerateModelService({
                schemaFolderPath: schemaFolder,
                codeGenPath: codeGenDirectory,
                logger: config.logger,
            });
        }
        if (!updated && !configUpdated) {
            // There was nothing to delete or the data source was not found
            return false;
        }
    }
    return true;
}
async function _cleanupPowerConfig(powerConfigPath, dataSourceName, isDataverse = false) {
    // Read the power config file
    const powerConfig = await readRepoConfig(powerConfigPath);
    if (!powerConfig) {
        return false;
    }
    let updated = false;
    const keysToDelete = new Set();
    if (isDataverse) {
        // Handle Dataverse specific cleanup
        if (!powerConfig.databaseReferences || !powerConfig.databaseReferences['default.cds']) {
            return false;
        }
        const databaseReference = powerConfig.databaseReferences['default.cds'];
        if (databaseReference.dataSources && databaseReference.dataSources[dataSourceName]) {
            delete databaseReference.dataSources[dataSourceName];
            updated = true;
        }
        // If there are no more data sources, mark the database reference for removal
        const remainingDataSources = Object.keys(databaseReference.dataSources).length;
        if (remainingDataSources === 0) {
            delete powerConfig.databaseReferences['default.cds'];
            updated = true;
        }
    }
    else {
        if (!powerConfig.connectionReferences) {
            return false;
        }
        for (const [connectionName, metadata] of Object.entries(powerConfig.connectionReferences)) {
            let dataSources = metadata.dataSources || [];
            if (dataSources &&
                dataSources.some((ds) => ds.toLowerCase() === dataSourceName.toLowerCase())) {
                // Remove the data source from the list (case-insensitive)
                dataSources = dataSources.filter((ds) => ds.toLowerCase() !== dataSourceName.toLowerCase());
                updated = true;
                if (metadata.dataSets) {
                    for (const [dataSetName, dataSet] of Object.entries(metadata.dataSets)) {
                        if (dataSet) {
                            const dataSourceReferences = dataSet.dataSources;
                            // if any in the dataSourceReferences matches datasource name case insensitve remove it
                            dataSet.dataSources = Object.fromEntries(Object.entries(dataSourceReferences).filter(([key, _value]) => key.toLowerCase() !== dataSourceName.toLowerCase()));
                            updated = true;
                            metadata.dataSets[dataSetName] = dataSet; // Update the dataset reference
                        }
                    }
                }
            }
            // If there are no more data sources, mark the connection for removal
            if (dataSources.length === 0) {
                keysToDelete.add(connectionName);
            }
            else {
                metadata.dataSources = dataSources;
                powerConfig.connectionReferences[connectionName] = metadata; // Update the connection reference
            }
        }
        // Remove empty connections
        for (const key of keysToDelete) {
            delete powerConfig.connectionReferences[key];
            updated = true;
        }
    }
    // save the updated power config back to the file
    if (updated) {
        await writeRepoConfig(powerConfigPath, powerConfig);
    }
    return updated;
}
//# sourceMappingURL=DeleteDataSource.js.map