from llama_index.llms.openai_like import OpenAILike
from langchain_openai import OpenAIEmbeddings

from ragas.llms import LlamaIndexLLMWrapper, LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper

from ragas import EvaluationDataset, evaluate
from dotenv import load_dotenv
import os


from ragas.metrics import (
    ResponseRelevancy,
    ContextUtilization,
    AnswerAccuracy,
    NonLLMStringSimilarity
)

load_dotenv()

llm = OpenAILike(
    model=os.getenv('LLM_MODEL'),
    api_base=os.getenv('LLM_API_BASE'),
    api_key=os.getenv('LLM_API_KEY'),                   
    is_chat_model=True,
)

evaluator_llm = LlamaIndexLLMWrapper(llm)


evaluator_embeddings = LangchainEmbeddingsWrapper(
    OpenAIEmbeddings(
        model=os.getenv('OPENAI_MODEL'),
        base_url=os.getenv('OPENAI_BASE_URL')
))

def setup_all_metrics():
    """Настройка всех доступных метрик ragas"""    
    reference_free_metrics = [
        ResponseRelevancy(embeddings=evaluator_embeddings, llm=evaluator_llm),
        ContextUtilization(llm=evaluator_llm),
    ]
    
    reference_based_metrics = [
        AnswerAccuracy(llm=evaluator_llm),
        NonLLMStringSimilarity(),
    ]
    
    
    return reference_free_metrics, reference_based_metrics

def comprehensive_evaluation(data_samples):
    """Комплексная оценка с всеми метриками"""
    
    # Создание dataset
    dataset = EvaluationDataset.from_list(data_samples)
    
    # Получение метрик
    ref_free, ref_based = setup_all_metrics()
    
    # Выбор метрик в зависимости от наличия reference
    metrics_to_use = ref_free
    
    has_reference = any('reference' in sample for sample in data_samples)
    if has_reference:
        metrics_to_use.extend(ref_based)
    else:
        print("Reference данные отсутствуют, используем только reference-free метрики")

    print(f"Запуск оценки с {len(metrics_to_use)} метриками...")
    
    result = evaluate(
        dataset=dataset,
        metrics=metrics_to_use,
        raise_exceptions=False
    )
    
    result_dict = {}

    result_dict['response_relevancy'] = float(result['answer_relevancy'][0])
    result_dict['context_utilization'] = float(result['context_utilization'][0])
    result_dict['answer_accuracy'] = float(result['nv_accuracy'][0])
    result_dict['non_llm_string_similarity'] = float(result['non_llm_string_similarity'][0])

    return result_dict