import { join } from 'node:path';
import { buildCommandContext } from '../../../app/command-context.js';
import { withScopeOption } from '../../shared/scope-option.js';
import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.utils.js';
import { detectDrift } from '../../../drift/index.js';
import { normalizeToPosixPath, resolveProjectRoot, resolveScopeRoot, } from '../../../fs/paths.js';
import { loadManifest } from '../../../manifest/index.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 { getSyncMappings } from '../../../providers/shared/index.js';
import { Command } from 'commander';
function formatSummary(item) {
    const contentTypes = item.contentTypes.length > 0 ? item.contentTypes.join('|') : 'none';
    return [
        item.detected ? 'detected' : 'not detected',
        `strategy=${item.defaultStrategy}`,
        `content_types=${contentTypes}`,
        `managed=${item.summary.managed}`,
        `in_sync=${item.summary.inSync}`,
        `drifted=${item.summary.drifted}`,
        `missing=${item.summary.missing}`,
    ].join(', ');
}
function formatList(items) {
    if (items.length === 0) {
        return 'No provider adapters registered.';
    }
    const nameWidth = Math.max('Provider'.length, ...items.map((item) => item.name.length));
    const statusWidth = Math.max('Status'.length, ...items.map((item) => (item.detected ? 'detected' : 'not detected').length));
    const header = [
        'Provider'.padEnd(nameWidth),
        'Status'.padEnd(statusWidth),
        'Summary',
    ].join('  ');
    const divider = [
        '-'.repeat(nameWidth),
        '-'.repeat(statusWidth),
        '-------',
    ].join('  ');
    const rows = items.map((item) => {
        const status = item.detected ? 'detected' : 'not detected';
        return [
            item.name.padEnd(nameWidth),
            status.padEnd(statusWidth),
            formatSummary(item),
        ].join('  ');
    });
    return [header, divider, ...rows].join('\n');
}
function createDependencies() {
    return {
        buildCommandContext,
        async resolveScopeRoot(scope, context) {
            if (scope === 'project') {
                return resolveProjectRoot(context.cwd);
            }
            return resolveScopeRoot(scope, context.cwd, context.home);
        },
        getAdapters() {
            return [
                claudeAdapter,
                cursorAdapter,
                codexAdapter,
                copilotAdapter,
                geminiAdapter,
            ];
        },
        getSyncMappings,
        loadManifest,
        detectDrift,
    };
}
function createEmptySummary() {
    return {
        managed: 0,
        inSync: 0,
        drifted: 0,
        missing: 0,
    };
}
async function collectProviderList(context, dependencies) {
    const scopes = resolveConcreteScopes(context.scope);
    const scopeRoots = await Promise.all(scopes.map(async (scope) => ({
        scope,
        root: await dependencies.resolveScopeRoot(scope, context),
    })));
    const manifestsByRoot = new Map();
    for (const scopeRoot of scopeRoots) {
        const manifestPath = join(scopeRoot.root, '.oat', 'sync', 'manifest.json');
        manifestsByRoot.set(scopeRoot.root, await dependencies.loadManifest(manifestPath));
    }
    const items = [];
    for (const adapter of dependencies.getAdapters()) {
        const summary = createEmptySummary();
        const contentTypes = new Set();
        const allMappings = [];
        for (const scope of scopes) {
            for (const mapping of dependencies.getSyncMappings(adapter, scope)) {
                contentTypes.add(mapping.contentType);
                allMappings.push(mapping);
            }
        }
        let detected = false;
        for (const scopeRoot of scopeRoots) {
            if (await adapter.detect(scopeRoot.root)) {
                detected = true;
            }
            const manifest = manifestsByRoot.get(scopeRoot.root);
            if (!manifest) {
                continue;
            }
            for (const entry of manifest.entries) {
                if (entry.provider !== adapter.name) {
                    continue;
                }
                summary.managed += 1;
                const matchedMapping = allMappings.find((mapping) => {
                    const normalizedEntry = normalizeToPosixPath(entry.providerPath);
                    const normalizedDir = normalizeToPosixPath(mapping.providerDir);
                    return (mapping.contentType === entry.contentType &&
                        (normalizedEntry === normalizedDir ||
                            normalizedEntry.startsWith(`${normalizedDir}/`)));
                });
                const copyTransform = matchedMapping?.transformCanonical
                    ? { transformCanonical: matchedMapping.transformCanonical }
                    : undefined;
                const report = await dependencies.detectDrift(entry, scopeRoot.root, copyTransform);
                if (report.state.status === 'in_sync') {
                    summary.inSync += 1;
                    continue;
                }
                if (report.state.status === 'missing') {
                    summary.missing += 1;
                    continue;
                }
                if (report.state.status === 'drifted') {
                    summary.drifted += 1;
                }
            }
        }
        items.push({
            name: adapter.name,
            displayName: adapter.displayName,
            detected,
            defaultStrategy: adapter.defaultStrategy,
            contentTypes: [...contentTypes].sort(),
            summary,
        });
    }
    return items;
}
async function runListCommand(context, dependencies) {
    const items = await collectProviderList(context, dependencies);
    if (context.json) {
        context.logger.json(items);
    }
    else {
        context.logger.info(formatList(items));
    }
    process.exitCode = 0;
}
export function createProvidersListCommand(overrides = {}) {
    const dependencies = {
        ...createDependencies(),
        ...overrides,
    };
    return withScopeOption(new Command('list'))
        .description('List provider adapters and sync summary')
        .action(async (_options, command) => {
        const context = dependencies.buildCommandContext(readGlobalOptions(command));
        await runListCommand(context, dependencies);
    });
}
