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

ASK_PROMPT = """\
<role>
You are the Upgrade Question Generator. You generate thoughtful questions about rule extraction and process improvements.
</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 upgrades:
{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 logs, reviewer feedback, test results, and process artifacts
2. Generate 3-5 new questions about what rules should be extracted, what patterns were learned, or what process improvements are needed
3. Questions can be about recurring issues, generalizable patterns, or rule quality
4. Keep each question to one paragraph
5. Do NOT repeat existing questions or ask questions similar to disliked ones
</steps>

<constraints>
- Focus on process improvement: lessons learned, generalizable rules, recurring patterns, quality gaps
- Consider what future builds would benefit from knowing
- Each question should be actionable — answering it should change what rules get extracted
- 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 Upgrade Question Responder. You answer questions about rule extraction and process improvements.
</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 upgrades:
{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 build history, logs, and existing rules
3. Be specific about what rules or improvements should be captured
</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("upgrade"),
        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("upgrade"),
        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
