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 = "report_question_builder"

ASK_PROMPT = """\
<role>
You are the Report Question Generator. You generate thoughtful questions about the final report and commit message.
</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 reports:
{rules}
</quick-start>

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

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

<user-instructions>
{instructions}
</user-instructions>

<steps>
1. Analyze the work output, updates, upgrades, and overall session history
2. Generate 3-5 new questions about report framing, commit message scope, changelog entries, or release notes
3. Questions can be about what to emphasize, what to omit, or how to categorize changes
4. Keep each question to one paragraph
5. Do NOT repeat existing questions or ask questions similar to disliked ones
</steps>

<constraints>
- Focus on reporting: commit message clarity, changelog accuracy, scope description, audience
- Consider what reviewers and future maintainers need to know
- Each question should be actionable — answering it should change the report output
- 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 Report Question Responder. You answer questions about report content and framing.
</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 reports:
{rules}
</quick-start>

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

<user-instructions>
{instructions}
</user-instructions>

<steps>
1. Read all context carefully
2. Answer each question based on the session history and changes made
3. Be specific about what should be reported and how
</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:
    visible = [q for q in questions if not q.get("inactive") and not q.get("implemented")]
    if not visible:
        return "(none)"
    lines = []
    for q in visible:
        tag = " [answered]" if q.get("answer") 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")]
    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", instructions: str = "") -> list[dict]:
    ctx = get_context()
    prompt = ASK_PROMPT.format(
        artifacts=ctx.resolve_artifacts(),
        docs=ctx.resolve_docs(),
        rules=ctx.resolve_rules("report"),
        existing_questions=_format_existing(questions),
        disliked_questions=_format_disliked(questions),
        instructions=instructions or "(none)",
    )
    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", instructions: str = "") -> list[dict]:
    ctx = get_context()
    pending = [q for q in questions if q.get("auto_respond")]
    if not pending:
        return questions
    prompt = RESPOND_PROMPT.format(
        artifacts=ctx.resolve_artifacts(),
        docs=ctx.resolve_docs(),
        rules=ctx.resolve_rules("report"),
        questions_to_answer=_format_to_answer(questions),
        instructions=instructions or "(none)",
    )
    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,
                    "inactive": False,
                    "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, "auto_respond": False}
        updated.append(q)
    return updated
