"""Сервис для генерации текста с LLM"""
import logging
import os
from typing import Dict, List, Tuple, Optional

import requests

from data.processors import create_summarize_text_prompt
from utils.metrics import request_metrics

logger = logging.getLogger(__name__)

DEFAULT_GENERATION_TEMPERATURE = 0.3


class LLMService:
    """Сервис для генерации текста с LLM"""

    def __init__(self) -> None:
        """Инициализирует LLM сервис"""
        self.api_url = os.getenv('URL_LLM')
        self.api_key = os.getenv('LLM_API_KEY')
        if not self.api_url or not self.api_key:
            logger.warning('URL_LLM or LLM_API_KEY environment variable not set')

    def generate_response(
        self,
        messages: List[Dict[str, str]],
        model: str,
        temperature: float = 1.0,
    ) -> Tuple[str, Dict[str, float]]:
        """Генерирует ответ с LLM через API.
        
        Args:
            messages: Список сообщений в диалоге формата [{role: "user|assistant|system", content: "текст"}]
            model: Название модели для генерации
            temperature: Параметр температуры для контроля случайности генерации
            
        Returns:
            Tuple (ответ_модели, статистика_использования_токенов)
        """
        if not self.api_url or not self.api_key:
            raise ValueError('URL_LLM or LLM_API_KEY environment variable not set')

        json_data = {'model': model, 'messages': messages, 'temperature': temperature}
        headers = {'Authorization': f'Bearer {self.api_key}', 'Content-Type': 'application/json'}

        try:
            response = requests.post(self.api_url, headers=headers, json=json_data)
            if response.status_code == requests.codes.ok:
                response_data = response.json()
                answer = response_data['choices'][0]['message']['content']
                usage = response_data['usage']
                return answer, usage
            else:
                logger.error('Error generating response: %s', response.json())
                raise Exception(f'Error generating response: {response.status_code}')
        except requests.exceptions.JSONDecodeError as e:
            logger.error('Failed to parse JSON. Response text: %s', response.text[:200])
            raise ValueError(f'Invalid JSON from API: {str(e)}')
        except Exception as error:
            logger.error('Exception during LLM response generation: %s', str(error))
            raise Exception(f'LLM generation failed: {str(error)}')

    def generate_and_validate(
        self,
        messages: List[Dict[str, str]],
        model_name: str,
        reference_answer: str,
        user_input: str,
        documents: List[str],
        num_generations: int,
    ) -> Tuple[List[Dict[str, float]], List[str], List[Dict[str, float]]]:
        """Генерирует ответы несколько раз и рассчитывает метрики качества.
        
        Выполняет указанное количество генераций и для каждой рассчитывает
        метрики качества относительно эталонного ответа.
        
        Returns:
            - список метрик для каждой генерации
            - список сгенерированных ответов
            - список использованных токенов для каждой генерации
        """
        metrics_list = []
        generated_answers = []
        tokens_list = []

        for _ in range(num_generations):
            answer, usage = self.generate_response(messages, model_name, temperature=DEFAULT_GENERATION_TEMPERATURE)

            in_tokens, out_tokens = usage.get('prompt_tokens'), usage.get('completion_tokens')
            tokens_list.append({'in_tokens': in_tokens, 'out_tokens': out_tokens})

            if reference_answer:
                metrics = request_metrics(reference=reference_answer, 
                                        hypothesis=answer, 
                                        user_input=user_input, 
                                        documents=documents)
            else:
                metrics = {}

            metrics_list.append(metrics)
            generated_answers.append(answer)

        return metrics_list, generated_answers, tokens_list

    def summarize(self, text: str, model: str) -> str:
        """Создает саммари текста.
        
        Обращается к той же LLM модели по API
        Формирует специальный промпт для суммаризации через data.create_summarize_text_prompt
        """

        summary_messages = create_summarize_text_prompt(text)
        summary, _ = self.generate_response(summary_messages, model)
        return summary
