from pathlib import Path
from typing import Mapping, Optional

from .config import Config
from .docs import DocsManager
from .prompts import DEFAULT_PROMPT_TEMPLATE, FINAL_SUMMARY_PROMPT_TEMPLATE


def _display_path(root: Path, path: Path) -> str:
    try:
        return str(path.relative_to(root))
    except ValueError:
        return str(path)


def build_doc_paths(config: Config) -> Mapping[str, str]:
    return {
        "todo": _display_path(config.root, config.doc_path("todo")),
        "progress": _display_path(config.root, config.doc_path("progress")),
        "opinions": _display_path(config.root, config.doc_path("opinions")),
        "spec": _display_path(config.root, config.doc_path("spec")),
        "summary": _display_path(config.root, config.doc_path("summary")),
    }


def load_prompt_template(config: Config) -> str:
    template_path: Optional[Path] = config.prompt_template
    if template_path and template_path.exists():
        return template_path.read_text(encoding="utf-8")
    return DEFAULT_PROMPT_TEMPLATE


def build_prompt_text(
    *,
    template: str,
    docs: Mapping[str, str],
    doc_paths: Mapping[str, str],
    prev_run_output: Optional[str],
) -> str:
    prev_section = ""
    if prev_run_output:
        prev_section = "<PREV_RUN_OUTPUT>\n" + prev_run_output + "\n</PREV_RUN_OUTPUT>"

    replacements = {
        "{{TODO}}": docs.get("todo", ""),
        "{{PROGRESS}}": docs.get("progress", ""),
        "{{OPINIONS}}": docs.get("opinions", ""),
        "{{SPEC}}": docs.get("spec", ""),
        "{{SUMMARY}}": docs.get("summary", ""),
        "{{PREV_RUN_OUTPUT}}": prev_section,
        "{{TODO_PATH}}": doc_paths.get("todo", ""),
        "{{PROGRESS_PATH}}": doc_paths.get("progress", ""),
        "{{OPINIONS_PATH}}": doc_paths.get("opinions", ""),
        "{{SPEC_PATH}}": doc_paths.get("spec", ""),
        "{{SUMMARY_PATH}}": doc_paths.get("summary", ""),
    }
    for marker, value in replacements.items():
        template = template.replace(marker, value)
    return template


def build_prompt(
    config: Config, docs: DocsManager, prev_run_output: Optional[str]
) -> str:
    doc_paths = build_doc_paths(config)
    template = load_prompt_template(config)
    doc_contents = {
        "todo": docs.read_doc("todo"),
        "progress": docs.read_doc("progress"),
        "opinions": docs.read_doc("opinions"),
        "spec": docs.read_doc("spec"),
        "summary": docs.read_doc("summary"),
    }
    return build_prompt_text(
        template=template,
        docs=doc_contents,
        doc_paths=doc_paths,
        prev_run_output=prev_run_output,
    )


def build_final_summary_prompt(
    config: Config, docs: DocsManager, prev_run_output: Optional[str] = None
) -> str:
    """
    Build the final report prompt that produces/updates SUMMARY.md once TODO is complete.

    Note: Unlike build_prompt(), this intentionally does not use the repo's prompt.template
    override. It's a separate, purpose-built job.
    """

    doc_paths = build_doc_paths(config)
    doc_contents = {
        "todo": docs.read_doc("todo"),
        "progress": docs.read_doc("progress"),
        "opinions": docs.read_doc("opinions"),
        "spec": docs.read_doc("spec"),
        "summary": docs.read_doc("summary"),
    }
    # Keep a hook for future expansion (template doesn't currently include it).
    _ = prev_run_output
    return build_prompt_text(
        template=FINAL_SUMMARY_PROMPT_TEMPLATE,
        docs=doc_contents,
        doc_paths=doc_paths,
        prev_run_output=None,
    )
