import { join } from 'node:path';
import { InstallerError, copyTree, dirExists, ensureDirectory, fileExists, readJson, replaceTree, writeJson } from './utils.js';
function codexMarketplacePath(targetRoot) {
    return join(targetRoot, '.agents', 'plugins', 'marketplace.json');
}
function parseMarketplace(path) {
    if (!fileExists(path)) {
        return null;
    }
    return readJson(path);
}
function defaultMarketplace() {
    return {
        name: 'loom-local',
        interface: {
            displayName: 'Loom Local Plugins',
        },
        plugins: [],
    };
}
function loomMarketplaceEntry() {
    return {
        name: 'loom',
        source: {
            source: 'local',
            path: './plugins/loom',
        },
        policy: {
            installation: 'AVAILABLE',
            authentication: 'ON_INSTALL',
        },
        category: 'Productivity',
    };
}
function ensureMarketplace(targetRoot, force) {
    const marketplacePath = codexMarketplacePath(targetRoot);
    const marketplace = parseMarketplace(marketplacePath) ?? defaultMarketplace();
    if (!Array.isArray(marketplace.plugins)) {
        throw new InstallerError('Codex marketplace.json must contain a plugins array');
    }
    const expectedPath = './plugins/loom';
    const existing = marketplace.plugins.find((entry) => typeof entry === 'object' && entry !== null && entry.name === 'loom');
    if (existing && existing.source?.path && existing.source.path !== expectedPath && !force) {
        throw new InstallerError(`Codex marketplace already declares loom from a different path: ${existing.source.path}`, `refusing to take over non-Loom marketplace entry for loom: ${existing.source.path}`);
    }
    if (!existing) {
        marketplace.plugins.push(loomMarketplaceEntry());
    }
    else if (force) {
        const index = marketplace.plugins.indexOf(existing);
        marketplace.plugins[index] = loomMarketplaceEntry();
    }
    writeJson(marketplacePath, marketplace);
    return [marketplacePath];
}
export function installCodexPlugin(targetRoot, packageRoot, manifest, force) {
    const pluginSource = join(packageRoot, 'payload', manifest.plugin.relative_path);
    const pluginTarget = join(targetRoot, 'plugins', 'loom');
    const pluginManifestPath = join(pluginTarget, '.codex-plugin', 'plugin.json');
    const installedPaths = [];
    const warnings = [];
    if (dirExists(pluginTarget) && !force) {
        if (!fileExists(pluginManifestPath)) {
            throw new InstallerError(`target already contains plugins/loom but it is not a Loom plugin: ${pluginTarget}`, `refusing to take over non-Loom plugin directory: ${pluginTarget}`);
        }
    }
    if (dirExists(pluginTarget)) {
        replaceTree(pluginSource, pluginTarget);
    }
    else {
        copyTree(pluginSource, pluginTarget, true);
    }
    installedPaths.push(pluginTarget);
    installedPaths.push(...ensureMarketplace(targetRoot, force));
    const pluginManifest = readJson(pluginManifestPath);
    if (pluginManifest.name !== 'loom') {
        throw new InstallerError('Codex plugin installation drifted: plugin name must stay `loom`');
    }
    warnings.push('Codex plugin install remains repo-local; it does not replace the Python runtime.');
    return {
        mode: 'plugin',
        host: 'codex',
        distribution_layer: 'host-adapter-plugin',
        status: 'installed',
        installed_paths: installedPaths,
        verification: [
            `verified plugin payload at ${pluginTarget}`,
            `verified marketplace entry at ${codexMarketplacePath(targetRoot)}`,
        ],
        warnings,
        version_context: null,
        failed_layer: null,
        fail_closed_reason: null,
    };
}
export function installCodexSkill(_env, targetRoot, packageRoot, skill, force) {
    const skillDirName = skill.id.startsWith('loom-') ? skill.id : `loom-${skill.id}`;
    const sourceDir = join(packageRoot, 'payload', skill.relative_path);
    const targetDir = join(targetRoot, '.agents', 'skills', skillDirName);
    const skillMarkdownPath = join(targetDir, 'SKILL.md');
    ensureDirectory(join(targetRoot, '.agents', 'skills'));
    if (dirExists(targetDir)) {
        if (!force && !fileExists(skillMarkdownPath)) {
            throw new InstallerError(`target already contains .agents/skills/${skillDirName} but it is not a Loom skill: ${targetDir}`, `refusing to take over non-Loom repo skill directory: ${targetDir}`);
        }
        replaceTree(sourceDir, targetDir);
    }
    else {
        copyTree(sourceDir, targetDir, true);
    }
    if (!fileExists(skillMarkdownPath)) {
        throw new InstallerError(`Codex repo skill install is missing SKILL.md: ${skillMarkdownPath}`);
    }
    return {
        mode: 'skill',
        host: 'codex',
        distribution_layer: 'generated-single-skill',
        status: 'installed',
        installed_paths: [targetDir],
        verification: [
            `verified skill payload at ${targetDir}`,
            `verified repo skill discovery path at ${skillMarkdownPath}`,
        ],
        warnings: ['Codex repo-scoped single-skill install exposes only the named skill, not the full Loom plugin surface.'],
        version_context: null,
        failed_layer: null,
        fail_closed_reason: null,
    };
}
