import fs from 'fs';
import path from 'path';
import yaml from 'js-yaml';
export function loadSquad(squadDir) {
    const yamlPath = path.join(squadDir, 'squad.yaml');
    if (!fs.existsSync(yamlPath)) {
        throw new Error(`squad.yaml not found in ${squadDir}`);
    }
    const raw = fs.readFileSync(yamlPath, 'utf-8');
    const parsed = yaml.load(raw);
    if (!parsed || typeof parsed !== 'object' || !parsed.squad) {
        throw new Error('Missing required field: squad');
    }
    const squad = parsed.squad;
    const requiredFields = ['code', 'name', 'description', 'icon', 'agents', 'pipeline'];
    for (const field of requiredFields) {
        if (squad[field] === undefined || squad[field] === null) {
            throw new Error(`Missing required field: squad.${field}`);
        }
    }
    const agents = squad.agents;
    if (!Array.isArray(agents) || agents.length === 0) {
        throw new Error('Missing required field: squad.agents must be a non-empty array');
    }
    const pipeline = squad.pipeline;
    if (!pipeline || !pipeline.steps) {
        throw new Error('Missing required field: squad.pipeline.steps');
    }
    const steps = pipeline.steps;
    const agentIds = new Set(agents.map(a => a.id));
    const VALID_PROVIDERS = ['claude-code', 'anthropic', 'openai'];
    for (const agent of agents) {
        if (agent.provider && !VALID_PROVIDERS.includes(agent.provider)) {
            throw new Error(`Agent "${agent.id}" has invalid provider "${agent.provider}". Valid values: ${VALID_PROVIDERS.join(', ')}`);
        }
    }
    for (const step of steps) {
        if (!agentIds.has(step.agent)) {
            throw new Error(`Agent "${step.agent}" not found in agents list (referenced by step "${step.id}")`);
        }
        if (step.deliverFrom && !agentIds.has(step.deliverFrom)) {
            throw new Error(`deliverFrom agent "${step.deliverFrom}" not found in agents list (referenced by step "${step.id}")`);
        }
    }
    const skills = squad.skills ?? [];
    // Parse chain: string or string[]
    let chain;
    const rawChain = squad.chain;
    if (rawChain) {
        if (typeof rawChain === 'string') {
            chain = [rawChain];
        }
        else if (Array.isArray(rawChain)) {
            chain = rawChain;
        }
    }
    const rawSchedule = squad.schedule;
    let schedule;
    if (rawSchedule && rawSchedule.enabled) {
        const timeoutMin = rawSchedule.timeout_minutes ?? 30;
        if (timeoutMin < 1 || timeoutMin > 480) {
            throw new Error('schedule.timeout_minutes must be between 1 and 480');
        }
        const retry = rawSchedule.retry_on_failure ?? 0;
        if (retry < 0 || retry > 5) {
            throw new Error('schedule.retry_on_failure must be between 0 and 5');
        }
        schedule = {
            enabled: true,
            cron: rawSchedule.cron || '',
            timezone: rawSchedule.timezone,
            mode: 'autonomous',
            prompt: rawSchedule.prompt || '',
            timeout_minutes: timeoutMin,
            retry_on_failure: retry,
        };
    }
    else if (rawSchedule) {
        schedule = { ...rawSchedule, enabled: false };
    }
    const group = squad.group;
    const setor = squad.setor;
    const grupo = squad.grupo;
    const sessao = squad.sessao;
    const rawWebhooks = squad.webhooks;
    const webhooks = rawWebhooks ? { secret: rawWebhooks.secret } : undefined;
    const rawSpend = squad.spendControl;
    let spendControl;
    if (rawSpend) {
        spendControl = {
            maxCostPerRun: typeof rawSpend.maxCostPerRun === 'number' ? rawSpend.maxCostPerRun : undefined,
            mode: (rawSpend.mode === 'strict' ? 'strict' : 'graceful'),
        };
        if (spendControl.maxCostPerRun !== undefined && spendControl.maxCostPerRun <= 0) {
            throw new Error('spendControl.maxCostPerRun must be a positive number');
        }
    }
    const rawVisual = squad.visual_templates;
    let visualTemplates;
    if (rawVisual && rawVisual.enabled) {
        visualTemplates = {
            enabled: true,
            format: rawVisual.format,
            count: typeof rawVisual.count === 'number' ? rawVisual.count : undefined,
        };
    }
    const mcps = Array.isArray(squad.mcps) ? squad.mcps : [];
    return {
        squad: {
            code: squad.code,
            setor,
            grupo,
            sessao,
            group,
            name: squad.name,
            description: squad.description,
            icon: squad.icon,
            agents,
            skills,
            pipeline: { steps },
            schedule,
            chain,
            webhooks,
            spendControl,
            visualTemplates,
            mcps,
        },
    };
}
export function findSquadDir(squadsDir, code) {
    if (!fs.existsSync(squadsDir))
        return null;
    const matches = [];
    function walk(dir, depth) {
        if (depth > 4)
            return;
        const yamlPath = path.join(dir, 'squad.yaml');
        if (fs.existsSync(yamlPath)) {
            // This is a squad directory — check its code, don't recurse further
            try {
                const raw = fs.readFileSync(yamlPath, 'utf-8');
                const parsed = yaml.load(raw);
                const squadCode = parsed?.squad?.code;
                if (squadCode === code) {
                    matches.push(dir);
                }
            }
            catch {
                // Invalid YAML — skip
            }
            return;
        }
        // No squad.yaml here — recurse into subdirectories
        let entries;
        try {
            entries = fs.readdirSync(dir, { withFileTypes: true });
        }
        catch {
            return;
        }
        for (const entry of entries) {
            if (!entry.isDirectory())
                continue;
            if (entry.name.startsWith('.') || entry.name.startsWith('_'))
                continue;
            walk(path.join(dir, entry.name), depth + 1);
        }
    }
    walk(squadsDir, 0);
    if (matches.length === 0)
        return null;
    if (matches.length > 1) {
        process.stderr.write(`Warning: duplicate squad code "${code}" found in: ${matches.join(', ')}. Using first match.\n`);
    }
    return matches[0];
}
