import json
import uuid
from pathlib import Path

from mixersystem.data.repository import get_context, rel_path
from mixersystem.data.agent_sdk import call_agent

MODEL = "M"
_AGENT_NAME = "update_question_builder"

ASK_PROMPT = """\
<role>
You are the Update Question Generator. You generate thoughtful questions about documentation updates needed after implementation.
</role>

<quick-start>
1. Read the existing artifacts for this job:
{artifacts}
2. Read the following project docs:
{docs}
3. Read the rules for creating updates:
{rules}
</quick-start>

<existing-questions>
{existing_questions}
</existing-questions>

<disliked-questions>
Questions the user disliked — avoid asking similar questions:
{disliked_questions}
</disliked-questions>

<steps>
1. Analyze the work output, implementation changes, and existing documentation
2. Generate 3-5 new questions about what documentation needs updating, what's missing, or what might be outdated
3. Questions can be about API docs, README updates, configuration changes, or migration guides
4. Keep each question to one paragraph
5. Do NOT repeat existing questions or ask questions similar to disliked ones
</steps>

<constraints>
- Focus on documentation: what changed, what's missing, what's outdated, what needs migration notes
- Consider user-facing docs, developer docs, and internal references
- Each question should be actionable — answering it should change what gets documented
- Avoid generic questions
- Implemented questions are shown for context — do not re-ask them
- You MUST follow the exact output format below
</constraints>

<output-format>
[RESULT]
questions:
- Question text here
- Another question here
- A third question here
[NOTES]
Summary of what areas the questions cover.
</output-format>"""

RESPOND_PROMPT = """\
<role>
You are the Update Question Responder. You answer questions about documentation updates using project context.
</role>

<quick-start>
1. Read the existing artifacts for this job:
{artifacts}
2. Read the following project docs:
{docs}
3. Read the rules for creating updates:
{rules}
</quick-start>

<questions-to-answer>
{questions_to_answer}
</questions-to-answer>

<steps>
1. Read all context carefully
2. Answer each question based on the implementation changes and existing documentation
3. Be specific about what should be documented and where
</steps>

<constraints>
- Answer every question listed above
- Base answers on actual project context, not assumptions
- Keep answers concise but complete
- You MUST follow the exact output format below
</constraints>

<output-format>
[RESULT]
answers:
- Answer to first question
- Answer to second question
- Answer to third question
[NOTES]
Summary of answers provided.
</output-format>"""


def _format_existing(questions: list[dict]) -> str:
    if not questions:
        return "(none)"
    lines = []
    for q in questions:
        status = []
        if q.get("answer"):
            status.append("answered")
        if q.get("implemented"):
            status.append("implemented")
        tag = f" [{', '.join(status)}]" if status else ""
        lines.append(f"- {q['text']}{tag}")
    return "\n".join(lines)


def _format_disliked(questions: list[dict]) -> str:
    disliked = [q for q in questions if q.get("reaction") == "dislike"]
    if not disliked:
        return "(none)"
    return "\n".join(f"- {q['text']}" for q in disliked)


def _format_to_answer(questions: list[dict]) -> str:
    pending = [q for q in questions if q.get("auto_respond") and not q.get("answer")]
    if not pending:
        return "(none)"
    return "\n".join(f"- [{q['id']}] {q['text']}" for q in pending)


async def run_ask(*, questions: list[dict], provider: str = "claude") -> list[dict]:
    ctx = get_context()
    prompt = ASK_PROMPT.format(
        artifacts=ctx.resolve_artifacts(),
        docs=ctx.resolve_docs(),
        rules=ctx.resolve_rules("update"),
        existing_questions=_format_existing(questions),
        disliked_questions=_format_disliked(questions),
    )
    response, _ = await call_agent(
        prompt=prompt, model=MODEL, provider=provider, agent_name=_AGENT_NAME,
    )
    new_questions = _parse_questions_response(response)
    return questions + new_questions


async def run_respond(*, questions: list[dict], provider: str = "claude") -> list[dict]:
    ctx = get_context()
    pending = [q for q in questions if q.get("auto_respond") and not q.get("answer")]
    if not pending:
        return questions
    prompt = RESPOND_PROMPT.format(
        artifacts=ctx.resolve_artifacts(),
        docs=ctx.resolve_docs(),
        rules=ctx.resolve_rules("update"),
        questions_to_answer=_format_to_answer(questions),
    )
    response, _ = await call_agent(
        prompt=prompt, model=MODEL, provider=provider, agent_name=_AGENT_NAME,
    )
    answers = _parse_answers_response(response)
    return _apply_answers(questions, pending, answers)


def _parse_questions_response(text: str) -> list[dict]:
    result_marker = text.find("[RESULT]")
    if result_marker == -1:
        return []
    after = text[result_marker + len("[RESULT]"):]
    notes_marker = after.find("[NOTES]")
    section = after[:notes_marker] if notes_marker != -1 else after
    questions = []
    for line in section.strip().splitlines():
        line = line.strip()
        if line.startswith("- ") and len(line) > 2:
            q_text = line[2:].strip()
            if q_text:
                questions.append({
                    "id": uuid.uuid4().hex[:8],
                    "text": q_text,
                    "answer": None,
                    "auto_respond": False,
                    "reaction": None,
                    "implemented": False,
                })
    return questions


def _parse_answers_response(text: str) -> list[str]:
    result_marker = text.find("[RESULT]")
    if result_marker == -1:
        return []
    after = text[result_marker + len("[RESULT]"):]
    notes_marker = after.find("[NOTES]")
    section = after[:notes_marker] if notes_marker != -1 else after
    answers = []
    for line in section.strip().splitlines():
        line = line.strip()
        if line.startswith("- ") and len(line) > 2:
            answers.append(line[2:].strip())
    return answers


def _apply_answers(questions: list[dict], pending: list[dict], answers: list[str]) -> list[dict]:
    pending_ids = {q["id"] for q in pending}
    answer_iter = iter(answers)
    updated = []
    for q in questions:
        if q["id"] in pending_ids:
            answer = next(answer_iter, None)
            if answer:
                q = {**q, "answer": answer}
        updated.append(q)
    return updated
