// engine/spec-templates/custom-loader.ts — Loads custom user templates from data/global/.
// AC-06: Custom templates from data/global/spec-templates/custom/.
// AC-11: Validates with Zod, reports malformed templates as warnings.
import { readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { z } from 'zod';
/** Zod schema for validating custom template JSON files. */
const templateVariableSchema = z.object({
    key: z.string().min(1),
    label: z.string().min(1),
    description: z.string().min(1),
    example: z.string().min(1),
    required: z.boolean(),
    defaultValue: z.string().optional(),
});
const templateCriterionSchema = z.object({
    id: z.string().min(1),
    title: z.string().min(1),
    required: z.boolean(),
});
const complexityScoreSchema = z.enum(['S', 'M', 'L', 'XL']);
const estimationBaseSchema = z.object({
    hoursMin: z.number().nonnegative(),
    hoursMax: z.number().nonnegative(),
    notes: z.string(),
});
const templateCategorySchema = z.enum([
    'auth',
    'crud',
    'api',
    'ui',
    'infra',
    'testing',
    'integration',
    'data',
    'security',
    'performance',
    'industry',
]);
const industrySubcategorySchema = z.enum(['fintech', 'healthtech', 'ecommerce', 'saas']);
const customTemplateSchema = z.object({
    id: z.string().min(1),
    name: z.string().min(1),
    category: templateCategorySchema,
    subcategory: industrySubcategorySchema.optional(),
    description: z.string().min(1),
    tags: z.array(z.string()),
    complexityScore: complexityScoreSchema,
    estimationBase: estimationBaseSchema,
    criteria: z.array(templateCriterionSchema),
    variables: z.array(templateVariableSchema),
    huTemplate: z.string().min(1),
    fichaTecnicaTemplate: z.string().min(1),
    progressTemplate: z.string().min(1),
});
/** Default directory for custom user templates. */
const CUSTOM_TEMPLATES_DIR = 'data/global/spec-templates/custom';
/**
 * Loads custom templates from a directory. Each .json file is validated.
 * Malformed files generate warnings but do not block loading of other templates.
 */
export async function loadCustomTemplates(baseDir) {
    const dir = baseDir ?? CUSTOM_TEMPLATES_DIR;
    const templates = [];
    const warnings = [];
    let files;
    try {
        files = await readdir(dir);
    }
    catch {
        // Directory does not exist — not an error, just no custom templates
        return { templates, warnings };
    }
    const jsonFiles = files.filter((f) => f.endsWith('.json'));
    for (const file of jsonFiles) {
        const filePath = join(dir, file);
        try {
            const content = await readFile(filePath, 'utf-8');
            const parsed = JSON.parse(content);
            const validated = customTemplateSchema.parse(parsed);
            templates.push(validated);
        }
        catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            warnings.push({ file: filePath, error: message });
        }
    }
    return { templates, warnings };
}
/**
 * Merges custom templates with built-in templates.
 * Custom templates override built-in templates with the same ID.
 */
export function mergeTemplates(builtIn, custom) {
    const customIds = new Set(custom.map((t) => t.id));
    const filtered = builtIn.filter((t) => !customIds.has(t.id));
    return [...filtered, ...custom];
}
//# sourceMappingURL=custom-loader.js.map