"""
cortex/dialectic/prompts.py — Prompt templates for the Dialectic Engine.

Centralises all LLM prompt strings so they can be tuned, versioned, and
tested independently of the engine logic.

Templates:
    SYNTHESIS_PROMPT        — System prompt for grounded Q&A from retrieved memories.
    HISTORY_SYSTEM_PROMPT   — System prompt for history-aware Q&A.
    DECOMPOSE_PROMPT        — Break a complex question into sub-queries (agentic path).
    CONTINUE_PROMPT         — Decide if more retrieval is needed (agentic path).
    FINAL_SYNTHESIS_PROMPT  — Synthesise final answer from all evidence (agentic path).
    format_memories         — Helper: list of memory dicts → numbered prompt block.
    format_history          — Helper: conversation history → plain-text transcript.
    format_evidence_chain   — Helper: list of evidence items → numbered prompt block.
"""

from __future__ import annotations

from typing import Any, Dict, List

# ---------------------------------------------------------------------------
# System prompts
# ---------------------------------------------------------------------------

SYNTHESIS_PROMPT = (
    "You are a memory assistant. "
    "Given the following memories about {owner_id}, answer the user's question. "
    "Only use information from the provided memories. "
    "If the memories don't contain enough information, say so.\n\n"
    "Memories:\n"
    "{memories_block}"
)

HISTORY_SYSTEM_PROMPT = (
    "You are a memory assistant engaged in a conversation. "
    "Given the following memories about {owner_id} and the conversation history, "
    "answer the user's latest question. "
    "Only use information from the provided memories. "
    "If the memories don't contain enough information, say so.\n\n"
    "Memories:\n"
    "{memories_block}"
)

# ---------------------------------------------------------------------------
# Agentic path prompts (M14 — multi-step retrieval loop)
# ---------------------------------------------------------------------------

DECOMPOSE_PROMPT = (
    "Break this question into 2-4 simpler sub-questions that together fully cover "
    "the original question. Each sub-question should be independently answerable "
    "from a memory store.\n\n"
    "Output ONLY a numbered list of sub-questions, one per line, with no preamble "
    "or explanation. Example format:\n"
    "1. What is the user's primary programming language?\n"
    "2. What projects is the user currently working on?\n\n"
    "Question to decompose: {query}"
)

CONTINUE_PROMPT = (
    "You are evaluating whether a complex question has been fully answered given "
    "the evidence collected so far.\n\n"
    "Original question: {query}\n\n"
    "Evidence collected:\n"
    "{evidence_block}\n\n"
    "Answer with ONLY 'yes' if the evidence fully answers the question, "
    "or 'no' if more retrieval is needed. No explanation."
)

FINAL_SYNTHESIS_PROMPT = (
    "You are a memory assistant. "
    "Synthesise a complete, coherent answer to the original question using ALL "
    "evidence collected across multiple retrieval steps.\n\n"
    "Original question: {query}\n\n"
    "Evidence chain:\n"
    "{evidence_block}\n\n"
    "Instructions:\n"
    "- Ground your answer strictly in the evidence above.\n"
    "- Be concise but complete.\n"
    "- If the evidence is contradictory, note the contradiction.\n"
    "- If the evidence is insufficient, say so clearly."
)

# ---------------------------------------------------------------------------
# Formatting helpers
# ---------------------------------------------------------------------------


def format_memories(memories: List[Dict[str, Any]]) -> str:
    """Format a list of memory dicts as a numbered, category-annotated list.

    Each memory dict may contain:
        - subject / predicate / object_value — structured claim fields
        - content / text — free-form content fallback
        - category — optional category label
        - confidence — optional score

    Args:
        memories: List of memory dicts (from RetrievalResult.items).

    Returns:
        A multi-line numbered string ready to embed in a prompt.

    Example output::

        1. [preferences] user prefers dark mode (confidence: 0.92)
        2. [engineering] user works with Python and TypeScript
        3. [identity] user's name is Andrew
    """
    if not memories:
        return "(no memories available)"

    lines: List[str] = []
    for i, mem in enumerate(memories, start=1):
        # Build the textual representation of this memory
        category = mem.get("category") or mem.get("claim_type") or "misc"

        # Prefer structured claim fields; fall back to free-form content
        subject = mem.get("subject", "")
        predicate = mem.get("predicate", "")
        obj = mem.get("object_value", "")

        if subject and predicate and obj:
            text = f"{subject} {predicate} {obj}"
        elif mem.get("content"):
            text = mem["content"]
        elif mem.get("text"):
            text = mem["text"]
        else:
            # Last-resort: join whatever non-empty string values exist
            parts = [str(v) for k, v in mem.items()
                     if isinstance(v, str) and v and k not in ("id", "category", "claim_type")]
            text = " ".join(parts) if parts else str(mem)

        # Confidence annotation (optional)
        confidence = mem.get("score") or mem.get("confidence")
        conf_note = f" (confidence: {confidence:.2f})" if confidence is not None else ""

        lines.append(f"{i}. [{category}] {text}{conf_note}")

    return "\n".join(lines)


def format_history(history: List[Dict[str, str]]) -> str:
    """Format conversation history as a plain-text transcript.

    Args:
        history: List of ``{role, content}`` dicts (older messages first).

    Returns:
        Multi-line string with each turn on a new line.
    """
    lines = []
    for turn in history:
        role = turn.get("role", "user").capitalize()
        content = turn.get("content", "")
        lines.append(f"{role}: {content}")
    return "\n".join(lines)


def format_evidence_chain(evidence_chain: List[Dict[str, Any]]) -> str:
    """Format the agentic evidence chain as a numbered block for synthesis prompts.

    Each item in *evidence_chain* is expected to have:
        sub_query   — the sub-question that generated this evidence
        answer      — intermediate synthesised answer for that sub-query
        sources     — list of memory dicts used

    Args:
        evidence_chain: List of evidence step dicts from the agentic loop.

    Returns:
        Multi-line string ready to embed in CONTINUE_PROMPT or
        FINAL_SYNTHESIS_PROMPT.
    """
    if not evidence_chain:
        return "(no evidence collected)"

    lines: List[str] = []
    for i, step in enumerate(evidence_chain, start=1):
        sub_query = step.get("sub_query", f"Sub-query {i}")
        answer = step.get("answer", "(no answer)")
        sources = step.get("sources", [])
        source_count = len(sources)
        lines.append(
            f"{i}. Sub-query: {sub_query}\n"
            f"   Answer: {answer}\n"
            f"   Sources: {source_count} memories"
        )
    return "\n\n".join(lines)
