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

ASK_PROMPT = """\
<role>
You are the Plan Question Generator. You generate thoughtful questions about the implementation plan and architecture.
</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 plans:
{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 plan, task requirements, and project context
2. Generate 3-5 new questions about architectural decisions, implementation strategy, trade-offs, or technical approach
3. Questions can be clarifications, alternative approaches, risk assessments, or dependency concerns
4. Keep each question to one paragraph
5. Do NOT repeat existing questions or ask questions similar to disliked ones
</steps>

<constraints>
- Focus on architecture: component boundaries, data flow, API design, patterns, trade-offs
- Consider scalability, maintainability, and consistency with existing codebase
- Each question should be actionable — answering it should change the plan 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 Plan Question Responder. You answer questions about architectural decisions and implementation strategy 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 plans:
{rules}
</quick-start>

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

<steps>
1. Read all context carefully
2. Answer each question based on available project context, existing architecture, and best practices
3. Be specific and actionable — recommend concrete approaches over vague suggestions
4. If trade-offs exist, explain them clearly
</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 about the plan. Returns updated list."""
    ctx = get_context()
    prompt = ASK_PROMPT.format(
        artifacts=ctx.resolve_artifacts(),
        docs=ctx.resolve_docs(),
        rules=ctx.resolve_rules("plan"),
        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 list."""
    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("plan"),
        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
