import fs from 'fs-extra';
import { readJsonFile, writeJsonFile } from '../lib/json.js';
import { getPackagePath, getStatePath } from '../lib/paths.js';
import { CatalogItemSchema, CatalogMcpServerSchema, CatalogSkillSchema, QuarantineFileSchema, WhitelistFileSchema } from '../lib/validation/contracts.js';
const ITEMS_REL_PATH = 'data/catalog/items.json';
const SKILLS_REL_PATH = 'data/catalog/skills.json';
const MCPS_REL_PATH = 'data/catalog/mcps.json';
const WHITELIST_REL_PATH = 'data/whitelist/approved.json';
const QUARANTINE_REL_PATH = 'data/quarantine/quarantined.json';
export function getItemsPath() {
    return getStatePath(ITEMS_REL_PATH);
}
export function getSkillsPath() {
    return getStatePath(SKILLS_REL_PATH);
}
export function getMcpsPath() {
    return getStatePath(MCPS_REL_PATH);
}
export function getWhitelistPath() {
    return getStatePath(WHITELIST_REL_PATH);
}
export function getQuarantinePath() {
    return getStatePath(QUARANTINE_REL_PATH);
}
function getDefaultItemsPath() {
    return getPackagePath(ITEMS_REL_PATH);
}
function getDefaultSkillsPath() {
    return getPackagePath(SKILLS_REL_PATH);
}
function getDefaultMcpsPath() {
    return getPackagePath(MCPS_REL_PATH);
}
function getDefaultWhitelistPath() {
    return getPackagePath(WHITELIST_REL_PATH);
}
function getDefaultQuarantinePath() {
    return getPackagePath(QUARANTINE_REL_PATH);
}
export async function loadCatalogItems() {
    const primaryPath = getItemsPath();
    if (await fs.pathExists(primaryPath)) {
        return parseCatalogItems(await readJsonFile(primaryPath));
    }
    const fallbackPath = getDefaultItemsPath();
    if (await fs.pathExists(fallbackPath)) {
        return parseCatalogItems(await readJsonFile(fallbackPath));
    }
    return loadLegacyItems();
}
async function loadLegacyItems() {
    const [skills, mcps] = await Promise.all([loadSkillsCatalog(), loadMcpsCatalog()]);
    return [...skills, ...mcps];
}
export async function loadSkillsCatalog() {
    const raw = await readArrayFromStateOrPackage(getSkillsPath(), getDefaultSkillsPath());
    return raw.map((entry) => {
        const value = ensureObject(entry);
        return CatalogSkillSchema.parse({ ...value, kind: 'skill', provider: readProvider(entry, 'openai') });
    });
}
export async function loadMcpsCatalog() {
    const raw = await readArrayFromStateOrPackage(getMcpsPath(), getDefaultMcpsPath());
    return raw.map((entry) => {
        const value = ensureObject(entry);
        return CatalogMcpServerSchema.parse({ ...value, kind: 'mcp', provider: readProvider(entry, 'mcp') });
    });
}
function readProvider(value, fallback) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return fallback;
    }
    const provider = value.provider;
    return typeof provider === 'string' && provider.trim().length > 0 ? provider.trim() : fallback;
}
function ensureObject(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return {};
    }
    return value;
}
export async function saveCatalogItems(records) {
    await writeJsonFile(getItemsPath(), records);
}
export async function saveSkillsCatalog(records) {
    await writeJsonFile(getSkillsPath(), records);
}
export async function saveMcpsCatalog(records) {
    await writeJsonFile(getMcpsPath(), records);
}
export async function saveLegacyCatalogViews(records) {
    const skills = records
        .filter((item) => item.kind === 'skill')
        .map((item) => CatalogSkillSchema.parse(item));
    const mcps = records
        .filter((item) => item.kind === 'mcp')
        .map((item) => CatalogMcpServerSchema.parse(item));
    await Promise.all([saveSkillsCatalog(skills), saveMcpsCatalog(mcps)]);
}
export async function loadWhitelist() {
    const raw = await readObjectFromStateOrPackage(getWhitelistPath(), getDefaultWhitelistPath());
    if (!raw) {
        return new Set();
    }
    const parsed = WhitelistFileSchema.parse(raw);
    return new Set(parsed.approved);
}
export async function saveWhitelist(ids) {
    const approved = Array.from(new Set(ids)).sort((a, b) => a.localeCompare(b));
    await writeJsonFile(getWhitelistPath(), { approved });
}
export async function loadQuarantine() {
    const raw = await readObjectFromStateOrPackage(getQuarantinePath(), getDefaultQuarantinePath());
    if (!raw) {
        return [];
    }
    const parsed = QuarantineFileSchema.parse(raw);
    return parsed.quarantined;
}
export async function saveQuarantine(entries) {
    const deduped = new Map();
    entries.forEach((entry) => deduped.set(entry.id, entry));
    const sorted = Array.from(deduped.values()).sort((a, b) => a.id.localeCompare(b.id));
    await writeJsonFile(getQuarantinePath(), { quarantined: sorted });
}
export async function loadCatalogItemById(id) {
    const records = await loadCatalogItems();
    return records.find((entry) => entry.id === id) ?? null;
}
export async function loadCatalogById(id) {
    const found = await loadCatalogItemById(id);
    if (!found) {
        return null;
    }
    if (found.kind === 'skill') {
        return { kind: 'skill', item: CatalogSkillSchema.parse(found) };
    }
    if (found.kind === 'mcp') {
        return { kind: 'mcp', item: CatalogMcpServerSchema.parse(found) };
    }
    return { kind: found.kind, item: found };
}
async function readArrayFromStateOrPackage(statePath, packagePath) {
    const preferred = await readObjectFromStateOrPackage(statePath, packagePath);
    if (!preferred) {
        return [];
    }
    return Array.isArray(preferred) ? preferred : [];
}
async function readObjectFromStateOrPackage(statePath, packagePath) {
    if (await fs.pathExists(statePath)) {
        return readJsonFile(statePath);
    }
    if (await fs.pathExists(packagePath)) {
        return readJsonFile(packagePath);
    }
    return null;
}
function parseCatalogItems(raw) {
    return raw.map((entry) => CatalogItemSchema.parse(entry));
}
