/**
 * Mermaid diagram builders for module structure, dependencies,
 * and root-level dependency overviews.
 */

import { KnowledgeGraph } from "../../repopilot/graph/knowledge-graph";
import type { ModuleNode } from "../../repopilot/module-tree";
import { EdgeType, NodeType } from "../../repopilot/types";
import type { ClassEntry } from "../types";
import {
  CAP_DIAGRAM_CLASSES,
  CAP_DIAGRAM_DEPS,
} from "../constants";
import {
  getString,
  mermaidId,
  mermaidText,
  resolveTopLevelName,
} from "../utils";

export function buildModuleStructureDiagram(
  module: ModuleNode,
  classes: ClassEntry[],
): string | undefined {
  if (classes.length === 0) return undefined;

  const selected = classes.slice(0, CAP_DIAGRAM_CLASSES);
  const lines = ["flowchart LR"];
  const moduleNodeId = mermaidId(`module_${module.path || module.name}`);
  lines.push(
    `  ${moduleNodeId}["${mermaidText(module.path || module.name)}"]`,
  );

  for (const cls of selected) {
    const classId = mermaidId(`class_${cls.name}`);
    lines.push(`  ${classId}["${mermaidText(cls.name)}"]`);
    lines.push(`  ${moduleNodeId} --> ${classId}`);

    if (cls.extendsName) {
      const targetId = mermaidId(`super_${cls.extendsName}`);
      lines.push(
        `  ${targetId}["${mermaidText(cls.extendsName)}"]`,
      );
      lines.push(`  ${classId} -. extends .-> ${targetId}`);
    }

    for (const iface of cls.implementsNames.slice(0, 2)) {
      const targetId = mermaidId(`iface_${cls.name}_${iface}`);
      lines.push(`  ${targetId}["${mermaidText(iface)}"]`);
      lines.push(
        `  ${classId} -. implements .-> ${targetId}`,
      );
    }
  }

  return lines.join("\n");
}

export function buildDependencyDiagram(
  moduleName: string,
  dependencies: string[],
): string | undefined {
  if (dependencies.length === 0) return undefined;

  const lines = ["flowchart LR"];
  const moduleId = mermaidId(`dep_${moduleName}`);
  lines.push(`  ${moduleId}["${mermaidText(moduleName)}"]`);

  for (const dep of dependencies.slice(0, CAP_DIAGRAM_DEPS)) {
    const depId = mermaidId(`dep_${moduleName}_${dep}`);
    lines.push(`  ${depId}["${mermaidText(dep)}"]`);
    lines.push(`  ${moduleId} --> ${depId}`);
  }

  return lines.join("\n");
}

export function buildRootDependencyDiagram(
  tree: ModuleNode,
  graph: KnowledgeGraph,
): string | undefined {
  const topLevelNameList = tree.children.map((child) => child.name);
  const topLevelNames = new Set(topLevelNameList);
  if (topLevelNames.size === 0) return undefined;

  const mappedEdges = new Set<string>();
  for (const pkgId of graph.getNodesByType(NodeType.PACKAGE)) {
    const attrs = graph.getNodeAttrs(pkgId);
    const sourceName = getString(attrs, "name");
    if (!sourceName) continue;

    const sourceTopLevel = resolveTopLevelName(sourceName, topLevelNameList);
    if (!sourceTopLevel) continue;

    for (const depId of graph.getNeighbors(
      pkgId,
      EdgeType.DEPENDS_ON,
      "out",
    )) {
      if (!graph.hasNode(depId)) continue;
      const depAttrs = graph.getNodeAttrs(depId);
      const targetName = getString(depAttrs, "name");
      if (!targetName) continue;
      const targetTopLevel = resolveTopLevelName(
        targetName,
        topLevelNameList,
      );
      if (!targetTopLevel || targetTopLevel === sourceTopLevel) continue;
      mappedEdges.add(`${sourceTopLevel}|${targetTopLevel}`);
    }
  }

  if (mappedEdges.size === 0) return undefined;

  const lines = ["flowchart LR"];
  for (const name of topLevelNames) {
    lines.push(
      `  ${mermaidId(`root_${name}`)}["${mermaidText(name)}"]`,
    );
  }
  for (const edge of mappedEdges) {
    const [src, tgt] = edge.split("|");
    lines.push(
      `  ${mermaidId(`root_${src}`)} --> ${mermaidId(`root_${tgt}`)}`,
    );
  }
  return lines.join("\n");
}
