"""
Character Voice: All messages come from the bot's personality.

No system messages, no robotic status dumps. Everything sounds
like the character is talking naturally.
"""

import random
from typing import Any

from loguru import logger


class CharacterVoice:
    """
    Transforms raw information into character voice.
    Every message the user sees passes through this layer.
    """
    
    # Templates for fast-path messages (no LLM call needed)
    PROGRESS_TEMPLATES = [
        "Still at it — {summary}",
        "Making progress — {summary}",
        "Chugging along — {summary}",
        "Quick update — {summary}",
        "Working on it — {summary}",
    ]
    
    COMPLETION_TEMPLATES = [
        "Done! {summary}",
        "Finished up — {summary}",
        "All set! {summary}",
        "Wrapped that up — {summary}",
        "Got it done — {summary}",
    ]
    
    FAILURE_TEMPLATES = [
        "Hit a snag — {summary}",
        "Ran into an issue — {summary}",
        "Something went wrong — {summary}",
        "Couldn't finish that — {summary}",
    ]
    
    def __init__(self, persona_prompt: str, llm_provider: Any):
        self.persona = persona_prompt
        self.llm = llm_provider
    
    async def speak(
        self,
        content: str,
        context: str | None = None,
        must_include: list[str] | None = None,
        use_llm: bool = True,
    ) -> str:
        """
        Transform content into character voice.
        
        Args:
            content: The raw information to convey
            context: Optional context (e.g., "progress update", "task completion")
            must_include: Strings that MUST appear in output (references, etc.)
            use_llm: Whether to use LLM for generation (False = template only)
        
        Returns:
            The message in character voice
        """
        if use_llm:
            try:
                result = await self._speak_with_llm(content, context, must_include)
                return result
            except Exception as e:
                logger.warning(f"Voice LLM failed, using fallback: {e}")
        
        # Fallback: return content with must_include appended
        result = content
        if must_include:
            missing = [s for s in must_include if s not in result]
            if missing:
                result = f"{result} {' '.join(missing)}"
        return result
    
    async def _speak_with_llm(
        self,
        content: str,
        context: str | None,
        must_include: list[str] | None,
    ) -> str:
        """Use LLM to generate in-character message."""
        prompt = f"""You are speaking as this character:

{self.persona}

Convey the following information naturally, in character, in 1-2 sentences:

{content}

Context: {context or 'general message'}

Rules:
- Stay completely in character
- Be concise (1-2 sentences max)
- Sound natural and conversational, not robotic
- Don't mention being an AI or break character
- Don't use phrases like "I've completed" or "Task completed" - be more natural"""

        if must_include:
            prompt += f"\n- You MUST include these exact strings somewhere in your response: {must_include}"
        
        response = await self.llm.chat(
            messages=[{"role": "system", "content": prompt}],
            tools=None,
            max_tokens=150,
        )
        
        result = (response.content or "").strip()
        
        # Verify must_include strings are present
        if must_include:
            for s in must_include:
                if s not in result:
                    result = f"{result} {s}"
        
        return result
    
    async def speak_task_started(self, label: str, reference: str) -> str:
        """Generate in-character task start acknowledgment."""
        return await self.speak(
            content=f"Starting work on: {label}",
            context="acknowledging new task, be enthusiastic but brief",
            must_include=[reference],
        )
    
    async def speak_progress(self, summaries: list[str]) -> str:
        """Generate in-character progress update (uses template for speed)."""
        NUMBER_EMOJI = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"]
        
        if len(summaries) == 1:
            summary = summaries[0]
        else:
            # Format with numbered emoji and line breaks
            lines = []
            for i, s in enumerate(summaries):
                emoji = NUMBER_EMOJI[i] if i < len(NUMBER_EMOJI) else f"{i+1}."
                lines.append(f"{emoji} {s}")
            summary = "\n".join(lines)
        
        template = random.choice(self.PROGRESS_TEMPLATES)
        return template.format(summary=summary)
    
    async def speak_completion(
        self,
        label: str,
        result: str,
        completion_reference: str,
    ) -> str:
        """Generate in-character completion message."""
        result_preview = result[:400] if result else "done"
        
        return await self.speak(
            content=f"Finished {label}. Result: {result_preview}",
            context="task completion, be satisfied but not over the top",
            must_include=[completion_reference],
        )
    
    async def speak_failure(
        self,
        label: str,
        error: str,
        completion_reference: str,
    ) -> str:
        """Generate in-character failure message."""
        return await self.speak(
            content=f"Failed to complete {label}: {error}",
            context="task failure, be honest and helpful, suggest what might help",
            must_include=[completion_reference],
        )
    
    async def speak_status(self, status_info: str) -> str:
        """Generate in-character status response."""
        return await self.speak(
            content=status_info,
            context="responding to status request, be informative but conversational",
        )
    
    async def speak_no_tasks(self) -> str:
        """Generate in-character response when no tasks are running."""
        return await self.speak(
            content="No tasks currently running or recently completed",
            context="responding to status check with nothing to report, be helpful",
        )
