from __future__ import annotations

import logging
import time
from typing import Any

import httpx

from app.core.ai.domain.models import (
    AiModelSpec,
    AiProviderType,
    AiResponse,
    AiTextRequest,
    AiVisionRequest,
)

logger = logging.getLogger("dscons.ai.adapter.lmstudio")


class LmStudioAdapter:
    """Offline On-Premise Adapter for Local LM Studio server."""

    def __init__(
        self,
        base_url: str = "http://127.0.0.1:1234/v1",
        api_key: str = "lm-studio",
        timeout_seconds: float = 20.0,
    ) -> None:
        self._base_url = base_url.rstrip("/")
        self._api_key = api_key
        self._timeout = timeout_seconds

    async def generate_text(
        self, request: AiTextRequest, spec: AiModelSpec
    ) -> AiResponse:
        """Executes text generation via Local LM Studio."""
        t0 = time.perf_counter()
        messages: list[dict[str, Any]] = []

        if request.system_prompt:
            messages.append({"role": "system", "content": request.system_prompt})

        if request.messages:
            messages.extend(request.messages)
        elif request.prompt:
            messages.append({"role": "user", "content": request.prompt})

        payload = {
            "model": spec.provider_model_id,
            "messages": messages,
            "temperature": request.temperature,
            "max_tokens": request.max_tokens or spec.max_output_tokens,
        }

        async with httpx.AsyncClient(timeout=self._timeout) as client:
            res = await client.post(
                f"{self._base_url}/chat/completions",
                json=payload,
                headers={"Authorization": f"Bearer {self._api_key}"},
            )
            res.raise_for_status()
            data = res.json()

        choice = data["choices"][0]
        content = choice.get("message", {}).get("content") or ""

        latency = (time.perf_counter() - t0) * 1000.0
        return AiResponse(
            content=content,
            model_used=spec.canonical_id,
            provider_used=AiProviderType.LMSTUDIO,
            latency_ms=latency,
        )

    async def analyze_vision(
        self, request: AiVisionRequest, spec: AiModelSpec
    ) -> AiResponse:
        """LM Studio currently does not support heavy vision models locally in DSCons."""
        raise NotImplementedError("Local LM Studio does not support vision OCR in DSCons configuration.")
