import { join } from 'node:path';
import { buildCommandContext } from '../../../app/command-context.js';
import { withScopeOption } from '../../shared/scope-option.js';
import { readGlobalOptions } from '../../shared/shared.utils.js';
import { DEFAULT_SYNC_CONFIG, loadSyncConfig, saveSyncConfig, } from '../../../config/index.js';
import { resolveProjectRoot } from '../../../fs/paths.js';
import { claudeAdapter } from '../../../providers/claude/index.js';
import { codexAdapter } from '../../../providers/codex/index.js';
import { copilotAdapter } from '../../../providers/copilot/index.js';
import { cursorAdapter } from '../../../providers/cursor/index.js';
import { geminiAdapter } from '../../../providers/gemini/index.js';
import { Command } from 'commander';
const PROJECT_SCOPE_ONLY_MESSAGE = 'oat providers set only supports project scope. Remove --scope or pass --scope project.';
function parseCsvList(raw) {
    if (!raw) {
        return [];
    }
    const parsed = raw
        .split(',')
        .map((entry) => entry.trim().toLowerCase())
        .filter((entry) => entry.length > 0);
    return [...new Set(parsed)];
}
function formatList(values) {
    return values.length > 0 ? values.join(', ') : '(none)';
}
function createDependencies() {
    return {
        buildCommandContext,
        async resolveScopeRoot(scope, context) {
            if (scope === 'project') {
                return resolveProjectRoot(context.cwd);
            }
            throw new Error(PROJECT_SCOPE_ONLY_MESSAGE);
        },
        getAdapters() {
            return [
                claudeAdapter,
                cursorAdapter,
                codexAdapter,
                copilotAdapter,
                geminiAdapter,
            ];
        },
        async loadSyncConfig(configPath) {
            return loadSyncConfig(configPath, DEFAULT_SYNC_CONFIG);
        },
        saveSyncConfig,
    };
}
function buildUpdatedConfig(config, enabledProviders, disabledProviders) {
    const providers = {
        ...config.providers,
    };
    for (const provider of enabledProviders) {
        providers[provider] = {
            ...(providers[provider] ?? {}),
            enabled: true,
        };
    }
    for (const provider of disabledProviders) {
        providers[provider] = {
            ...(providers[provider] ?? {}),
            enabled: false,
        };
    }
    return {
        ...config,
        providers,
    };
}
async function runProvidersSetCommand(context, options, dependencies) {
    try {
        if (context.scope !== 'project') {
            throw new Error(PROJECT_SCOPE_ONLY_MESSAGE);
        }
        const enabledProviders = parseCsvList(options.enabled);
        const disabledProviders = parseCsvList(options.disabled);
        if (enabledProviders.length === 0 && disabledProviders.length === 0) {
            throw new Error('No provider updates requested. Pass --enabled <providers> and/or --disabled <providers>.');
        }
        const overlap = enabledProviders.filter((provider) => disabledProviders.includes(provider));
        if (overlap.length > 0) {
            throw new Error(`Providers cannot be both enabled and disabled: ${overlap.join(', ')}`);
        }
        const knownProviders = dependencies
            .getAdapters()
            .map((adapter) => adapter.name);
        const unknown = [...enabledProviders, ...disabledProviders].filter((provider) => !knownProviders.includes(provider));
        if (unknown.length > 0) {
            throw new Error(`Unknown providers: ${[...new Set(unknown)].join(', ')}. Known providers: ${knownProviders.join(', ')}`);
        }
        const scopeRoot = await dependencies.resolveScopeRoot('project', context);
        const configPath = join(scopeRoot, '.oat', 'sync', 'config.json');
        const config = await dependencies.loadSyncConfig(configPath);
        const updated = buildUpdatedConfig(config, enabledProviders, disabledProviders);
        const saved = await dependencies.saveSyncConfig(configPath, updated);
        if (context.json) {
            context.logger.json({
                status: 'ok',
                scope: 'project',
                configPath,
                enabled: enabledProviders,
                disabled: disabledProviders,
                providers: saved.providers,
            });
        }
        else {
            context.logger.info(`Updated provider configuration: ${configPath}`);
            context.logger.info(`Enabled: ${formatList(enabledProviders)}`);
            context.logger.info(`Disabled: ${formatList(disabledProviders)}`);
        }
        process.exitCode = 0;
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        if (context.json) {
            context.logger.json({ status: 'error', message });
        }
        else {
            context.logger.error(message);
        }
        process.exitCode = 1;
    }
}
export function createProvidersSetCommand(overrides = {}) {
    const dependencies = {
        ...createDependencies(),
        ...overrides,
    };
    // Default to 'project' scope: providers set only supports project scope, so
    // a bare `oat providers set --enabled X` should succeed without requiring
    // an explicit --scope project flag.
    return withScopeOption(new Command('set'), 'project')
        .description('Enable or disable project providers in sync config')
        .option('--enabled <providers>', 'Comma-separated providers to enable')
        .option('--disabled <providers>', 'Comma-separated providers to disable')
        .action(async (options, command) => {
        const context = dependencies.buildCommandContext(readGlobalOptions(command));
        await runProvidersSetCommand(context, options, dependencies);
    });
}
