import { randomUUID } from "node:crypto";
import { createDocumentStore } from "./state-backend.js";
export const QUEUE_PLAN_STATUSES = [
    "draft",
    "review",
    "approved",
    "queued",
    "in_progress",
    "done",
    "failed",
    "aborted",
    "archived",
];
export class QueuePlanStore {
    store;
    constructor(workspace, backend = "json") {
        this.store = createDocumentStore({
            workspace,
            backend,
            fileName: "queue-plans.json",
            sqliteKey: "queue-plans",
        });
    }
    list() {
        return this.payload().plans.sort(sortPlans);
    }
    get(id) {
        return this.payload().plans.find((plan) => plan.id === id) ?? null;
    }
    save(input) {
        const now = new Date().toISOString();
        const id = normalizeId(input.id) || createQueuePlanId();
        let plan;
        this.store.update((current) => {
            const payload = this.normalizePayload(current);
            const existing = payload.plans.find((candidate) => candidate.id === id);
            plan = normalizePlan({
                ...existing,
                ...input,
                id,
                createdAt: existing?.createdAt ?? input.createdAt ?? now,
                updatedAt: now,
            });
            payload.plans = upsertById(payload.plans, plan);
            return payload;
        });
        return plan;
    }
    patch(id, patch) {
        let updated = null;
        this.store.update((current) => {
            const payload = this.normalizePayload(current);
            const existing = payload.plans.find((plan) => plan.id === id);
            if (!existing)
                return payload;
            updated = normalizePlan({
                ...existing,
                ...patch,
                id,
                updatedAt: patch.updatedAt ?? new Date().toISOString(),
            });
            payload.plans = upsertById(payload.plans, updated);
            return payload;
        });
        return updated;
    }
    delete(id) {
        let removed = false;
        this.store.update((current) => {
            const payload = this.normalizePayload(current);
            const next = payload.plans.filter((plan) => plan.id !== id);
            removed = next.length !== payload.plans.length;
            payload.plans = next;
            return payload;
        });
        return removed;
    }
    payload() {
        return this.normalizePayload(this.store.read());
    }
    normalizePayload(payload) {
        if (!payload || payload.version !== 1) {
            return { version: 1, plans: [] };
        }
        return {
            version: 1,
            plans: Array.isArray(payload.plans) ? payload.plans.map(normalizePlan).filter((plan) => plan.prompt) : [],
        };
    }
}
function normalizePlan(input) {
    const now = new Date().toISOString();
    const prompt = String(input.prompt ?? "").trim();
    return {
        id: normalizeId(input.id) || createQueuePlanId(),
        title: cleanOptional(input.title) || promptTitle(prompt),
        prompt,
        status: normalizeStatus(input.status),
        labels: normalizeLabels(input.labels),
        priority: normalizePriority(input.priority),
        agentId: input.agentId,
        workspace: cleanOptional(input.workspace),
        threadId: cleanOptional(input.threadId),
        queueId: cleanOptional(input.queueId),
        correlationId: cleanOptional(input.correlationId),
        ownerUserId: cleanOptional(input.ownerUserId),
        approvedBy: cleanOptional(input.approvedBy),
        createdAt: validDate(input.createdAt) ?? now,
        updatedAt: validDate(input.updatedAt) ?? now,
        queuedAt: validDate(input.queuedAt),
        startedAt: validDate(input.startedAt),
        finishedAt: validDate(input.finishedAt),
        error: cleanOptional(input.error),
    };
}
function promptTitle(prompt) {
    const firstLine = prompt.replace(/\s+/g, " ").trim();
    return firstLine.length <= 80 ? firstLine || "Untitled prompt" : `${firstLine.slice(0, 79)}…`;
}
function normalizeStatus(status) {
    return QUEUE_PLAN_STATUSES.includes(status) ? status : "draft";
}
function normalizeLabels(labels) {
    if (!Array.isArray(labels))
        return [];
    return [...new Set(labels.map((label) => String(label).trim()).filter(Boolean))];
}
function normalizePriority(priority) {
    const value = Number(priority);
    return Number.isFinite(value) ? Math.max(0, Math.min(100, Math.round(value))) : 0;
}
function normalizeId(id) {
    return String(id ?? "").trim().replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 64);
}
function createQueuePlanId() {
    return `qp_${randomUUID().replace(/-/g, "").slice(0, 10)}`;
}
function cleanOptional(value) {
    const text = String(value ?? "").trim();
    return text || undefined;
}
function validDate(value) {
    const text = cleanOptional(value);
    if (!text)
        return undefined;
    const timestamp = Date.parse(text);
    return Number.isFinite(timestamp) ? new Date(timestamp).toISOString() : undefined;
}
function upsertById(items, item) {
    const index = items.findIndex((candidate) => candidate.id === item.id);
    if (index < 0)
        return [...items, item];
    const next = [...items];
    next[index] = item;
    return next;
}
function sortPlans(left, right) {
    return right.priority - left.priority || Date.parse(right.updatedAt) - Date.parse(left.updatedAt);
}
