import { reviewPlanArtifact } from "../../core/planning/review-plan-artifact.js";
import { readLatestPlanArtifact, readPlanArtifactVersion, writeNextPlanArtifactVersion } from "../../core/planning/plan-artifact-storage.js";
import { validatePlanArtifactDraftInput } from "../../core/planning/validate-plan-artifact.js";
import { openPlanningStores } from "../../core/planning/index.js";
import { planningGenPolicyGate } from "../task-engine/planning-generation-gate.js";
import { attachPolicyMeta } from "../task-engine/attach-planning-response-meta.js";
import { TaskEngineError } from "../task-engine/transitions.js";
import { planningConcurrencySaveOpts } from "../task-engine/mutation-utils.js";
const REVIEW_PROFILES = new Set([
    "minimal",
    "refactor",
    "full-feature",
    "sprint-phase"
]);
function parseProfile(raw) {
    if (typeof raw === "string" && REVIEW_PROFILES.has(raw)) {
        return raw;
    }
    return undefined;
}
function parseWaivers(raw) {
    if (!Array.isArray(raw)) {
        return undefined;
    }
    const waivers = [];
    for (const item of raw) {
        if (!item || typeof item !== "object" || Array.isArray(item)) {
            continue;
        }
        const row = item;
        if (typeof row.code === "string" && typeof row.rationale === "string") {
            const code = row.code.trim();
            const rationale = row.rationale.trim();
            if (code.length > 0 && rationale.length > 0) {
                waivers.push({ code, rationale });
            }
        }
    }
    return waivers.length > 0 ? waivers : undefined;
}
function parseVersion(raw) {
    if (typeof raw === "number" && Number.isInteger(raw) && raw >= 1) {
        return raw;
    }
    return undefined;
}
function formatReviewSummary(result) {
    const blockers = result.blockers.length;
    const warnings = result.warnings.length;
    if (blockers === 0 && warnings === 0) {
        return "0 blockers, 0 warnings";
    }
    if (blockers === 0) {
        return `0 blockers, ${warnings} warning(s)`;
    }
    return `${blockers} blocker(s), ${warnings} warning(s)`;
}
function reviewDataPayload(result, extras = {}) {
    return {
        schemaVersion: 1,
        responseSchemaVersion: 1,
        passed: result.passed,
        profile: result.profile,
        blockers: result.blockers,
        warnings: result.warnings,
        coverageMap: result.coverageMap,
        sizingFindings: result.sizingFindings,
        openQuestionCount: result.openQuestionCount,
        reviewSummary: formatReviewSummary(result),
        ...extras
    };
}
function reviewSuccessResult(result, extras = {}) {
    return {
        ok: true,
        code: result.passed ? "plan-artifact-review-complete" : "plan-artifact-review-blocked",
        message: result.passed ? "PlanArtifact review passed" : "PlanArtifact review has blockers",
        data: reviewDataPayload(result, extras)
    };
}
async function resolveArtifact(args, ctx) {
    const artifactRaw = args.artifact;
    const hasArtifact = artifactRaw && typeof artifactRaw === "object" && !Array.isArray(artifactRaw);
    const planIdRaw = typeof args.planId === "string" ? args.planId.trim() : "";
    if (hasArtifact) {
        const validation = validatePlanArtifactDraftInput(artifactRaw, {
            workspaceRoot: ctx.workspacePath,
            planId: planIdRaw || undefined,
            actor: typeof args.actor === "string" ? args.actor : undefined
        });
        if (!validation.ok) {
            return {
                ok: false,
                result: {
                    ok: false,
                    code: "plan-artifact-schema-invalid",
                    message: "PlanArtifact validation failed",
                    data: {
                        schemaVersion: 1,
                        responseSchemaVersion: 1,
                        errors: validation.errors
                    }
                }
            };
        }
        return { ok: true, artifact: validation.artifact, planId: validation.artifact.planId };
    }
    if (!planIdRaw) {
        return {
            ok: false,
            result: {
                ok: false,
                code: "invalid-run-args",
                message: "review-plan-artifact requires planId or artifact"
            }
        };
    }
    const version = parseVersion(args.version);
    const loaded = version !== undefined
        ? readPlanArtifactVersion(ctx.workspacePath, planIdRaw, version)
        : readLatestPlanArtifact(ctx.workspacePath, planIdRaw);
    if (!loaded) {
        return {
            ok: false,
            result: {
                ok: false,
                code: "plan-artifact-not-found",
                message: version !== undefined
                    ? `PlanArtifact ${planIdRaw} version ${version} not found`
                    : `PlanArtifact ${planIdRaw} not found`,
                data: {
                    schemaVersion: 1,
                    responseSchemaVersion: 1,
                    planId: planIdRaw,
                    version
                }
            }
        };
    }
    return { ok: true, artifact: loaded, planId: planIdRaw };
}
export async function runReviewPlanArtifact(args, ctx, instructionPath) {
    const recordReview = args.recordReview === true;
    const resolved = await resolveArtifact(args, ctx);
    if (!resolved.ok) {
        return resolved.result;
    }
    const profile = parseProfile(args.profile);
    const waivers = parseWaivers(args.waivers);
    const review = reviewPlanArtifact(resolved.artifact, { profile, waivers });
    if (!recordReview) {
        return reviewSuccessResult(review, {
            planId: resolved.planId,
            version: resolved.artifact.version,
            planRef: resolved.artifact.planRef,
            recordReview: false
        });
    }
    const stores = await openPlanningStores(ctx);
    const pg = planningGenPolicyGate(ctx, args, instructionPath, stores.sqliteDual.getPlanningGeneration());
    if (pg.block) {
        return pg.block;
    }
    const now = new Date().toISOString();
    const reviewedBody = {
        ...resolved.artifact,
        status: "reviewed",
        provenance: {
            ...resolved.artifact.provenance,
            updatedAt: now
        }
    };
    let written;
    try {
        stores.sqliteDual.withTransaction(() => {
            const sqliteDb = stores.sqliteDual.getDatabase();
            written = writeNextPlanArtifactVersion(ctx.workspacePath, reviewedBody, {
                effectiveConfig: ctx.effectiveConfig,
                sqliteDb
            });
        }, planningConcurrencySaveOpts(args));
    }
    catch (err) {
        if (err instanceof TaskEngineError) {
            const data = err.code === "planning-generation-mismatch" && err.details
                ? err.details
                : undefined;
            return { ok: false, code: err.code, message: err.message, data };
        }
        throw err;
    }
    const storagePath = written.paths.artifactFileRelative(written.artifact.version);
    const result = reviewSuccessResult(review, {
        planId: written.artifact.planId,
        version: written.artifact.version,
        planRef: written.artifact.planRef,
        status: written.artifact.status,
        storagePath,
        recordReview: true
    });
    attachPolicyMeta(result.data, ctx, stores.sqliteDual.getPlanningGeneration(), pg.warnings);
    return result;
}
