"""
RAGSentinel RAGAS Metrics Module.

This module provides quality evaluation metrics for RAG applications using RAGAS:
- Faithfulness (How factually accurate is the answer based on context)
- Answer Relevancy (How relevant is the answer to the question)
- Context Precision (How precise is the retrieved context)
- Answer Correctness (How correct is the answer compared to ground truth)
"""

from datasets import Dataset
from ragas import evaluate
from ragas.run_config import RunConfig
from ragas.metrics import (
    Faithfulness,
    AnswerRelevancy,
    ContextPrecision,
    AnswerCorrectness,
)


# =============================================================================
# Constants
# =============================================================================

CATEGORY_SIMPLE = "simple"

# Available RAGAS metrics
AVAILABLE_METRICS = {
    "Faithfulness": Faithfulness,
    "AnswerRelevancy": AnswerRelevancy,
    "ContextPrecision": ContextPrecision,
    "AnswerCorrectness": AnswerCorrectness,
}


# =============================================================================
# Evaluation Function
# =============================================================================

def run_ragas_evaluation(responses_df, llm, embeddings):
    """
    Run RAGAS quality evaluation on collected responses.

    Uses ALL available RAGAS metrics by default:
    - Faithfulness
    - AnswerRelevancy
    - ContextPrecision
    - AnswerCorrectness

    Args:
        responses_df: DataFrame with columns: query, answer, contexts, ground_truth, response_time_ms
        llm: LangChain LLM instance
        embeddings: LangChain embeddings instance

    Returns:
        DataFrame with evaluation results including all scores
    """
    # Prepare data for RAGAS
    ragas_data = {
        "question": [],
        "answer": [],
        "contexts": [],
        "ground_truth": []
    }

    for _, row in responses_df.iterrows():
        contexts = row.get("contexts", [])
        if not isinstance(contexts, list):
            contexts = [str(contexts)]
        contexts = [str(c) for c in contexts if c and str(c).strip()]
        if not contexts:
            contexts = ["No context available."]

        ragas_data["question"].append(str(row["query"]))
        ragas_data["answer"].append(str(row["answer"]))
        ragas_data["contexts"].append(contexts)
        ragas_data["ground_truth"].append(str(row["ground_truth"]))

    dataset = Dataset.from_dict(ragas_data)

    # Use ALL available metrics
    metrics = [metric_class() for metric_class in AVAILABLE_METRICS.values()]

    # Run evaluation
    run_config = RunConfig(timeout=300, max_retries=3, max_wait=600)

    ragas_result = evaluate(
        dataset,
        metrics=metrics,
        llm=llm,
        embeddings=embeddings,
        batch_size=2,
        run_config=run_config,
        raise_exceptions=False
    )

    # Convert to DataFrame and merge with original data
    scores_df = ragas_result.to_pandas()

    # Add response time from original data
    scores_df["response_time_ms"] = responses_df["response_time_ms"].values

    return scores_df

