import { loadDorItemDefs } from './items-loader.js';
// --- Internal builders ---
function computeDoR(specId, items) {
    const requiredItems = items.filter((i) => i.required);
    const passedCount = items.filter((i) => i.status === 'passed').length;
    const isReady = requiredItems.every((i) => i.status === 'passed');
    return {
        specId,
        items,
        passedCount,
        requiredCount: requiredItems.length,
        isReady,
        generatedAt: new Date().toISOString(),
    };
}
function bothNonEmpty(spec) {
    return spec.type.length > 0 && spec.scope.length > 0;
}
function checkFieldNonEmpty(spec, field) {
    const val = spec[field];
    return typeof val === 'string' && val.length > 0 ? 'passed' : 'failed';
}
/** Evaluates the auto-check condition defined in config against the spec. */
function evaluateAutoCheck(def, spec) {
    const { autoCheckField, autoCheckCondition } = def;
    if (!autoCheckField || !autoCheckCondition) {
        return 'failed';
    }
    switch (autoCheckCondition) {
        case 'length>3':
            return spec.title.length > 3 ? 'passed' : 'failed';
        case 'bothNonEmpty':
            return bothNonEmpty(spec) ? 'passed' : 'failed';
        case 'between1and5':
            return spec.difficulty >= 1 && spec.difficulty <= 5 ? 'passed' : 'failed';
        case 'greaterThan0':
            return spec.estimation.devHours > 0 ? 'passed' : 'failed';
        case 'nonEmpty':
            return checkFieldNonEmpty(spec, autoCheckField);
        case 'emptyArray':
            return spec.blockedBy.length === 0 ? 'passed' : 'failed';
        case 'approvedOrImplementing':
            return spec.status === 'approved' || spec.status === 'implementing' ? 'passed' : 'failed';
        default:
            return 'failed';
    }
}
/** Converts a DorDodItemDef into a live DoRItem by evaluating its auto-check condition. */
function defToDoRItem(def, spec) {
    const status = def.autoCheck ? evaluateAutoCheck(def, spec) : 'pending';
    return {
        id: def.id,
        description: def.description,
        category: def.category,
        required: def.required,
        autoCheck: def.autoCheck,
        status,
    };
}
function buildScopeAwareDoRItems(defs, type, scope, spec) {
    const items = [];
    for (const def of defs) {
        if (def.scopeFilter) {
            if (!def.scopeFilter.includes(scope)) {
                continue;
            }
            const item = defToDoRItem(def, spec);
            // dor-arch-1: required only for architectural scope
            const required = scope === 'architectural';
            items.push({ ...item, required });
            continue;
        }
        if (def.typeFilter) {
            if (!def.typeFilter.includes(type)) {
                continue;
            }
            items.push(defToDoRItem(def, spec));
        }
    }
    return items;
}
function buildDoRItems(spec, projectHash) {
    const defs = loadDorItemDefs(projectHash);
    // Separate core/tech defs from scope/type-conditional defs
    const coreDefs = defs.filter((d) => !d.scopeFilter && !d.typeFilter);
    const conditionalDefs = defs.filter((d) => d.scopeFilter ?? d.typeFilter);
    const coreItems = coreDefs.map((def) => defToDoRItem(def, spec));
    const conditionalItems = buildScopeAwareDoRItems(conditionalDefs, spec.type, spec.scope, spec);
    return [...coreItems, ...conditionalItems];
}
function buildDoRHumanMessage(title, blockingItems) {
    if (blockingItems.length === 0) {
        return `Spec "${title}" is ready to implement. All required DoR items passed.`;
    }
    const count = blockingItems.length;
    const listed = blockingItems.slice(0, 3).join('; ');
    const extra = count > 3 ? ` (and ${count - 3} more)` : '';
    return `Spec "${title}" is NOT ready. Missing ${count} required item(s): ${listed}${extra}`;
}
// --- Public API ---
/**
 * Generate a Definition of Ready checklist for a spec.
 * Items are type/scope-aware and include auto-checkable conditions.
 * Optionally pass a projectHash to load project-level overrides.
 */
export function generateDoR(spec, projectHash) {
    const items = buildDoRItems(spec, projectHash);
    return computeDoR(spec.id, items);
}
/**
 * Validate a spec's DoR and return a structured result.
 * Blocking = required items that failed; warnings = optional items that failed.
 */
export function validateDoR(spec, projectHash) {
    const dor = generateDoR(spec, projectHash);
    const blockingItems = dor.items
        .filter((i) => i.required && i.status === 'failed')
        .map((i) => i.description);
    const warningItems = dor.items
        .filter((i) => !i.required && i.status === 'failed')
        .map((i) => i.description);
    const isValid = blockingItems.length === 0;
    const humanMessage = buildDoRHumanMessage(spec.title, blockingItems);
    const expertSummary = `DoR: ${dor.passedCount}/${dor.items.length} passed | Blocking: ${blockingItems.length} | Warnings: ${warningItems.length}`;
    return { isValid, blockingItems, warningItems, humanMessage, expertSummary };
}
/**
 * Add a custom item to an existing DoR checklist.
 */
export function addCustomDoRItem(dor, item) {
    const items = [...dor.items, item];
    return computeDoR(dor.specId, items);
}
/**
 * Mark DoR items as HIGH PRIORITY when they match known failure patterns.
 */
export function enrichDoRWithLearning(dor, failurePatterns) {
    if (failurePatterns.length === 0) {
        return dor;
    }
    const items = dor.items.map((item) => {
        const isFrequentFailure = failurePatterns.some((p) => item.description.toLowerCase().includes(p.toLowerCase()));
        return isFrequentFailure && !item.description.startsWith('[HIGH PRIORITY]')
            ? { ...item, description: `[HIGH PRIORITY] ${item.description}` }
            : item;
    });
    return computeDoR(dor.specId, items);
}
//# sourceMappingURL=dor.js.map