import path from 'node:path';
import { appendJsonl, nowIso, readJson, writeJsonAtomic } from '../fsx.js';
import { normalizeAgentFollowUpWorkItems } from './agent-follow-up-work-items.js';
export const AGENT_WORK_QUEUE_SCHEMA = 'sks.agent-work-queue.v1';
export const AGENT_WORK_QUEUE_EVENT_SCHEMA = 'sks.agent-work-queue-event.v1';
export function createAgentWorkQueue(input = {}) {
    const sourceSlices = Array.isArray(input.slices) && input.slices.length
        ? input.slices
        : [{ id: 'slice-01', role: 'verifier', description: input.prompt || 'Native agent work item', write_paths: [], readonly_paths: [] }];
    const items = sourceSlices.map((slice, index) => ({
        id: String(slice.id || `work-${String(index + 1).padStart(3, '0')}`),
        title: String(slice.title || slice.id || `Work item ${index + 1}`),
        description: String(slice.description || input.prompt || 'Native agent work item'),
        required_persona_category: String(slice.required_persona_category || slice.role || 'verifier'),
        lease_requirements: [
            ...(Array.isArray(slice.write_paths) ? slice.write_paths.map((file) => ({ kind: 'write', path: file })) : []),
            ...(Array.isArray(slice.readonly_paths) ? slice.readonly_paths.map((file) => ({ kind: 'read', path: file })) : [])
        ],
        dependencies: Array.isArray(slice.dependencies) ? slice.dependencies.map(String) : [],
        priority: Number.isFinite(Number(slice.priority)) ? Number(slice.priority) : index + 1,
        status: 'pending',
        attempts: 0,
        max_attempts: Number.isFinite(Number(slice.max_attempts)) ? Number(slice.max_attempts) : 1,
        running_session_id: null,
        completed_session_id: null,
        blocked_reason: null,
        follow_up_origin_session_id: null,
        source_intelligence_refs: input.sourceIntelligenceRefs || null,
        goal_mode_ref: input.goalModeRef || null,
        slice: slice || {}
    }));
    return {
        schema: AGENT_WORK_QUEUE_SCHEMA,
        updated_at: nowIso(),
        total_work_items: items.length,
        generated_work_item_count: 0,
        max_queue_expansion: input.maxQueueExpansion ?? 10,
        items
    };
}
export function pendingWorkItems(queue) {
    const completed = new Set(queue.items.filter((item) => item.status === 'completed').map((item) => item.id));
    return queue.items
        .filter((item) => item.status === 'pending' && item.dependencies.every((dep) => completed.has(dep)))
        .sort((a, b) => a.priority - b.priority || a.id.localeCompare(b.id));
}
export function leaseNextWorkItem(queue, sessionId, opts = {}) {
    const activeWritePaths = new Set((opts.activeWritePaths || []).map(normalizePath).filter(Boolean));
    const ready = pendingWorkItems(queue).filter((candidate) => {
        const writePaths = sliceWritePaths(candidate);
        return writePaths.every((file) => !activeWritePaths.has(file));
    });
    const item = ready.find((candidate) => ownerMatches(candidate, opts))
        || ready.find((candidate) => !candidateOwner(candidate))
        || ready[0];
    if (!item)
        return null;
    item.status = 'running';
    item.attempts += 1;
    item.running_session_id = sessionId;
    queue.updated_at = nowIso();
    return item;
}
function ownerMatches(item, opts) {
    const owner = candidateOwner(item);
    if (!owner)
        return false;
    return owner === opts.slotId || owner === opts.agentId;
}
function candidateOwner(item) {
    const slice = item.slice || {};
    return String(slice.owner_agent_id || slice.owner || slice.lane || '').trim();
}
function sliceWritePaths(item) {
    const paths = Array.isArray(item.slice?.write_paths) ? item.slice.write_paths : [];
    return paths.map((file) => normalizePath(String(file))).filter(Boolean);
}
function normalizePath(file) {
    return String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, '');
}
export function completeWorkItem(queue, itemId, sessionId, status, reason = null) {
    const item = queue.items.find((row) => row.id === itemId);
    if (!item)
        return null;
    item.status = status;
    item.running_session_id = null;
    item.completed_session_id = sessionId;
    item.blocked_reason = reason;
    queue.updated_at = nowIso();
    return item;
}
export function enqueueFollowUpWorkItems(queue, items, input) {
    const accepted = [];
    const validation = normalizeAgentFollowUpWorkItems(items, { originSessionId: input.originSessionId });
    const validItems = validation.accepted;
    const remainingCapacity = Math.max(0, queue.max_queue_expansion - queue.generated_work_item_count);
    for (const [index, raw] of validItems.slice(0, remainingCapacity).entries()) {
        const id = String(raw.id || `follow-up-${queue.generated_work_item_count + index + 1}`);
        if (queue.items.some((item) => item.id === id))
            continue;
        accepted.push({
            id,
            title: String(raw.title || id),
            description: String(raw.description || id),
            required_persona_category: String(raw.required_persona_category || 'verifier'),
            lease_requirements: Array.isArray(raw.lease_requirements) ? raw.lease_requirements : [],
            dependencies: Array.isArray(raw.dependencies) ? raw.dependencies.map(String) : [],
            priority: Number.isFinite(Number(raw.priority)) ? Number(raw.priority) : queue.items.length + accepted.length + 1,
            status: 'pending',
            attempts: 0,
            max_attempts: Number.isFinite(Number(raw.max_attempts)) ? Number(raw.max_attempts) : 1,
            running_session_id: null,
            completed_session_id: null,
            blocked_reason: null,
            follow_up_origin_session_id: input.originSessionId,
            source_intelligence_refs: input.sourceIntelligenceRefs || null,
            goal_mode_ref: input.goalModeRef || null,
            slice: raw
        });
    }
    queue.items.push(...accepted);
    queue.generated_work_item_count += accepted.length;
    queue.total_work_items = queue.items.length;
    queue.updated_at = nowIso();
    return {
        accepted,
        blocked_count: validation.blockers.length + Math.max(0, validItems.length - accepted.length),
        blocked: [
            ...validation.blockers,
            ...(validItems.length > accepted.length ? ['follow_up_work_items_exceeded_max_queue_expansion'] : [])
        ]
    };
}
export async function writeAgentWorkQueue(root, queue) {
    queue.updated_at = nowIso();
    queue.total_work_items = queue.items.length;
    await writeJsonAtomic(path.join(root, 'agent-work-queue.json'), queue);
    return queue;
}
export async function appendAgentWorkQueueEvent(root, eventType, payload = {}) {
    await appendJsonl(path.join(root, 'agent-work-queue-events.jsonl'), {
        schema: AGENT_WORK_QUEUE_EVENT_SCHEMA,
        ts: nowIso(),
        event_type: eventType,
        payload
    });
}
export async function readAgentWorkQueue(root) {
    return readJson(path.join(root, 'agent-work-queue.json'), {
        schema: AGENT_WORK_QUEUE_SCHEMA,
        updated_at: nowIso(),
        total_work_items: 0,
        generated_work_item_count: 0,
        max_queue_expansion: 10,
        items: []
    });
}
//# sourceMappingURL=agent-work-queue.js.map