"""Synthesize ephemeral guidance for missing sub-agent skills."""

from __future__ import annotations

import json
import re
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any
from uuid import uuid4

from beaver.engine.context import SkillContext
from beaver.engine.providers import ProviderBundle
from beaver.skills.specs.serialization import canonical_hash

if TYPE_CHECKING:
    from beaver.tasks.models import TaskRecord


@dataclass(slots=True)
class EphemeralGuidanceResult:
    guidance_id: str
    guidance_name: str
    skill_context: SkillContext


class EphemeralGuidanceSynthesizer:
    """Create one-run guidance for the current delegated sub-agent."""

    async def synthesize(
        self,
        *,
        task: TaskRecord,
        user_message: str,
        attempt_index: int,
        node_id: str,
        node_task: str,
        skill_query: str,
        required_capabilities: list[str],
        provider_bundle: ProviderBundle,
    ) -> EphemeralGuidanceResult:
        provider = provider_bundle.auxiliary_provider or provider_bundle.main_provider
        runtime = provider_bundle.auxiliary_runtime or provider_bundle.main_runtime
        model = getattr(runtime, "model", None)
        payload = self._fallback_payload(skill_query=skill_query, node_task=node_task, capabilities=required_capabilities)
        try:
            response = await provider.chat(
                messages=[
                    {
                        "role": "system",
                        "content": (
                            "You create concise Beaver ephemeral guidance. Return only JSON with keys: "
                            "guidance_name, description, content, tags."
                        ),
                    },
                    {
                        "role": "user",
                        "content": (
                            "Create procedural guidance for this missing Task sub-agent capability.\n\n"
                            f"Task goal:\n{task.goal}\n\n"
                            f"Current user request:\n{user_message}\n\n"
                            f"Node id: {node_id}\n"
                            f"Node task:\n{node_task}\n\n"
                            f"Skill query:\n{skill_query}\n"
                            f"Required capabilities: {required_capabilities}\n\n"
                            "The content must be actionable guidance for a temporary sub-agent. "
                            "Do not include implementation claims, review metadata, or publish metadata."
                        ),
                    },
                ],
                tools=None,
                model=model,
                max_tokens=4096,
                temperature=0,
            )
            payload = self._parse_payload(response.content or "") or payload
        except Exception:
            payload = payload

        guidance_name = _slug(str(payload.get("guidance_name") or payload.get("skill_name") or skill_query or node_id))
        guidance_id = f"eg_{uuid4().hex}"
        content = str(payload.get("content") or "").strip()
        if not content:
            content = str(self._fallback_payload(skill_query=skill_query, node_task=node_task, capabilities=required_capabilities)["content"])
        context = SkillContext(
            name=f"ephemeral:{guidance_name}",
            content=content,
            version=f"ephemeral:{guidance_id}",
            content_hash=canonical_hash(content),
            activation_reason="ephemeral_guidance",
            tool_hints=[],
        )
        return EphemeralGuidanceResult(
            guidance_id=guidance_id,
            guidance_name=guidance_name,
            skill_context=context,
        )

    @staticmethod
    def _parse_payload(text: str) -> dict[str, Any] | None:
        cleaned = text.strip()
        if cleaned.startswith("```"):
            lines = cleaned.splitlines()
            if len(lines) >= 3 and lines[0].startswith("```") and lines[-1].startswith("```"):
                cleaned = "\n".join(lines[1:-1]).strip()
                if cleaned.lower().startswith("json"):
                    cleaned = cleaned[4:].strip()
        start = cleaned.find("{")
        end = cleaned.rfind("}")
        if start >= 0 and end >= start:
            cleaned = cleaned[start : end + 1]
        try:
            payload = json.loads(cleaned)
        except json.JSONDecodeError:
            return None
        return payload if isinstance(payload, dict) else None

    @staticmethod
    def _fallback_payload(*, skill_query: str, node_task: str, capabilities: list[str]) -> dict[str, Any]:
        title = skill_query or node_task or "task subagent guidance"
        capability_lines = "\n".join(f"- {item}" for item in capabilities) or "- Follow the node task precisely."
        return {
            "guidance_name": _slug(title),
            "description": f"Draft guidance for {title}.",
            "tags": ["generated", "task-sub-agent"],
            "content": (
                f"# {title}\n\n"
                "Use this draft guidance only for the current delegated sub-task.\n\n"
                "## Objective\n"
                f"{node_task or title}\n\n"
                "## Capabilities to apply\n"
                f"{capability_lines}\n\n"
                "## Output\n"
                "Return concise evidence, decisions, and unresolved risks for the main Agent to synthesize."
            ),
        }


def _slug(value: str) -> str:
    cleaned = re.sub(r"[^a-zA-Z0-9]+", "-", value.strip().lower()).strip("-")
    return cleaned[:64].strip("-") or "generated-task-subagent-guidance"


MissingSkillDraftResult = EphemeralGuidanceResult
MissingSkillSynthesizer = EphemeralGuidanceSynthesizer
