"""
Script Generator for Intent-Driven Script Flow.
[AC-IDS-04] Flexible mode script generation with LLM.
"""

import asyncio
import logging
from typing import Any

logger = logging.getLogger(__name__)


class ScriptGenerator:
    """
    [AC-IDS-04] Flexible mode script generator.
    Generates dynamic scripts based on intent, constraints, and conversation history.
    """

    DEFAULT_TIMEOUT = 5.0
    MAX_SCRIPT_LENGTH = 200

    def __init__(self, llm_client: Any = None):
        """
        Initialize ScriptGenerator.

        Args:
            llm_client: LLM client for text generation (optional, for testing)
        """
        self._llm_client = llm_client

    async def generate(
        self,
        intent: str,
        intent_description: str | None,
        constraints: list[str] | None,
        context: dict[str, Any] | None,
        history: list[dict[str, str]] | None,
        fallback: str,
    ) -> str:
        """
        [AC-IDS-04] Generate flexible script based on intent and context.

        Args:
            intent: Step intent (e.g., "获取用户姓名")
            intent_description: Detailed intent description
            constraints: Script constraints (e.g., ["必须礼貌", "语气自然"])
            context: Session context with collected inputs
            history: Conversation history (last N turns)
            fallback: Fallback script when generation fails

        Returns:
            Generated script text or fallback
        """
        try:
            prompt = self._build_prompt(
                intent=intent,
                intent_description=intent_description,
                constraints=constraints,
                context=context,
                history=history,
            )

            if self._llm_client:
                messages = [{"role": "user", "content": prompt}]
                response = await asyncio.wait_for(
                    self._llm_client.generate(messages),
                    timeout=self.DEFAULT_TIMEOUT,
                )
                generated = response.content.strip() if hasattr(response, 'content') else str(response).strip()

                if len(generated) > self.MAX_SCRIPT_LENGTH * 2:
                    generated = generated[:self.MAX_SCRIPT_LENGTH * 2]

                logger.info(
                    f"[AC-IDS-04] Generated flexible script: "
                    f"intent={intent}, length={len(generated)}"
                )
                return generated
            else:
                logger.warning(
                    f"[AC-IDS-05] No LLM client configured, using fallback"
                )
                return fallback

        except asyncio.TimeoutError:
            logger.warning(
                f"[AC-IDS-05] Script generation timeout, use fallback: "
                f"intent={intent}"
            )
            return fallback

        except Exception as e:
            logger.error(
                f"[AC-IDS-05] Script generation failed: {e}, use fallback"
            )
            return fallback

    def _build_prompt(
        self,
        intent: str,
        intent_description: str | None,
        constraints: list[str] | None,
        context: dict[str, Any] | None,
        history: list[dict[str, str]] | None,
    ) -> str:
        """
        [AC-IDS-04] Build LLM prompt for script generation.
        """
        prompt_parts = [
            "你是一个客服对话系统，当前需要执行以下步骤：",
            "",
            f"【步骤目标】{intent}",
        ]

        if intent_description:
            prompt_parts.append(f"【详细说明】{intent_description}")

        if constraints:
            prompt_parts.append("")
            prompt_parts.append("【约束条件】")
            for c in constraints:
                prompt_parts.append(f"- {c}")

        if history:
            prompt_parts.append("")
            prompt_parts.append("【对话历史】")
            for msg in history[-3:]:
                role = "用户" if msg.get("role") == "user" else "客服"
                content = msg.get("content", "")
                prompt_parts.append(f"{role}: {content}")

        if context and context.get("inputs"):
            prompt_parts.append("")
            prompt_parts.append("【已收集信息】")
            for inp in context["inputs"]:
                if isinstance(inp, dict):
                    step = inp.get("step", "?")
                    input_text = inp.get("input", "")
                    prompt_parts.append(f"- 步骤{step}: {input_text}")
                else:
                    prompt_parts.append(f"- {inp}")

        prompt_parts.extend([
            "",
            f"请生成一句符合目标和约束的话术（不超过{self.MAX_SCRIPT_LENGTH}字）。",
            "只返回话术内容，不要解释。",
        ])

        return "\n".join(prompt_parts)
