import db from '../db/database.js';
import yaml from 'js-yaml';
import fs from 'fs';
import path from 'path';
import { isCloud, nanoid } from '@nangohq/utils';
import { dirname } from '../utils/utils.js';
import { NangoError } from '../utils/error.js';
import encryptionManager from '../utils/encryption.manager.js';
import syncOrchestrator from './sync/orchestrator.service.js';
import { deleteSyncFilesForConfig, deleteByConfigId as deleteSyncConfigByConfigId } from '../services/sync/config/config.service.js';
import environmentService from '../services/environment.service.js';
class ConfigService {
    templates;
    constructor() {
        this.templates = this.getTemplatesFromFile();
    }
    getTemplatesFromFile() {
        const templatesPath = () => {
            // find the providers.yaml file
            // recursively searching in parent directories
            const findProvidersYaml = (dir) => {
                const providersYamlPath = path.join(dir, 'providers.yaml');
                if (fs.existsSync(providersYamlPath)) {
                    return providersYamlPath;
                }
                const parentDir = path.dirname(dir);
                if (parentDir === dir) {
                    throw new NangoError('providers_yaml_not_found');
                }
                return findProvidersYaml(parentDir);
            };
            return findProvidersYaml(dirname());
        };
        try {
            const fileEntries = yaml.load(fs.readFileSync(templatesPath()).toString());
            if (fileEntries == null) {
                throw new NangoError('provider_template_loading_failed');
            }
            for (const key in fileEntries) {
                const entry = fileEntries[key];
                if (entry?.alias) {
                    let hasOverrides = false;
                    let templateOverrides;
                    if (Object.keys(fileEntries[key]).length > 0) {
                        const { alias, ...overrides } = entry;
                        hasOverrides = true;
                        templateOverrides = overrides;
                    }
                    const aliasData = fileEntries[entry.alias];
                    if (hasOverrides) {
                        fileEntries[key] = { ...aliasData, ...templateOverrides };
                    }
                }
            }
            return fileEntries;
        }
        catch (_) {
            return null;
        }
    }
    async getProviderName(providerConfigKey) {
        const result = await db.knex.select('provider').from(`_nango_configs`).where({ unique_key: providerConfigKey, deleted: false });
        if (result == null || result.length == 0 || result[0] == null) {
            return null;
        }
        return result[0].provider;
    }
    async getIdByProviderConfigKey(environment_id, providerConfigKey) {
        const result = await db.knex
            .select('id')
            .from(`_nango_configs`)
            .where({ unique_key: providerConfigKey, environment_id, deleted: false });
        if (result == null || result.length == 0 || result[0] == null) {
            return null;
        }
        return result[0].id;
    }
    async getProviderConfigByUuid(providerConfigKey, environment_uuid) {
        if (!providerConfigKey) {
            throw new NangoError('missing_provider_config');
        }
        if (!environment_uuid) {
            throw new NangoError('missing_environment_uuid');
        }
        const environment_id = await environmentService.getIdByUuid(environment_uuid);
        if (!environment_id) {
            return null;
        }
        return this.getProviderConfig(providerConfigKey, environment_id);
    }
    async getProviderConfig(providerConfigKey, environment_id) {
        const result = await db.knex
            .select('*')
            .from(`_nango_configs`)
            .where({ unique_key: providerConfigKey, environment_id, deleted: false })
            .first();
        if (!result) {
            return null;
        }
        return encryptionManager.decryptProviderConfig(result);
    }
    async listProviderConfigs(environment_id) {
        return (await db.knex.select('*').from(`_nango_configs`).where({ environment_id, deleted: false }))
            .map((config) => encryptionManager.decryptProviderConfig(config))
            .filter((config) => config != null);
    }
    async listProviderConfigsByProvider(environment_id, provider) {
        return (await db.knex.select('*').from(`_nango_configs`).where({ environment_id, provider, deleted: false }))
            .map((config) => encryptionManager.decryptProviderConfig(config))
            .filter((config) => config != null);
    }
    async getAllNames(environment_id) {
        const configs = await this.listProviderConfigs(environment_id);
        return configs.map((config) => config.unique_key);
    }
    async createProviderConfig(config) {
        const configToInsert = config.oauth_client_secret ? encryptionManager.encryptProviderConfig(config) : config;
        return db.knex.from(`_nango_configs`).insert(configToInsert, ['id']);
    }
    async createEmptyProviderConfig(provider, environment_id) {
        const exists = await db.knex
            .count('*')
            .from(`_nango_configs`)
            .where({ provider, environment_id, deleted: false })
            .first();
        const config = {
            environment_id,
            unique_key: exists?.count === '0' ? provider : `${provider}-${nanoid(4).toLocaleLowerCase()}`,
            provider
        };
        const id = await this.createProviderConfig(config);
        if (!id || id.length === 0) {
            throw new NangoError('unknown_provider_config');
        }
        return { id: id[0]?.id, unique_key: config.unique_key };
    }
    async deleteProviderConfig(providerConfigKey, environment_id) {
        const idResult = (await db.knex.select('id').from(`_nango_configs`).where({ unique_key: providerConfigKey, environment_id, deleted: false }))[0];
        if (!idResult) {
            throw new NangoError('unknown_provider_config');
        }
        const { id } = idResult;
        await syncOrchestrator.deleteSyncsByProviderConfig(environment_id, providerConfigKey);
        if (isCloud) {
            const config = await this.getProviderConfig(providerConfigKey, environment_id);
            await deleteSyncFilesForConfig(config?.id, environment_id);
        }
        await deleteSyncConfigByConfigId(id);
        await db.knex.from(`_nango_configs`).where({ id, deleted: false }).update({ deleted: true, deleted_at: new Date() });
        return db.knex
            .from(`_nango_connections`)
            .where({ provider_config_key: providerConfigKey, environment_id, deleted: false })
            .update({ deleted: true, deleted_at: new Date() });
    }
    async editProviderConfig(config) {
        return db.knex
            .from(`_nango_configs`)
            .where({ unique_key: config.unique_key, environment_id: config.environment_id, deleted: false })
            .update(encryptionManager.encryptProviderConfig(config));
    }
    async editProviderConfigName(providerConfigKey, newUniqueKey, environment_id) {
        return db.knex
            .from(`_nango_configs`)
            .where({ unique_key: providerConfigKey, environment_id, deleted: false })
            .update({ unique_key: newUniqueKey });
    }
    checkProviderTemplateExists(provider) {
        if (this.templates == null) {
            throw new NangoError('provider_template_loading_failed');
        }
        return provider in this.templates;
    }
    getTemplate(provider) {
        if (this.templates == null) {
            throw new NangoError('unknown_provider_template_in_config');
        }
        const template = this.templates[provider];
        if (template == null) {
            throw new NangoError('unknown_provider_template_in_config');
        }
        return template;
    }
    getTemplates() {
        if (this.templates == null) {
            throw new NangoError('provider_template_loading_failed');
        }
        return this.templates;
    }
    async getConfigIdByProvider(provider, environment_id) {
        const result = await db.knex
            .select('id', 'unique_key')
            .from(`_nango_configs`)
            .where({ provider, environment_id, deleted: false })
            .first();
        if (!result) {
            return null;
        }
        return result;
    }
    async getConfigIdByProviderConfigKey(providerConfigKey, environment_id) {
        const result = await db.knex
            .select('id')
            .from(`_nango_configs`)
            .where({ unique_key: providerConfigKey, environment_id, deleted: false })
            .first();
        if (!result) {
            return null;
        }
        return result.id;
    }
}
export default new ConfigService();
//# sourceMappingURL=config.service.js.map