// Copyright (c) 2026 Modelware. All rights reserved.

import { bindTemplateParameters } from './binder.js';
import type { TemplateDefinition, TemplateInvocation, TemplateValue } from './types.js';

export interface TemplateRenderResult {
    output: string;
    values: Record<string, TemplateValue>;
}

export function renderTemplate(
    template: TemplateDefinition,
    invocation: TemplateInvocation
): TemplateRenderResult {
    const bound = bindTemplateParameters(template, invocation.context, invocation.args);
    const output = interpolateTemplateBody(template.body, bound.values);
    return {
        output,
        values: bound.values,
    };
}

export function interpolateTemplateBody(
    source: string,
    values: Readonly<Record<string, TemplateValue>>
): string {
    return source.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?:\|([^|}]*)(?:\|([^}]*))?)?\}/g, (_match: string, key: string, delimiter: string | undefined, entryTemplate: string | undefined): string => {
        if (!(key in values)) {
            return _match;
        }
        const value = values[key];
        if (Array.isArray(value)) {
            const format = (entry: string) => entryTemplate ? entryTemplate.replace('%s', entry) : entry;
            return value.map((entry) => format(String(entry))).join(delimiter ?? ', ');
        }
        if (value === null || value === undefined) {
            return '';
        }
        if (typeof value === 'object') {
            return JSON.stringify(value);
        }
        return String(value);
    });
}
