import { join } from 'node:path';
import { BRAINSTORM_SKILLS, CORE_SKILLS, DOCS_SKILLS, DOCS_SCRIPTS, IDEA_SKILLS, PROJECT_MANAGEMENT_SKILLS, PROJECT_MANAGEMENT_SCRIPTS, PROJECT_MANAGEMENT_TEMPLATES, RESEARCH_AGENTS, RESEARCH_SKILLS, UTILITY_SKILLS, WORKFLOW_AGENTS, WORKFLOW_SKILLS, WORKFLOW_SCRIPTS, WORKFLOW_TEMPLATES, } from '../../init/tools/shared/skill-manifest.js';
const BUNDLED_PACK_MEMBERS = {
    core: CORE_SKILLS.map((name) => ({ name, type: 'skill' })),
    ideas: IDEA_SKILLS.map((name) => ({ name, type: 'skill' })),
    docs: DOCS_SKILLS.map((name) => ({ name, type: 'skill' })),
    workflows: [
        ...WORKFLOW_SKILLS.map((name) => ({ name, type: 'skill' })),
        ...WORKFLOW_AGENTS.map((name) => ({
            name: name.replace(/\.md$/, ''),
            type: 'agent',
        })),
    ],
    utility: UTILITY_SKILLS.map((name) => ({ name, type: 'skill' })),
    'project-management': PROJECT_MANAGEMENT_SKILLS.map((name) => ({
        name,
        type: 'skill',
    })),
    research: [
        ...RESEARCH_SKILLS.map((name) => ({ name, type: 'skill' })),
        ...RESEARCH_AGENTS.map((name) => ({
            name: name.replace(/\.md$/, ''),
            type: 'agent',
        })),
    ],
    brainstorm: BRAINSTORM_SKILLS.map((name) => ({ name, type: 'skill' })),
};
const BUNDLED_PACK_ASSETS = {
    core: {
        templates: [],
        scripts: [],
    },
    ideas: {
        templates: [],
        scripts: [],
    },
    docs: {
        templates: [],
        scripts: DOCS_SCRIPTS,
    },
    workflows: {
        templates: WORKFLOW_TEMPLATES,
        scripts: WORKFLOW_SCRIPTS,
    },
    utility: {
        templates: [],
        scripts: [],
    },
    'project-management': {
        templates: PROJECT_MANAGEMENT_TEMPLATES,
        scripts: PROJECT_MANAGEMENT_SCRIPTS,
    },
    research: {
        templates: [],
        scripts: [],
    },
    brainstorm: {
        templates: [],
        scripts: [],
    },
};
export async function updateTools(target, scopes, cwd, home, dryRun, dependencies) {
    const assetsRoot = await dependencies.resolveAssetsRoot();
    const result = {
        updated: [],
        current: [],
        newer: [],
        notInstalled: [],
        notBundled: [],
        assetRefreshes: [],
    };
    const allTools = [];
    for (const scope of scopes) {
        const scopeRoot = await dependencies.resolveScopeRoot(scope, cwd, home);
        const tools = await dependencies.scanTools({
            scope,
            scopeRoot,
            assetsRoot,
        });
        for (const tool of tools) {
            allTools.push({ tool, scopeRoot });
        }
    }
    const targetEntries = target.kind === 'name'
        ? allTools
        : expandInstalledPackEntries(target, allTools);
    const targets = resolveTargets(target, targetEntries.map((t) => t.tool));
    if (target.kind === 'name' && targets.length === 0) {
        result.notInstalled.push(target.name);
        return result;
    }
    for (const targetTool of targets) {
        const entry = targetEntries.find((t) => t.tool === targetTool);
        if (!entry)
            continue;
        const { tool, scopeRoot } = entry;
        if (tool.status === 'not-bundled') {
            result.notBundled.push(tool);
            continue;
        }
        if (tool.status === 'current') {
            result.current.push(tool);
            continue;
        }
        if (tool.status === 'newer') {
            result.newer.push(tool);
            continue;
        }
        // outdated — perform update
        if (!dryRun) {
            if (tool.type === 'skill') {
                const source = join(assetsRoot, 'skills', tool.name);
                const destination = join(scopeRoot, '.agents', 'skills', tool.name);
                await dependencies.copyDirWithStatus(source, destination, true);
            }
            else {
                const filename = `${tool.name}.md`;
                const source = join(assetsRoot, 'agents', filename);
                const destination = join(scopeRoot, '.agents', 'agents', filename);
                await dependencies.copyFileWithStatus(source, destination, true);
            }
        }
        result.updated.push(tool);
    }
    for (const assetTarget of resolvePackAssetTargets(target, allTools)) {
        const assets = BUNDLED_PACK_ASSETS[assetTarget.pack];
        for (const template of assets.templates) {
            const source = join(assetsRoot, 'templates', template);
            const destination = join(assetTarget.scopeRoot, '.oat', 'templates', template);
            if (!dryRun) {
                await dependencies.copyFileWithStatus(source, destination, true);
            }
            result.assetRefreshes.push({
                name: template,
                type: 'template',
                pack: assetTarget.pack,
                scope: assetTarget.scope,
                status: dryRun ? 'planned' : 'refreshed',
            });
        }
        for (const script of assets.scripts) {
            const source = join(assetsRoot, 'scripts', script);
            if (!(await dependencies.fileExists(source))) {
                continue;
            }
            const destination = join(assetTarget.scopeRoot, '.oat', 'scripts', script);
            if (!dryRun) {
                await dependencies.copyFileWithStatus(source, destination, true);
                await dependencies.chmod(destination, 0o755);
            }
            result.assetRefreshes.push({
                name: script,
                type: 'script',
                pack: assetTarget.pack,
                scope: assetTarget.scope,
                status: dryRun ? 'planned' : 'refreshed',
            });
        }
    }
    return result;
}
function expandInstalledPackEntries(target, installedEntries) {
    const entries = [...installedEntries];
    const seen = new Set(installedEntries.map((entry) => buildEntryKey(entry.tool)));
    const entriesByScope = new Map();
    for (const entry of installedEntries) {
        const scopeEntries = entriesByScope.get(entry.tool.scope) ?? [];
        scopeEntries.push(entry);
        entriesByScope.set(entry.tool.scope, scopeEntries);
    }
    for (const [scope, scopeEntries] of entriesByScope) {
        const scopeRoot = scopeEntries[0]?.scopeRoot;
        if (!scopeRoot)
            continue;
        const installedPacks = new Set(scopeEntries
            .map((entry) => entry.tool.pack)
            .filter((pack) => pack !== 'custom'));
        const packsToExpand = target.kind === 'pack'
            ? installedPacks.has(target.pack)
                ? [target.pack]
                : []
            : [...installedPacks];
        for (const pack of packsToExpand) {
            for (const member of getBundledPackMembers(pack, scope)) {
                const tool = {
                    name: member.name,
                    type: member.type,
                    scope,
                    version: null,
                    bundledVersion: null,
                    pack,
                    status: 'outdated',
                };
                const key = buildEntryKey(tool);
                if (seen.has(key))
                    continue;
                entries.push({ tool, scopeRoot });
                seen.add(key);
            }
        }
    }
    return entries;
}
function getBundledPackMembers(pack, scope) {
    return BUNDLED_PACK_MEMBERS[pack].filter((member) => scope === 'project' || member.type === 'skill' || pack === 'workflows');
}
function resolvePackAssetTargets(target, installedEntries) {
    if (target.kind === 'name') {
        return [];
    }
    const entriesByScope = new Map();
    for (const entry of installedEntries) {
        const scopeEntries = entriesByScope.get(entry.tool.scope) ?? [];
        scopeEntries.push(entry);
        entriesByScope.set(entry.tool.scope, scopeEntries);
    }
    const targets = [];
    for (const [scope, scopeEntries] of entriesByScope) {
        const scopeRoot = scopeEntries[0]?.scopeRoot;
        if (!scopeRoot)
            continue;
        const installedPacks = new Set(scopeEntries
            .map((entry) => entry.tool.pack)
            .filter((pack) => pack !== 'custom'));
        const packsToExpand = target.kind === 'pack'
            ? installedPacks.has(target.pack)
                ? [target.pack]
                : []
            : [...installedPacks];
        for (const pack of packsToExpand) {
            const assets = BUNDLED_PACK_ASSETS[pack];
            if (assets.templates.length === 0 && assets.scripts.length === 0) {
                continue;
            }
            targets.push({ pack, scope, scopeRoot });
        }
    }
    return targets;
}
function buildEntryKey(tool) {
    return [tool.scope, tool.type, tool.name].join(':');
}
function resolveTargets(target, tools) {
    switch (target.kind) {
        case 'name':
            return tools.filter((t) => t.name === target.name);
        case 'pack':
            return tools.filter((t) => t.pack === target.pack);
        case 'all':
            return tools;
    }
}
