/**
 * Dev Specly Generator
 *
 * Generates a dev.specly file from an inferred specification.
 * The dev.specly describes the development GUI:
 * - Per-model views (list, detail, form)
 * - Specialist views (board for lifecycle models, timeline for date models, dashboard)
 * - Sidebar navigation structure grouped by domain
 *
 * This is consumed by @specverse/runtime's DevShell component at runtime.
 */
/**
 * Simplify parameters: {pollId: {name, type:'UUID', required}} → {pollId: 'UUID'}
 */
function simplifyParameters(params) {
    if (!params || typeof params !== 'object')
        return undefined;
    const result = {};
    for (const [key, def] of Object.entries(params)) {
        if (typeof def === 'string') {
            result[key] = def;
        }
        else if (def && typeof def === 'object') {
            result[key] = def.type || 'String';
        }
    }
    return Object.keys(result).length > 0 ? result : undefined;
}
/**
 * Generate dev.specly YAML from an inferred component.
 *
 * The dev spec is a standalone .specly file that the DevShell loads
 * at runtime to render dev views for all models.
 */
export function generateDevSpecly(component, componentName) {
    const models = component.models || {};
    const modelNames = Object.keys(models);
    if (modelNames.length === 0) {
        return '# No models found — nothing to generate\n';
    }
    const name = componentName || component.name || 'DevViews';
    const views = {};
    const sidebarGroups = {};
    for (const modelName of modelNames) {
        const model = models[modelName];
        const attributes = model.attributes || {};
        const relationships = model.relationships || {};
        const lifecycles = model.lifecycles || {};
        // Group models by first relationship parent (or 'General')
        let group = 'General';
        if (relationships) {
            for (const rel of Object.values(relationships)) {
                if (rel.type === 'belongsTo' && modelNames.includes(rel.targetModel || rel.target)) {
                    group = rel.targetModel || rel.target;
                    break;
                }
            }
        }
        if (!sidebarGroups[group])
            sidebarGroups[group] = [];
        sidebarGroups[group].push(modelName);
        // Standard views for every model
        views[`${modelName}ListView`] = {
            type: 'list',
            model: modelName,
            description: `Browse all ${modelName} records`,
        };
        views[`${modelName}DetailView`] = {
            type: 'detail',
            model: modelName,
            description: `View ${modelName} details`,
        };
        views[`${modelName}FormView`] = {
            type: 'form',
            model: modelName,
            description: `Create or edit ${modelName}`,
        };
        // Specialist views based on model characteristics
        // Dashboard for models with numeric fields or many relationships
        const attrEntries = Object.entries(attributes);
        const hasNumericFields = attrEntries.some(([_, def]) => {
            const typeStr = typeof def === 'string' ? def : def?.type || '';
            return /int|number|float|decimal|count|amount|total|price|quantity/i.test(typeStr);
        });
        const hasMany = Object.values(relationships).filter((r) => r.type === 'hasMany');
        if (hasNumericFields || hasMany.length >= 2) {
            views[`${modelName}DashboardView`] = {
                type: 'dashboard',
                model: modelName,
                description: `${modelName} metrics and overview`,
            };
        }
        // Board view for models with lifecycle
        // TODO: Board view (kanban by lifecycle state) — not yet implemented in runtime renderer
        // TODO: Timeline view (chronological by date) — not yet implemented in runtime renderer
    }
    // Normalize services: array → object
    let services = component.services || {};
    if (Array.isArray(services)) {
        const obj = {};
        for (const svc of services) {
            if (svc.name)
                obj[svc.name] = svc;
        }
        services = obj;
    }
    for (const [serviceName, serviceDef] of Object.entries(services)) {
        let operations = serviceDef.operations || {};
        if (Array.isArray(operations)) {
            const obj = {};
            for (const op of operations) {
                if (op.name)
                    obj[op.name] = op;
            }
            operations = obj;
        }
        for (const [opName, opDef] of Object.entries(operations)) {
            views[`${serviceName}_${opName}`] = {
                type: 'operation',
                service: serviceName,
                operation: opName,
                description: opDef.description || `Execute ${opName}`,
                parameters: simplifyParameters(opDef.parameters),
                returns: typeof opDef.returns === 'object' ? opDef.returns?.type || 'any' : opDef.returns,
                source: 'service',
            };
        }
    }
    // Operation views from custom controller operations (non-CRUD)
    let controllers = component.controllers || {};
    if (Array.isArray(controllers)) {
        const obj = {};
        for (const ctrl of controllers) {
            if (ctrl.name)
                obj[ctrl.name] = ctrl;
        }
        controllers = obj;
    }
    const crudOps = new Set(['create', 'update', 'delete', 'list', 'retrieve', 'retrieve_many']);
    for (const [ctrlName, ctrlDef] of Object.entries(controllers)) {
        const operations = ctrlDef.operations || {};
        for (const [opName, opDef] of Object.entries(operations)) {
            if (crudOps.has(opName))
                continue; // skip standard CRUD
            views[`${ctrlName}_${opName}`] = {
                type: 'operation',
                service: ctrlName,
                operation: opName,
                description: opDef.description || `Execute ${opName}`,
                parameters: simplifyParameters(opDef.parameters),
                returns: opDef.returns,
                source: 'controller',
            };
        }
    }
    // Build YAML
    let yaml = `# Dev GUI specification — auto-generated by inference\n`;
    yaml += `# Consumed by @specverse/runtime DevShell at runtime\n`;
    yaml += `# To promote a dev view to a spec view, copy it to your main.specly\n\n`;
    yaml += `metadata:\n`;
    yaml += `  name: ${name}-dev\n`;
    yaml += `  type: development\n`;
    yaml += `  generated: true\n\n`;
    // Sidebar navigation structure
    yaml += `navigation:\n`;
    yaml += `  sidebar:\n`;
    for (const [group, groupModels] of Object.entries(sidebarGroups)) {
        yaml += `    ${group}:\n`;
        for (const modelName of groupModels) {
            yaml += `      - ${modelName}\n`;
        }
    }
    // Add services group if any service operations exist
    const serviceNames = Object.keys(services);
    if (serviceNames.length > 0) {
        yaml += `    Services:\n`;
        for (const svcName of serviceNames) {
            yaml += `      - ${svcName}\n`;
        }
    }
    yaml += `\n`;
    // Views
    yaml += `views:\n`;
    for (const [viewName, viewDef] of Object.entries(views)) {
        yaml += `  ${viewName}:\n`;
        for (const [key, value] of Object.entries(viewDef)) {
            if (value === undefined || value === null)
                continue;
            if (typeof value === 'object') {
                yaml += `    ${key}:\n`;
                for (const [k, v] of Object.entries(value)) {
                    yaml += `      ${k}: ${v}\n`;
                }
            }
            else {
                yaml += `    ${key}: ${value}\n`;
            }
        }
        yaml += `\n`;
    }
    return yaml.trimEnd() + '\n';
}
//# sourceMappingURL=dev-specly-generator.js.map