import { errorCodeToClassName, type ParsedCommandDoc } from "./parse-command-doc";

export function moduleNameToPrefix(moduleName: string): string {
  return moduleName.toUpperCase().replace(/-/g, "_");
}

interface CollectedError {
  description: string;
  sources: { commandName: string; description: string }[];
}

export function generateErrors(moduleName: string, docs: ParsedCommandDoc[]): string {
  const collected = new Map<string, CollectedError>();

  for (const doc of docs) {
    for (const error of doc.errors) {
      const existing = collected.get(error.code);
      if (!existing) {
        collected.set(error.code, {
          description: error.description,
          sources: [{ commandName: doc.commandName, description: error.description }],
        });
        continue;
      }
      existing.sources.push({ commandName: doc.commandName, description: error.description });
    }
  }

  const conflicts = [...collected.entries()].filter(
    ([, entry]) => new Set(entry.sources.map((s) => s.description)).size > 1,
  );

  if (conflicts.length > 0) {
    const details = conflicts
      .map(([code, entry]) => {
        const sourceLines = entry.sources
          .map((s) => `    - ${s.commandName}: ${JSON.stringify(s.description)}`)
          .join("\n");
        return `  - ${code}\n${sourceLines}`;
      })
      .join("\n");
    throw new Error(
      `Error code conflicts in module "${moduleName}": the same code is declared with different descriptions. ` +
        `Unify the descriptions or split into distinct codes.\n${details}`,
    );
  }

  if (collected.size === 0) return "";

  const prefix = moduleNameToPrefix(moduleName);
  const lines: string[] = [];
  for (const [code, entry] of collected) {
    const className = errorCodeToClassName(code);
    const prefixedCode = `${prefix}_${code}`;
    lines.push(`export const ${className} = createDomainError(`);
    lines.push(`  "${className}", "${prefixedCode}",`);
    const escapedDesc = entry.description.replace(/`/g, "'");
    lines.push(`  (identifier: string) => \`${escapedDesc}: \${identifier}\`,`);
    lines.push(`);`);
    lines.push(``);
  }

  return `// @generated — do not edit
import { createDomainError } from "@tailor-platform/erp-kit/core";

${lines.join("\n")}`;
}
