/**
 * LLM prompt builders for wiki page generation.
 *
 * Each function assembles a structured prompt that instructs the LLM agent
 * to read source code and produce a specific documentation page.
 */

import type { ModuleNode } from "../../repopilot/module-tree";
import type { KnowledgeGraph } from "../../repopilot/graph/knowledge-graph";
import type { RepoIndex } from "../../repopilot/graph/index";
import { EdgeType, NodeType } from "../../repopilot/types";
import { MERMAID_AGENT_RULES } from "../constants";
import type {
  CrossCuttingPattern,
  KeyClassCandidate,
  ModuleEvidence,
  RootEvidence,
} from "../types";
import {
  buildCodeLink,
  collectModuleFiles,
  getNumber,
  getString,
  humanTitle,
  uniqueStrings,
} from "../utils";
import {
  buildTreeContext,
} from "../analysis/graph-extractor";

function buildOutputContract(docPath: string): string {
  return `## Tool contract

- Use the exact tool names \`read_file\` and \`write_file\`.
- The final output path is \`${docPath}\`.
- Finish by calling \`write_file\` with JSON arguments of the form \`{"path":"${docPath}","content":"<full markdown document>"}\`.
- A plain-text response is not a valid completion. The task is only complete after \`write_file\` succeeds.`;
}

/* ------------------------------------------------------------------ */
/*  Leaf module prompt                                                  */
/* ------------------------------------------------------------------ */

export function buildLeafPrompt(
  module: ModuleNode,
  tree: ModuleNode,
  graph: KnowledgeGraph,
  sourcePath: string,
  wikiDir: string,
  evidence: ModuleEvidence,
): string {
  const title = humanTitle(module.path || module.name);
  const fileList =
    collectModuleFiles(module)
      .map((fp) => `- ${fp}`)
      .join("\n") || "- No files indexed";

  return `You are a technical documentation writer for a software engineering team.

Write clear, well-organized documentation for the module described below. Your audience is engineers who need to understand what this module does, why it exists, and how to work with it.

## Module: ${title}
- Package path: \`${module.path}\`
- Output path for \`write_file\`: \`${wikiDir}/${module.docPath}\`

## Source files to read
${fileList}

${buildTreeContext(module, tree)}

## Evidence from code analysis

### Module statistics
${evidence.facts}

### Child module links
${evidence.childLinks}

### Source files
${evidence.fileInventory}

### Classes and interfaces
${evidence.classReferences}

### Methods
${evidence.methodReferences}

### Package dependencies
${evidence.dependencySummary}

### Cross-module relationships
${evidence.crossModuleRelationships}

### Import patterns (frameworks and libraries used)
${evidence.importPatterns}

## Writing guidelines

1. Write in Markdown. Use the title: # ${title}
2. **Start with a clear overview** — 2-3 sentences explaining what this module does and why it exists in the system. A new team member should understand the module's purpose after reading the first paragraph.
3. **Organize content naturally.** Use these sections as a guide, but adapt based on what's interesting about this module:
   - **Overview** — what this module is responsible for
   - **Key Classes and Interfaces** — for EACH important class: explain its purpose, design role, key methods, and how it relates to other classes. Go beyond listing — explain what each class does and WHY. Read the actual source code for each class.
   - **How It Works** — main flows, patterns, algorithms, and design decisions. Trace a typical request or operation through the code step by step.
   - **Data Model** — if there are entity/DTO/model classes, explain the data structures and their relationships
   - **Dependencies and Integration** — what this module connects to, and how
   - **Notes for Developers** — gotchas, extension points, conventions worth knowing
4. Include at least one mermaid diagram showing the most important relationships.
4a. ${MERMAID_AGENT_RULES}
5. **Use exact code links from the evidence sections** when citing code — these make the documentation interactive.
6. Write in a documentation tone: clear, direct, helpful. Explain things as if onboarding a new engineer.
7. When inferring business purpose from code patterns, say "This appears to..." rather than stating as fact.
8. **Do not invent** symbols, files, or dependencies not present in the evidence.
9. **Aim for depth over breadth** — it's better to explain 5 classes in detail than 20 classes superficially.
10. **Read the actual source code** for each important class using \`read_file\`. Don't just work from the metadata — look at the implementation and explain what the code actually does.
11. For each key method, explain: what it does, what parameters it takes, what it returns, and any important side effects or business logic.
12. **Large files**: Some source files may be very large (10,000+ lines). Do NOT try to read an entire large file at once. Instead, use the line numbers from the method list above to read specific sections (e.g., read lines 100-200 for a specific method). Use the pre-indexed method list as your authoritative inventory — do not try to enumerate all methods by scanning the whole file.

${buildOutputContract(`${wikiDir}/${module.docPath}`)}

Read specific sections of the source files, then write the completed documentation with \`write_file\`.`;
}

/* ------------------------------------------------------------------ */
/*  Parent module prompt                                               */
/* ------------------------------------------------------------------ */

export function buildParentPrompt(
  module: ModuleNode,
  tree: ModuleNode,
  sourcePath: string,
  wikiDir: string,
  evidence: ModuleEvidence,
): string {
  const title = humanTitle(module.path || module.name);
  const childDocs = module.children
    .filter((c) => c.docPath)
    .map((c) => `- ${wikiDir}/${c.docPath} (${c.name})`)
    .join("\n");

  return `You are a technical documentation writer synthesizing a parent-level overview from child module documentation.

Read the child wiki pages listed below, then write a cohesive overview that explains how these sub-modules work together as a system.

## Parent module: ${title}
- Package path: \`${module.path}\`
- Output path for \`write_file\`: \`${wikiDir}/${module.docPath}\`

${buildTreeContext(module, tree)}

## Child documentation pages to read
${childDocs || "- No child pages available"}

## Evidence from code analysis

### Module statistics
${evidence.facts}

### Sub-module links
${evidence.childLinks}

### Source files
${evidence.fileInventory}

### Classes and interfaces
${evidence.classReferences}

### Package dependencies
${evidence.dependencySummary}

### Cross-module relationships
${evidence.crossModuleRelationships}

### Import patterns
${evidence.importPatterns}

## Writing guidelines

1. Write in Markdown. Use the title: # ${title}
2. **Start with a clear overview** — what is this area of the codebase responsible for? What business or technical capability does it represent?
3. Use these sections as a guide:
   - **Overview** — the purpose and scope of this module
   - **Sub-module Guide** — what each child module does and how they relate to each other (don't just summarize — explain the relationships)
   - **Key Patterns and Architecture** — design patterns, data flows, or architectural decisions that span the sub-modules
   - **Dependencies and Integration** — external dependencies and how this module connects to the rest of the system
   - **Notes for Developers** — important context for anyone working in this area
4. Include at least one mermaid diagram showing how the sub-modules interact.
4a. ${MERMAID_AGENT_RULES}
5. Use exact code links from the evidence sections.
6. Synthesize — don't just concatenate child summaries. Explain the bigger picture.
7. When inferring intent, say "This appears to..." rather than stating as fact.

${buildOutputContract(`${wikiDir}/${module.docPath}`)}

Write the completed documentation with \`write_file\`.`;
}

/* ------------------------------------------------------------------ */
/*  Root overview prompt                                               */
/* ------------------------------------------------------------------ */

export function buildRootPrompt(
  tree: ModuleNode,
  index: RepoIndex,
  sourcePath: string,
  wikiDir: string,
  evidence: RootEvidence,
  resourceFiles: string[],
): string {
  const topLevelDocs = tree.children
    .filter((c) => c.docPath)
    .map((c) => `- ${wikiDir}/${c.docPath} (${c.name})`)
    .join("\n");

  const resourceSection =
    resourceFiles.length > 0
      ? `## Non-Java resource files discovered\n${resourceFiles.map((f) => `- ${f}`).join("\n")}`
      : "";

  return `You are a technical documentation writer creating the main overview page for a software repository.

This page is the first thing an engineer reads when exploring this codebase. Make it welcoming, clear, and useful.

## Repository facts
${evidence.repoStats}

## Technology stack (detected from imports)
${evidence.technologyStack}

## Top-level module pages to read
${topLevelDocs || "- No top-level package pages available"}

## Module summary
${evidence.topLevelSummary}

## Code reference catalog
${evidence.referenceCatalog}

${resourceSection}

## Writing guidelines

1. Write in Markdown. Use the title: # Repository Overview
2. **Start with a welcoming orientation** — in 3-4 sentences, tell the reader what this repository is, what it does, and what technology it uses. Write as if greeting a new team member.
3. Use these sections:
   - **Overview** — what this project is and what it does
   - **Technology Stack** — frameworks, libraries, and tools detected
   - **Architecture** — high-level system design with a mermaid diagram showing how the main modules relate
   - **Module Guide** — a paragraph for each top-level module explaining its purpose and key classes
   - **Getting Started** — where a new developer should start reading: entry points, main classes, and recommended reading order
   - **Resource Files** — if there are non-Java config/resource files, mention what they're for
4. Include a mermaid architecture diagram showing the main modules and their dependencies.
4a. ${MERMAID_AGENT_RULES}
5. Use exact code links from the Reference Catalog.
6. Write for a developer who has never seen this codebase before.
7. When inferring purpose, say "This appears to..." rather than stating as fact.

${buildOutputContract(`${wikiDir}/overview.md`)}

Write the completed documentation with \`write_file\`.`;
}

/* ------------------------------------------------------------------ */
/*  Cross-cutting pattern prompt                                       */
/* ------------------------------------------------------------------ */

export function buildCrossCuttingPrompt(
  pattern: CrossCuttingPattern,
  graph: KnowledgeGraph,
  sourcePath: string,
  wikiDir: string,
): string {
  const classInfo = pattern.nodeIds
    .slice(0, 20)
    .map((nodeId) => {
      try {
        const attrs = graph.getNodeAttrs(nodeId);
        const fp = getString(attrs, "file_path") || "";
        const name = String(attrs.name);
        return `- ${buildCodeLink(name, sourcePath, fp, getNumber(attrs, "line_start"), getNumber(attrs, "line_end"), name)} (${String(attrs.type)})`;
      } catch {
        return null;
      }
    })
    .filter(Boolean)
    .join("\n");

  const fileList = pattern.files
    .slice(0, 20)
    .map((fp) => `- ${fp}`)
    .join("\n");

  const docPath = `guides/${pattern.id}.md`;

  return `You are a technical documentation writer. Write a cross-cutting documentation page about "${pattern.title}" for this codebase.

## Topic: ${pattern.title}
${pattern.description}

## Output path for \`write_file\`: \`${wikiDir}/${docPath}\`

## Relevant classes (from code analysis)
${classInfo || "No matching classes found."}

## Relevant source files
${fileList || "No matching files found."}

## Import signals
${pattern.importSignals.length > 0 ? pattern.importSignals.map((s) => `- ${s}`).join("\n") : "No import signals."}

## Writing guidelines

1. Write in Markdown. Use the title: # ${pattern.title}
2. Start with an overview of how this concern is handled across the codebase.
3. Include sections for:
   - **Overview** — what this concern is and why it matters
   - **Implementation Patterns** — how the codebase implements this concern (with code references)
   - **Key Classes** — the most important classes involved, with explanations
   - **How It Fits Together** — a mermaid diagram or explanation of how the pieces connect
   - **Notes for Developers** — what to know when working with this concern
4. Use exact code links when referencing specific classes.
5. Focus on patterns and architecture, not individual method details.
6. ${MERMAID_AGENT_RULES}

${buildOutputContract(`${wikiDir}/${docPath}`)}

Read the relevant source files, then write the documentation with \`write_file\`.`;
}

/* ------------------------------------------------------------------ */
/*  Getting started guide prompt                                       */
/* ------------------------------------------------------------------ */

export function buildGettingStartedPrompt(
  tree: ModuleNode,
  keyClasses: KeyClassCandidate[],
  graph: KnowledgeGraph,
  sourcePath: string,
  wikiDir: string,
  resourceFiles: string[],
): string {
  const modules = tree.children
    .map((c) => `- **${c.name}** (${c.path}): ${c.classes.length} classes, ${c.children.length} sub-modules`)
    .join("\n");

  const keyClassInfo = keyClasses
    .slice(0, 10)
    .map((kc) => {
      return `- ${buildCodeLink(kc.name, sourcePath, kc.filePath, kc.lineStart, kc.lineEnd, kc.name)} — ${kc.connectionCount} connections (highly referenced)`;
    })
    .join("\n");

  const resourceSection =
    resourceFiles.length > 0
      ? `## Resource and config files\n${resourceFiles.slice(0, 15).map((f) => `- ${f}`).join("\n")}`
      : "";

  return `You are a technical documentation writer. Create a "Getting Started" guide for engineers who are new to this codebase.

## Output path for \`write_file\`: \`${wikiDir}/guides/getting-started.md\`

## Repository modules
${modules || "No modules found."}

## Most-referenced classes (entry points and key abstractions)
${keyClassInfo || "No highly-connected classes found."}

${resourceSection}

## Writing guidelines

1. Write in Markdown. Use the title: # Getting Started
2. This page should answer: "I just joined the team — where do I start reading?"
3. Include:
   - **What This Project Does** — 2-3 sentence summary
   - **Recommended Reading Order** — which wiki pages to read first, second, third
   - **Key Entry Points** — the most important classes to understand first (use the highly-referenced classes above)
   - **Project Structure** — how the source code is organized
   - **Configuration** — key config files and what they control
   - **Common Patterns** — coding conventions and patterns used throughout
4. Keep it concise and actionable. This is a guide, not a reference.
5. Use code links when referencing specific classes or files.
6. ${MERMAID_AGENT_RULES}

${buildOutputContract(`${wikiDir}/guides/getting-started.md`)}

Write the documentation with \`write_file\`.`;
}

/* ------------------------------------------------------------------ */
/*  Class deep-dive prompt                                             */
/* ------------------------------------------------------------------ */

/* ------------------------------------------------------------------ */
/*  Detailed Design (DD) prompt                                        */
/* ------------------------------------------------------------------ */

export interface DDMethodInfo {
  /** DD sequential number (DD01, DD02, ...) */
  ddIndex: number;
  className: string;
  methodName: string;
  filePath: string;
  lineStart?: number;
  lineEnd?: number;
  returnType?: string;
  parameters: string[];
  javadoc?: string;
  /** Pre-read source code to embed in the prompt (avoids agent file reads). */
  sourceCode?: string;
}

export function buildDDPrompt(
  method: DDMethodInfo,
  sourcePath: string,
  wikiDir: string,
): string {
  const ddLabel = `DD${String(method.ddIndex).padStart(2, "0")}`;
  const sig = `${method.className}.${method.methodName}(${method.parameters.join(", ")})`;
  const lineRange = method.lineStart && method.lineEnd
    ? `lines ${method.lineStart}–${method.lineEnd}`
    : "unknown lines";
  const loc = method.lineStart && method.lineEnd
    ? method.lineEnd - method.lineStart + 1
    : 0;
  const docPath = `dd/${method.className}/${method.methodName}.md`;
  const docFullPath = `${wikiDir}/${docPath}`;

  const sourceSection = method.sourceCode
    ? `## Source Code (pre-loaded, DO NOT read the file again)\n\n\`\`\`java\n${method.sourceCode}\n\`\`\``
    : `## Source\nRead lines ${method.lineStart ?? 1}–${Math.min(method.lineEnd ?? 300, (method.lineStart ?? 1) + 299)} of ${method.filePath} using \`read_file\`.`;

  return `You are a technical documentation writer producing a Detailed Design (DD) document for a single Java method. Write everything in English.

Follow the template below EXACTLY. Each DD document describes one method's processing logic, control flow, called methods, and their detailed descriptions.

## Method to document
- DD Label: ${ddLabel}
- Class: \`${method.className}\`
- Method: \`${method.methodName}\`
- Signature: \`${sig}\`
- Return type: \`${method.returnType || "void"}\`
- File: ${method.filePath}
- Line range: ${lineRange} (${loc} LOC)
${method.javadoc ? `- Javadoc: ${method.javadoc}` : ""}

## Output path for \`write_file\`: \`${docFullPath}\`

${sourceSection}

## CRITICAL INSTRUCTIONS

${method.sourceCode ? "1. The source code is provided above. Do NOT use `read_file` or `search_files`." : "1. Read the source code ONCE with `read_file`. Do NOT read any other files or search."}
2. Analyze the control flow and identify all method calls in the source.
3. Use the verify_mermaid tool to validate EVERY mermaid diagram before writing. If invalid, fix and re-verify.
4. Write the DD document with \`write_file\`.
5. Write EVERYTHING in English. Translate any Japanese comments to English.
6. For methods larger than 300 lines: document only the portion shown.

${buildOutputContract(docFullPath)}

## Template to follow

Write the document in this exact structure:

\`\`\`
# (${ddLabel}) [Short descriptive title of what this method does]

## 1. Data Flow Processing Logic

\`\`\`mermaid
flowchart TD
    ${ddLabel}(["${ddLabel}"])
    ... [nodes for each processing step, condition, and method call]
    NEXT(["Next step / Return"])

    ${ddLabel} --> ...
    ... --> NEXT
\`\`\`

### Inputs

- List each input parameter with its type, e.g. \`(paramType) paramName\`
- Also list any instance fields or external state read by the method

### Processing Rules

Describe the main logic of the method in plain language. For each conditional branch:

### If [condition description]

Explain what happens when the condition is true.

### If [condition is false] / Else

Explain the alternative path.

(Add more conditional sections as needed for the actual method logic.)

## 2. Sequence Diagram

\`\`\`mermaid
sequenceDiagram
    participant Caller as [CallerClass]
    participant Target as [TargetClass]
    ... [participants for each class whose methods are called]

    Caller->>Target: methodName(args)
    ... [show the actual call sequence]
\`\`\`

## 3. Class / Method List

| No | Class | Method | Arguments |
| --- | --- | --- | --- |
| 1 | \`ClassName\` | \`methodName\` | \`argType arg1, argType arg2\` |
... [list ALL methods called within the documented method]

## 4. Detailed Class / Method Description

### 1. \`ClassName.methodName\`

| Field | Value |
| --- | --- |
| Class Name | \`ClassName\` |
| Method Name | \`methodName\` |
| Arguments | \`argType1 arg1, argType2 arg2\` |
| Argument Description | \`arg1\` - description of argument. \`arg2\` - description. |
| Return Type | \`returnType\` |
| Overview | One-line summary of what this method does |
| Description | Detailed description of the method's behavior, including edge cases and side effects. |

... [repeat for each method listed in Section 3]
\`\`\`

## Writing rules

1. The flowchart must accurately reflect the method's control flow — every if/else, loop, and method call should be represented.
2. ${MERMAID_AGENT_RULES}
3. In the Sequence Diagram, show the actual runtime call sequence — which object calls which method in what order.
4. The Class/Method List in Section 3 must list EVERY method called within the documented method.
5. Section 4 must provide a detailed description for EACH method listed in Section 3. If you cannot determine full details, describe what you can infer from the call context.
6. Use the method's Javadoc (if provided above) to inform your descriptions, but verify against the actual source code.
7. For Japanese comments in the source code, preserve them and also provide English translations where helpful.
8. Do NOT invent methods or classes that aren't actually called in the source code.
9. Write the completed document with \`write_file\`.`;
}

export function buildClassDeepDivePrompt(
  candidate: KeyClassCandidate,
  graph: KnowledgeGraph,
  sourcePath: string,
  wikiDir: string,
): string {
  const attrs = graph.getNodeAttrs(candidate.nodeId);
  const classType = String(attrs.type);
  const extendsName = getString(attrs, "extends") || "none";
  const implementsNames = Array.isArray(attrs.implements)
    ? attrs.implements.filter((v): v is string => typeof v === "string")
    : [];

  // Collect methods
  const methodLines: string[] = [];
  for (const memberId of graph.getNeighbors(candidate.nodeId, EdgeType.CONTAINS, "out")) {
    let mAttrs: Record<string, unknown>;
    try { mAttrs = graph.getNodeAttrs(memberId); } catch { continue; }
    const mType = String(mAttrs.type);
    if (mType !== NodeType.METHOD && mType !== NodeType.CONSTRUCTOR) continue;
    const mName = String(mAttrs.name);
    const mParams = Array.isArray(mAttrs.parameters)
      ? mAttrs.parameters.filter((v): v is string => typeof v === "string")
      : [];
    const mReturn = getString(mAttrs, "return_type") || "void";
    const mLineStart = getNumber(mAttrs, "line_start");
    const mLineEnd = getNumber(mAttrs, "line_end");
    const link = buildCodeLink(
      `${candidate.name}.${mName}`,
      sourcePath,
      candidate.filePath,
      mLineStart,
      mLineEnd,
      `${candidate.name}.${mName}`,
    );
    const lineRange = mLineStart && mLineEnd
      ? ` [lines ${mLineStart}–${mLineEnd}]`
      : "";
    methodLines.push(`- ${link}(${mParams.join(", ")}) → ${mReturn}${lineRange}`);
  }

  // Collect who uses this class (inbound)
  const usedByLines: string[] = [];
  for (const edgeType of [EdgeType.REFERENCES, EdgeType.CALLS, EdgeType.IMPLEMENTS, EdgeType.EXTENDS]) {
    for (const callerId of graph.getNeighbors(candidate.nodeId, edgeType, "in")) {
      if (!graph.hasNode(callerId)) continue;
      const callerAttrs = graph.getNodeAttrs(callerId);
      const callerName = getString(callerAttrs, "name");
      if (callerName) usedByLines.push(`- ${callerName} (${edgeType})`);
    }
  }

  // Collect what this class uses (outbound)
  const usesLines: string[] = [];
  for (const edgeType of [EdgeType.REFERENCES, EdgeType.CALLS, EdgeType.EXTENDS, EdgeType.IMPLEMENTS]) {
    for (const targetId of graph.getNeighbors(candidate.nodeId, edgeType, "out")) {
      if (!graph.hasNode(targetId)) continue;
      const targetAttrs = graph.getNodeAttrs(targetId);
      const targetName = getString(targetAttrs, "name");
      if (targetName) usesLines.push(`- ${targetName} (${edgeType})`);
    }
  }

  const docPath = `deep-dive/${candidate.name}.md`;

  return `You are a technical documentation writer. Write an in-depth documentation page for a single, important class in this codebase.

This class has ${candidate.connectionCount} inbound connections, making it one of the most important types in the system. Your documentation should help a developer fully understand its purpose, design, and usage.

## Class: ${candidate.name}
- Type: ${classType}
- File: ${candidate.filePath}
- Lines: ${candidate.lineStart ?? "?"}–${candidate.lineEnd ?? "?"}
- Extends: ${extendsName}
- Implements: ${implementsNames.length > 0 ? implementsNames.join(", ") : "none"}
- Inbound connections: ${candidate.connectionCount}

## Output path for \`write_file\`: \`${wikiDir}/${docPath}\`

## Methods
${methodLines.length > 0 ? methodLines.join("\n") : "No methods indexed."}

## Used by (${usedByLines.length} classes depend on this)
${uniqueStrings(usedByLines).slice(0, 20).join("\n") || "No inbound references found."}

## Uses (outbound dependencies)
${uniqueStrings(usesLines).slice(0, 15).join("\n") || "No outbound references found."}

## Writing guidelines

1. Write in Markdown. Use the title: # ${candidate.name}
2. **Read specific sections of the source file** — this file may be very large (${candidate.lineEnd ? `${(candidate.lineEnd - (candidate.lineStart ?? 1))} lines` : "unknown size"}). Do NOT try to read the entire file at once. Instead:
   - First read lines ${candidate.lineStart ?? 1}–${Math.min((candidate.lineStart ?? 1) + 100, candidate.lineEnd ?? 200)} to see the class declaration, fields, and first methods.
   - Then read specific method line ranges from the method list above.
   - Focus on the most important methods (public methods, methods with many callers).
3. **Use the pre-indexed method list above** as your complete method inventory. Do NOT try to enumerate all methods by reading the whole file — the list above is authoritative.
4. Include these sections:
   - **Purpose** — what this class does, why it exists, what problem it solves (2-3 sentences)
   - **Design** — the design pattern or architectural role (e.g., facade, repository, service, data object)
   - **Key Methods** — explain each important method: what it does, its parameters, return value, and any side effects. Go into detail. You have ${methodLines.length} methods listed above — document the most important ones.
   - **Relationships** — who uses this class and why, what this class depends on. Include a mermaid diagram showing the most important relationships.
   - **Usage Example** — if the code reveals typical calling patterns, describe how this class is typically used
   - **Notes for Developers** — gotchas, thread safety, immutability, important invariants
5. **Be specific** — reference actual method names, parameter types, and return types from the source.
6. When inferring intent, say "This appears to..." rather than stating as fact.
7. Include a mermaid class or flowchart diagram.
8. ${MERMAID_AGENT_RULES}

${buildOutputContract(`${wikiDir}/${docPath}`)}

Read specific line ranges of the source file, then write the documentation with \`write_file\`.`;
}
