"""Local LLM adapter — invokes Ollama or compatible local model via subprocess."""

from __future__ import annotations

import logging
import subprocess
from dataclasses import dataclass, field
from typing import Any

from dpe.adapters.base import ModelAdapter
from dpe.models.adapter import ModelRequest, ModelResult

logger = logging.getLogger(__name__)


@dataclass
class LocalAdapter(ModelAdapter):
    """Adapter for local LLM backends (Ollama, llama.cpp, etc.)."""

    command_template: str = "ollama run llama3 {prompt_file}"
    model_name: str = "llama3"
    timeout_seconds: int = 180
    _call_count: int = field(default=0, init=False)

    def generate(self, request: ModelRequest) -> ModelResult:
        import tempfile
        from pathlib import Path

        self._call_count += 1

        with tempfile.NamedTemporaryFile(
            mode="w", suffix=".txt", delete=False, encoding="utf-8"
        ) as f:
            f.write(request.prompt)
            prompt_file = f.name

        try:
            cmd = self.command_template.replace("{prompt_file}", prompt_file)
            cmd_parts = cmd.split()

            logger.info("Local (%s): executing", self.model_name)
            result = subprocess.run(
                cmd_parts,
                capture_output=True,
                text=True,
                timeout=self.timeout_seconds,
            )

            if result.returncode != 0:
                logger.error("Local error: %s", result.stderr[:500])
                return ModelResult(
                    text=f"[ERROR] {result.stderr[:1000]}",
                    adapter_name="local",
                    role=request.role,
                    throttle_detected=False,
                    metadata={"returncode": result.returncode, "model": self.model_name},
                )

            return ModelResult(
                text=result.stdout,
                adapter_name="local",
                role=request.role,
                throttle_detected=False,
                metadata={"model": self.model_name},
            )
        except subprocess.TimeoutExpired:
            logger.error("Local: timeout after %ds", self.timeout_seconds)
            return ModelResult(
                text="[ERROR] Timeout",
                adapter_name="local",
                role=request.role,
                throttle_detected=False,
                metadata={"timeout": True, "model": self.model_name},
            )
        finally:
            Path(prompt_file).unlink(missing_ok=True)

    def healthcheck(self) -> bool:
        try:
            result = subprocess.run(
                ["ollama", "list"],
                capture_output=True,
                text=True,
                timeout=10,
            )
            return result.returncode == 0
        except (subprocess.TimeoutExpired, FileNotFoundError):
            return False

    def estimate_usage(self, request: ModelRequest) -> dict[str, Any]:
        return {"estimated_tokens": len(request.prompt) // 4, "cost": 0.0}

    def get_usage_snapshot(self) -> dict[str, Any]:
        return {"total_calls": self._call_count, "model": self.model_name}
