"""Built-in evaluation rubrics and YAML rubric loader."""

from __future__ import annotations

import logging
from pathlib import Path

import yaml

from sage_evaluator.models import EvaluationRubric, RubricDimension

logger = logging.getLogger(__name__)

# ── Built-in rubrics ────────────────────────────────────────────────────────

DEFAULT_RUBRIC = EvaluationRubric(
    name="default",
    description="General-purpose evaluation rubric for agent output quality",
    dimensions=[
        RubricDimension(
            name="relevance",
            description="How well the output addresses the user's intent and requirements",
            weight=2.0,
        ),
        RubricDimension(
            name="accuracy",
            description="Factual correctness and technical accuracy of the output",
            weight=2.0,
        ),
        RubricDimension(
            name="completeness",
            description="Whether the output covers all aspects of the request",
            weight=1.5,
        ),
        RubricDimension(
            name="clarity",
            description="How clear, well-structured, and easy to understand the output is",
            weight=1.0,
        ),
        RubricDimension(
            name="efficiency",
            description="Whether the agent used tools appropriately and avoided unnecessary steps",
            weight=1.0,
        ),
    ],
)

CODE_GENERATION_RUBRIC = EvaluationRubric(
    name="code_generation",
    description="Rubric for evaluating code generation tasks",
    dimensions=[
        RubricDimension(
            name="correctness",
            description="Whether the generated code is functionally correct and handles edge cases",
            weight=2.5,
        ),
        RubricDimension(
            name="completeness",
            description="Whether all requested functionality is implemented",
            weight=2.0,
        ),
        RubricDimension(
            name="code_quality",
            description="Clean code practices: naming, structure, DRY, appropriate abstractions",
            weight=1.5,
        ),
        RubricDimension(
            name="security",
            description="Whether the code avoids common vulnerabilities (injection, XSS, etc.)",
            weight=1.5,
        ),
        RubricDimension(
            name="documentation",
            description="Appropriate comments, docstrings, and explanation of approach",
            weight=1.0,
        ),
    ],
)

QA_RUBRIC = EvaluationRubric(
    name="qa",
    description="Rubric for evaluating question-answering tasks",
    dimensions=[
        RubricDimension(
            name="accuracy",
            description="Factual correctness of the answer",
            weight=2.5,
        ),
        RubricDimension(
            name="relevance",
            description="How directly the answer addresses the question asked",
            weight=2.0,
        ),
        RubricDimension(
            name="depth",
            description="Level of detail and thoroughness in the explanation",
            weight=1.5,
        ),
        RubricDimension(
            name="source_usage",
            description="Appropriate use of tools and references to support the answer",
            weight=1.0,
        ),
        RubricDimension(
            name="conciseness",
            description="Avoids unnecessary verbosity while remaining complete",
            weight=1.0,
        ),
    ],
)

BUILTIN_RUBRICS: dict[str, EvaluationRubric] = {
    "default": DEFAULT_RUBRIC,
    "code_generation": CODE_GENERATION_RUBRIC,
    "qa": QA_RUBRIC,
}


def load_rubric(name_or_path: str) -> EvaluationRubric:
    """Load a rubric by built-in name or YAML file path.

    Args:
        name_or_path: Either a built-in rubric name ("default", "code_generation", "qa")
                      or a path to a YAML rubric file.

    Returns:
        The loaded EvaluationRubric.

    Raises:
        FileNotFoundError: If the YAML path doesn't exist.
        ValueError: If the rubric format is invalid.
    """
    if name_or_path in BUILTIN_RUBRICS:
        logger.info("Using built-in rubric %r", name_or_path)
        return BUILTIN_RUBRICS[name_or_path]

    path = Path(name_or_path)
    if not path.exists():
        raise FileNotFoundError(f"Rubric file not found: {path}")

    logger.info("Loading rubric from file %s", path)
    with open(path) as f:
        data = yaml.safe_load(f)

    if not isinstance(data, dict):
        raise ValueError(f"Invalid rubric format: expected mapping, got {type(data).__name__}")

    if "name" not in data:
        data["name"] = path.stem

    dimensions = []
    for dim_data in data.get("dimensions", []):
        dimensions.append(RubricDimension(**dim_data))

    return EvaluationRubric(
        name=data["name"],
        description=data.get("description", ""),
        dimensions=dimensions,
    )
