import {
    emitClass,
    emitComponent,
    emitDirective,
    emitEnumeration,
    emitFunction,
    emitGuard,
    emitInjectable,
    emitInterceptor,
    emitInterface,
    emitModule,
    emitPipe,
    emitTypeAlias,
    emitVariable,
} from "./emit";
import { collapseDescription, escapeMarkdown, joinSections } from "./format";

const sectionHeader = (title: string): string => `## ${title}`;

const renderSection = <T>(
    title: string,
    items: ReadonlyArray<T> | undefined,
    emit: (item: T) => string,
): string => {
    if (!items || items.length === 0) {
        return "";
    }
    const blocks = items.map(emit).filter((s) => s.length > 0);
    if (blocks.length === 0) {
        return "";
    }
    return `${sectionHeader(title)}\n\n${blocks.join("\n\n")}`;
};

const renderListSection = <T>(
    title: string,
    items: ReadonlyArray<T> | undefined,
    emit: (item: T) => string,
): string => {
    if (!items || items.length === 0) {
        return "";
    }
    const lines = items.map(emit).filter((s) => s.length > 0);
    if (lines.length === 0) {
        return "";
    }
    return `${sectionHeader(title)}\n\n${lines.join("\n")}`;
};

const buildHeader = (
    projectName: string,
    projectDescription: string | undefined,
    compodocVersion: string,
    generatedAt: string,
): string => {
    const lines = [`# ${escapeMarkdown(projectName)}`];
    if (projectDescription) {
        const collapsed = collapseDescription(projectDescription);
        if (collapsed) {
            lines.push("", `> ${escapeMarkdown(collapsed)}`);
        }
    }
    const versionPart = compodocVersion ? ` ${compodocVersion}` : "";
    const generatedPart = generatedAt ? ` at ${generatedAt}` : "";
    lines.push(
        "",
        `> Generated by compodoc${versionPart}${generatedPart}, llm-md export.`,
    );
    return lines.join("\n");
};

export const renderLlmMd = (
    data: any,
    options: { projectName: string; projectDescription?: string },
    compodocVersion: string,
): string => {
    const generatedAt = new Date().toISOString();

    const sections: string[] = [
        buildHeader(
            options.projectName,
            options.projectDescription,
            compodocVersion,
            generatedAt,
        ),
        renderSection("Modules", data.modules, emitModule),
        renderSection("Components", data.components, emitComponent),
        renderSection("Directives", data.directives, emitDirective),
        renderSection("Pipes", data.pipes, emitPipe),
        renderSection(
            "Services / Injectables",
            data.injectables,
            emitInjectable,
        ),
        renderSection("Guards", data.guards, emitGuard),
        renderSection("Interceptors", data.interceptors, emitInterceptor),
        renderSection("Classes", data.classes, emitClass),
        renderSection("Interfaces", data.interfaces, emitInterface),
    ];

    const misc = data.miscellaneous;
    if (misc) {
        sections.push(
            renderListSection("Public functions", misc.functions, emitFunction),
            renderListSection(
                "Public type aliases",
                misc.typealiases,
                emitTypeAlias,
            ),
            renderSection(
                "Public enumerations",
                misc.enumerations,
                emitEnumeration,
            ),
            renderListSection("Public variables", misc.variables, emitVariable),
        );
    }

    return `${joinSections(sections)}\n`;
};
