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

ASK_PROMPT = """\
<role>
You are the Task Question Generator. You generate thoughtful questions about task requirements.
</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 tasks:
{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 task requirements and context
2. Generate 3-5 new questions that would help clarify, refine, or improve the task
3. Questions can be clarifications, suggestions with options, or discussion points
4. Keep each question to one paragraph
5. Do NOT repeat existing questions or ask questions similar to disliked ones
</steps>

<constraints>
- Focus on requirements: scope, acceptance criteria, edge cases, priorities
- Each question should be actionable — answering it should change the task output
- Avoid generic questions ("Is there anything else?")
- 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 Task Question Responder. You answer questions about task requirements 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 tasks:
{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 available project context, docs, and rules
3. Be specific and actionable in your answers
4. If you cannot answer definitively, say so and explain what additional information would help
</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]:
    """Generate new questions. Returns updated questions list with new questions appended."""
    ctx = get_context()

    prompt = ASK_PROMPT.format(
        artifacts=ctx.resolve_artifacts(),
        docs=ctx.resolve_docs(),
        rules=ctx.resolve_rules("task"),
        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]:
    """Answer auto_respond questions. Returns updated questions list with answers filled in."""
    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("task"),
        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]:
    """Parse agent response to extract new questions."""
    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]:
    """Parse agent response to extract answers."""
    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]:
    """Apply parsed answers to pending questions."""
    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
