import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { z } from 'zod';
import { projectDataDir } from '../../storage/base-store.js';
const DiscoverySchema = z.object({
    version: z.literal(1),
    rules: z.array(z.string().min(1)).max(200),
    examples: z.array(z.object({ rule: z.string().min(1), example: z.string().min(1) })).max(500),
    openQuestions: z
        .array(z.object({
        question: z.string().min(1),
        status: z.enum(['open', 'resolved', 'out_of_scope']),
        resolution: z.string().optional(),
    }))
        .max(200),
    outOfScope: z.array(z.string()).max(200),
    glossary: z.array(z.object({ term: z.string().min(1), meaning: z.string().min(1) })).max(200),
});
const TaskPlanSchema = z.object({
    version: z.literal(1),
    tasks: z
        .array(z.object({
        id: z.string().min(1).max(120),
        title: z.string().min(1).max(500),
        acceptanceCriteria: z.array(z.string().min(1)).max(200),
        status: z.enum(['pending', 'doing', 'done']),
    }))
        .max(500),
});
const TraceabilityMatrixSchema = z.object({
    version: z.literal(1),
    rows: z
        .array(z.object({
        acceptanceCriterion: z.string().min(1),
        scenario: z.string().optional(),
        testEvidence: z.array(z.string().min(1)).optional(),
        contractEvidence: z.array(z.string().min(1)).optional(),
        manualEvidence: z.string().optional(),
        changedFiles: z.array(z.string().min(1)).max(200),
        validationEvidence: z.string().optional(),
        reviewerEvidence: z.string().optional(),
    }))
        .max(1000),
});
const ContractValidationSchema = z.object({
    version: z.literal(1),
    kind: z.enum(['api', 'graphql', 'event', 'ui', 'mcp']),
    passed: z.boolean(),
    reportPath: z.string().optional(),
    summary: z.string().optional(),
});
function handoffEvidencePath(projectId, specId, filename) {
    return join(projectDataDir(projectId), 'handoffs', specId, filename);
}
async function readUnknown(paths) {
    for (const path of paths) {
        try {
            const raw = await readFile(path, 'utf-8');
            return { path, value: JSON.parse(raw) };
        }
        catch (err) {
            const code = err instanceof Error && 'code' in err ? err.code : undefined;
            if (code === 'ENOENT') {
                continue;
            }
            throw new Error(`${path}: ${err instanceof Error ? err.message : String(err)}`, {
                cause: err,
            });
        }
    }
    return null;
}
async function readOptional(args) {
    try {
        const found = await readUnknown(args.paths.filter((path) => Boolean(path)));
        if (!found) {
            return undefined;
        }
        const parsed = args.schema.safeParse(found.value);
        if (!parsed.success) {
            args.invalidArtifacts.push(`${args.label} is invalid at ${found.path}: ${parsed.error.issues.map((issue) => issue.message).join('; ')}`);
            return undefined;
        }
        return parsed.data;
    }
    catch (err) {
        args.invalidArtifacts.push(`${args.label} is unreadable: ${err instanceof Error ? err.message : String(err)}`);
        return undefined;
    }
}
export async function readEvidenceArtifacts(args) {
    const invalidArtifacts = [];
    const discovery = await readOptional({
        label: 'Discovery evidence',
        invalidArtifacts,
        schema: DiscoverySchema,
        paths: [handoffEvidencePath(args.projectId, args.specId, 'discovery.json')],
    });
    const taskPlan = await readOptional({
        label: 'Task plan evidence',
        invalidArtifacts,
        schema: TaskPlanSchema,
        paths: [handoffEvidencePath(args.projectId, args.specId, 'task-plan.json')],
    });
    const traceabilityMatrix = await readOptional({
        label: 'Traceability matrix evidence',
        invalidArtifacts,
        schema: TraceabilityMatrixSchema,
        paths: [handoffEvidencePath(args.projectId, args.specId, 'traceability-matrix.json')],
    });
    const contractValidations = [];
    for (const filename of [
        'contract-validation-api.json',
        'contract-validation-graphql.json',
        'contract-validation-event.json',
        'contract-validation-ui.json',
        'contract-validation-mcp.json',
    ]) {
        const evidence = await readOptional({
            label: filename,
            invalidArtifacts,
            schema: ContractValidationSchema,
            paths: [handoffEvidencePath(args.projectId, args.specId, filename)],
        });
        if (evidence) {
            contractValidations.push(evidence);
        }
    }
    return {
        discovery,
        taskPlan,
        traceabilityMatrix,
        contractValidations,
        invalidArtifacts,
    };
}
//# sourceMappingURL=artifact-reader.js.map