"""LLM-powered summarizer: generates higher-quality summaries using local or cloud LLMs."""

import urllib.request
from typing import Optional
from memotrail.utils import config, get_logger

logger = get_logger("memotrail.extractors.llm_summarizer")

_SUMMARIZE_PROMPT = """Summarize this AI coding session in 2-3 sentences. Focus on:
- What was the user's goal
- What was accomplished
- Key decisions or changes made

Session messages:
{messages}

Summary:"""


class LLMSummarizer:
    """Generate session summaries using LLM backends.

    Supports Ollama (local), OpenAI, and Anthropic APIs.
    Falls back gracefully if the backend is unavailable.
    """

    def __init__(
        self,
        backend: str | None = None,
        model: str | None = None,
    ):
        self.backend = backend or config.llm_summarizer_backend
        self.model = model or config.llm_summarizer_model or self._default_model()

    def _default_model(self) -> str:
        """Select default model per backend."""
        defaults = {
            "ollama": "llama3.2",
            "openai": "gpt-4o-mini",
            "anthropic": "claude-haiku-4-5-20251001",
        }
        return defaults.get(self.backend, "llama3.2")

    def summarize(self, messages: list[dict], max_chars: int = 500) -> Optional[str]:
        """Summarize a session using the configured LLM backend.

        Args:
            messages: List of {"role": str, "content": str}
            max_chars: Max characters for the summary

        Returns:
            Summary string or None if generation fails
        """
        # Format messages for prompt
        formatted = []
        for msg in messages[:30]:  # Limit input size
            role = msg.get("role", "unknown")
            content = msg.get("content", "")[:500]
            formatted.append(f"[{role}]: {content}")
        messages_text = "\n".join(formatted)

        prompt = _SUMMARIZE_PROMPT.format(messages=messages_text)

        try:
            if self.backend == "ollama":
                return self._call_ollama(prompt, max_chars)
            elif self.backend == "openai":
                return self._call_openai(prompt, max_chars)
            elif self.backend == "anthropic":
                return self._call_anthropic(prompt, max_chars)
            else:
                logger.warning(f"Unknown LLM backend: {self.backend}")
                return None
        except Exception as e:
            logger.warning(f"LLM summarization failed ({self.backend}): {e}")
            return None

    def _call_ollama(self, prompt: str, max_chars: int) -> Optional[str]:
        """Call local Ollama API."""
        import json

        payload = json.dumps({
            "model": self.model,
            "prompt": prompt,
            "stream": False,
            "options": {"num_predict": max_chars},
        }).encode()

        req = urllib.request.Request(
            "http://localhost:11434/api/generate",
            data=payload,
            headers={"Content-Type": "application/json"},
        )

        with urllib.request.urlopen(req, timeout=30) as resp:
            data = json.loads(resp.read())
            return data.get("response", "").strip()[:max_chars] or None

    def _call_openai(self, prompt: str, max_chars: int) -> Optional[str]:
        """Call OpenAI API."""
        import os
        import json

        api_key = os.environ.get("OPENAI_API_KEY")
        if not api_key:
            logger.warning("OPENAI_API_KEY not set")
            return None

        payload = json.dumps({
            "model": self.model,
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": max_chars // 3,
        }).encode()

        req = urllib.request.Request(
            "https://api.openai.com/v1/chat/completions",
            data=payload,
            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {api_key}",
            },
        )

        with urllib.request.urlopen(req, timeout=30) as resp:
            data = json.loads(resp.read())
            return data["choices"][0]["message"]["content"].strip()[:max_chars] or None

    def _call_anthropic(self, prompt: str, max_chars: int) -> Optional[str]:
        """Call Anthropic API."""
        import os
        import json

        api_key = os.environ.get("ANTHROPIC_API_KEY")
        if not api_key:
            logger.warning("ANTHROPIC_API_KEY not set")
            return None

        payload = json.dumps({
            "model": self.model,
            "max_tokens": max_chars // 3,
            "messages": [{"role": "user", "content": prompt}],
        }).encode()

        req = urllib.request.Request(
            "https://api.anthropic.com/v1/messages",
            data=payload,
            headers={
                "Content-Type": "application/json",
                "x-api-key": api_key,
                "anthropic-version": "2023-06-01",
            },
        )

        with urllib.request.urlopen(req, timeout=30) as resp:
            data = json.loads(resp.read())
            return data["content"][0]["text"].strip()[:max_chars] or None
