from __future__ import annotations

import logging

from app.core.agent.utils.llm.prompt_loader import PromptLoader
from app.core.shared.gigachat.client import GigaChatClient
from app.infra.observability.module_trace import ModuleTrace

LOGGER = logging.getLogger(__name__)


def _truncate_for_log(text: str, max_chars: int = 1500) -> str:
    value = (text or "").replace("\n", "\\n").strip()
    if len(value) <= max_chars:
        return value
    return value[:max_chars].rstrip() + "...[truncated]"


class AgentLlmService:
    def __init__(self, client: GigaChatClient, prompts: PromptLoader) -> None:
        self._client = client
        self._prompts = prompts

    def build_request(self, prompt_name: str, user_input: str, *, log_context: str | None = None) -> dict[str, str]:
        system_prompt = self._prompts.load(prompt_name) or "You are a helpful assistant."
        return {
            "prompt_name": prompt_name,
            "system_prompt": system_prompt,
            "user_prompt": user_input,
            "log_context": log_context or "",
        }

    def generate(
        self,
        prompt_name: str,
        user_input: str,
        *,
        log_context: str | None = None,
        trace: ModuleTrace | None = None,
    ) -> str:
        request = self.build_request(prompt_name, user_input, log_context=log_context)
        if trace is not None:
            trace.log("request", request)
        if log_context:
            LOGGER.warning(
                "graph llm input: context=%s prompt=%s user_input=%s",
                log_context,
                prompt_name,
                _truncate_for_log(user_input),
            )
        output = self._client.complete(
            system_prompt=request["system_prompt"],
            user_prompt=request["user_prompt"],
        )
        if trace is not None:
            trace.log("response", {"text": output})
        if log_context:
            LOGGER.warning(
                "graph llm output: context=%s prompt=%s output=%s",
                log_context,
                prompt_name,
                _truncate_for_log(output),
            )
        return output
