//! Instruction builders for each operation (plan §6–§9). The system prompt
//! (role + conventions) and context (repo map / diff / index) are supplied
//! separately on the [`crate::agent::AgentTask`].

use crate::state::manifest::ChangeSet;

/// System prompt = role + a compact restatement of the wiki conventions.
pub fn system_prompt(project_name: &str) -> String {
    format!(
        "{role}\n\nProject: {project}\n\n\
         Conventions (also in wiki/HEPHAES.md):\n\
         - Page types: overview, architecture, module, concept, flow, decision, answer, glossary.\n\
         - Put pages in matching subdirs (modules/, concepts/, architecture/, flows/, decisions/, answers/).\n\
         - Every page starts with YAML frontmatter: title, type, sources (paths/globs), related ([[links]]), summary, updated.\n\
         - `sources:` must list the real source paths the page summarizes — it drives incremental updates.\n\
         - Link related pages with [[wikilinks]]; cite source as path/to/file:line.\n\
         - Keep index.md and log.md current. Never write outside the wiki dir.",
        role = crate::wiki::schema::ROLE,
        project = project_name,
    )
}

/// `init`: build the wiki from scratch.
pub fn init_instruction() -> String {
    "Build the wiki for this repository from scratch.\n\n\
     1. Study the repository map (below) and read the key source files to understand what the \
        project is, how it is structured, and how data/control flows through it.\n\
     2. Create high-signal pages: an overview.md, one page per meaningful module under modules/, \
        concept pages under concepts/ for important abstractions, and flow/decision pages where \
        warranted. Fill frontmatter on every page — especially accurate `sources:`.\n\
     3. Cross-link pages with [[wikilinks]] and cite source as file:line.\n\n\
     Prefer a focused set of excellent pages over many thin ones. Read the source when unsure; \
     never invent behavior. Do not edit index.md or log.md — hephaes maintains those for you."
        .to_string()
}

/// `update`: reconcile the wiki with changed sources.
pub fn update_instruction(cs: &ChangeSet, affected: &[String]) -> String {
    let mut s = String::from(
        "The repository changed since the wiki was last built. Update the wiki to reflect the \
         changes below.\n\n",
    );
    let list = |label: &str, items: &[String]| -> String {
        if items.is_empty() {
            String::new()
        } else {
            format!("{label}:\n{}\n\n", bullet(items))
        }
    };
    s.push_str(&list("Added files", &cs.added));
    s.push_str(&list("Modified files", &cs.modified));
    s.push_str(&list("Deleted files", &cs.deleted));
    if !affected.is_empty() {
        s.push_str(&format!("Likely affected pages:\n{}\n\n", bullet(affected)));
    }
    s.push_str(
        "Re-read the changed source files. Update the affected pages (creating new pages for \
         significant new files, retiring pages for removed ones). Keep `sources:` accurate. If a \
         change contradicts an existing page, update the page and note the change rather than \
         silently overwriting. Do not edit index.md or log.md — hephaes maintains those.",
    );
    s
}

/// `ask`: answer a question against the wiki.
pub fn ask_instruction(question: &str, from_source: bool) -> String {
    let source_note = if from_source {
        " You may read source files directly when the wiki is insufficient."
    } else {
        " Prefer the wiki; read source only if strictly necessary."
    };
    format!(
        "Answer the following question using the wiki. Read index.md first, then open the relevant \
         pages.{source_note} Cite wiki pages and source as file:line. Be concise and concrete.\n\n\
         Question: {question}"
    )
}

/// `lint --deep`: LLM health-check.
pub fn lint_instruction() -> String {
    "Health-check this wiki. Read index.md and the pages, and report: contradictions between \
     pages, stale claims the current source has superseded, orphan pages, important concepts that \
     lack a page, and broken [[links]]. Output a concise findings report; do not modify pages."
        .to_string()
}

fn bullet(items: &[String]) -> String {
    items
        .iter()
        .take(80)
        .map(|i| format!("- {i}"))
        .collect::<Vec<_>>()
        .join("\n")
}
