import { persistAllowlistedModuleStateWithPlanningSync } from "../task-engine/persistence/module-state-planning-events-runtime.js";
import { archiveSidecarFile, persistModuleStateRow, readSidecarJsonFile } from "../../core/state/module-state-sidecar-migration.js";
import { UnifiedStateDb } from "../../core/state/unified-state-db.js";
import { resolvePolicyTraceIdFromLineCursor } from "../../core/state/kit-policy-traces-sqlite.js";
import { planningSqliteDatabaseRelativePath } from "../task-engine/planning-config.js";
export const IMPROVEMENT_STATE_SCHEMA_VERSION = 4;
/** Max scout rotation rows retained (FIFO trim on save). */
export const SCOUT_ROTATION_HISTORY_MAX = 32;
export const IMPROVEMENT_STATE_SIDECAR_REL = ".workspace-kit/improvement/state.json";
const IMPROVEMENT_MODULE_STATE_ID = "improvement";
export function emptyImprovementState() {
    return {
        schemaVersion: IMPROVEMENT_STATE_SCHEMA_VERSION,
        lastIngestedPolicyTraceId: 0,
        mutationLineCursor: 0,
        transitionLogLengthCursor: 0,
        transcriptLineCursors: {},
        lastSyncRunAt: null,
        lastIngestRunAt: null,
        transcriptRetryQueue: [],
        scoutRotationHistory: []
    };
}
function normalizeScoutRotationHistory(raw) {
    if (!Array.isArray(raw))
        return [];
    const out = [];
    for (const e of raw) {
        if (!e || typeof e !== "object")
            continue;
        const o = e;
        const primaryLens = typeof o.primaryLens === "string" ? o.primaryLens : "";
        const targetZone = typeof o.targetZone === "string" ? o.targetZone : "";
        const questionStem = typeof o.questionStem === "string" ? o.questionStem : "";
        const runAt = typeof o.runAt === "string" ? o.runAt : "";
        if (!primaryLens || !targetZone || !questionStem || !runAt)
            continue;
        out.push({
            primaryLens,
            adversarialLens: typeof o.adversarialLens === "string" ? o.adversarialLens : undefined,
            targetZone,
            questionStem,
            runAt
        });
    }
    if (out.length <= SCOUT_ROTATION_HISTORY_MAX)
        return out;
    return out.slice(-SCOUT_ROTATION_HISTORY_MAX);
}
function migrateFromV1(raw) {
    const base = emptyImprovementState();
    return {
        ...base,
        lastIngestedPolicyTraceId: typeof raw.lastIngestedPolicyTraceId === "number" ? raw.lastIngestedPolicyTraceId : 0,
        mutationLineCursor: typeof raw.mutationLineCursor === "number" ? raw.mutationLineCursor : 0,
        transitionLogLengthCursor: typeof raw.transitionLogLengthCursor === "number" ? raw.transitionLogLengthCursor : 0,
        transcriptLineCursors: raw.transcriptLineCursors && typeof raw.transcriptLineCursors === "object" && raw.transcriptLineCursors !== null
            ? raw.transcriptLineCursors
            : {},
        lastSyncRunAt: typeof raw.lastSyncRunAt === "string" ? raw.lastSyncRunAt : null,
        lastIngestRunAt: typeof raw.lastIngestRunAt === "string" ? raw.lastIngestRunAt : null,
        scoutRotationHistory: normalizeScoutRotationHistory(raw.scoutRotationHistory)
    };
}
function normalizeLoadedDoc(raw) {
    const ver = raw.schemaVersion;
    if (ver === 1) {
        return migrateFromV1(raw);
    }
    if (ver === 2 || ver === 3) {
        const doc = raw;
        const legacyLineCursor = typeof doc.policyTraceLineCursor === "number" ? doc.policyTraceLineCursor : 0;
        const lastIngestedPolicyTraceId = typeof raw.lastIngestedPolicyTraceId === "number"
            ? raw.lastIngestedPolicyTraceId
            : 0;
        return {
            ...emptyImprovementState(),
            ...doc,
            schemaVersion: IMPROVEMENT_STATE_SCHEMA_VERSION,
            lastIngestedPolicyTraceId,
            _legacyPolicyTraceLineCursor: legacyLineCursor > 0 && lastIngestedPolicyTraceId === 0 ? legacyLineCursor : 0,
            transcriptLineCursors: doc.transcriptLineCursors ?? {},
            transcriptRetryQueue: Array.isArray(doc.transcriptRetryQueue)
                ? doc.transcriptRetryQueue.filter((e) => e !== null &&
                    typeof e === "object" &&
                    typeof e.relativePath === "string")
                : [],
            scoutRotationHistory: normalizeScoutRotationHistory(doc.scoutRotationHistory)
        };
    }
    if (ver !== IMPROVEMENT_STATE_SCHEMA_VERSION) {
        return emptyImprovementState();
    }
    const doc = raw;
    return {
        ...emptyImprovementState(),
        ...doc,
        lastIngestedPolicyTraceId: typeof doc.lastIngestedPolicyTraceId === "number" ? doc.lastIngestedPolicyTraceId : 0,
        transcriptLineCursors: doc.transcriptLineCursors ?? {},
        transcriptRetryQueue: Array.isArray(doc.transcriptRetryQueue)
            ? doc.transcriptRetryQueue.filter((e) => e !== null &&
                typeof e === "object" &&
                typeof e.relativePath === "string")
            : [],
        scoutRotationHistory: normalizeScoutRotationHistory(doc.scoutRotationHistory)
    };
}
/** Append one scout rotation row and trim to cap (mutates and returns same doc). */
export function appendScoutRotationEntry(doc, entry) {
    const next = [...doc.scoutRotationHistory, entry];
    doc.scoutRotationHistory =
        next.length > SCOUT_ROTATION_HISTORY_MAX ? next.slice(-SCOUT_ROTATION_HISTORY_MAX) : next;
    return doc;
}
export async function loadImprovementState(workspacePath, effectiveConfig) {
    const ctx = { workspacePath, effectiveConfig };
    const dbRel = planningSqliteDatabaseRelativePath(ctx);
    const unified = new UnifiedStateDb(workspacePath, dbRel);
    const row = unified.getModuleState(IMPROVEMENT_MODULE_STATE_ID);
    if (row?.state) {
        return await finalizeImprovementStateLoad(workspacePath, normalizeLoadedDoc(row.state), effectiveConfig);
    }
    const sidecar = await readSidecarJsonFile(workspacePath, IMPROVEMENT_STATE_SIDECAR_REL);
    if (sidecar.ok) {
        const doc = normalizeLoadedDoc(sidecar.value);
        const finalized = await finalizeImprovementStateLoad(workspacePath, doc, effectiveConfig);
        persistModuleStateRow({
            workspacePath,
            databaseRelativePath: dbRel,
            moduleId: IMPROVEMENT_MODULE_STATE_ID,
            stateSchemaVersion: finalized.schemaVersion,
            state: finalized
        });
        await archiveSidecarFile(workspacePath, IMPROVEMENT_STATE_SIDECAR_REL);
        return finalized;
    }
    if ("corrupt" in sidecar && sidecar.corrupt) {
        await archiveSidecarFile(workspacePath, IMPROVEMENT_STATE_SIDECAR_REL);
        return emptyImprovementState();
    }
    return emptyImprovementState();
}
async function finalizeImprovementStateLoad(workspacePath, doc, effectiveConfig) {
    const legacy = doc._legacyPolicyTraceLineCursor ?? 0;
    delete doc._legacyPolicyTraceLineCursor;
    if (legacy > 0 && doc.lastIngestedPolicyTraceId === 0) {
        doc.lastIngestedPolicyTraceId = resolvePolicyTraceIdFromLineCursor(workspacePath, legacy, effectiveConfig);
        await saveImprovementState(workspacePath, doc, effectiveConfig);
    }
    return doc;
}
export async function saveImprovementState(workspacePath, doc, effectiveConfig, options) {
    const out = {
        ...doc,
        schemaVersion: IMPROVEMENT_STATE_SCHEMA_VERSION
    };
    return persistAllowlistedModuleStateWithPlanningSync({
        workspacePath,
        effectiveConfig,
        moduleId: IMPROVEMENT_MODULE_STATE_ID,
        state: out,
        documentSchemaVersion: out.schemaVersion,
        commandName: options?.commandName ?? "save-improvement-state",
        clientMutationId: options?.clientMutationId,
        policyApproval: options?.policyApproval
    });
}
