from __future__ import annotations

import os
from unittest.mock import patch

from evals.reviewer import run_eval
from evals.reviewer.run_eval import (
    DEFAULT_LANGSMITH_PROJECT,
    _apply_config_to_env,
    _apply_langsmith_project,
    _coerce_config,
    _load_env_config,
    _resolve_config,
)


def test_reviewer_eval_config_coerces_known_values() -> None:
    config = _coerce_config(
        {
            "dataset_name": "dataset",
            "experiment_prefix": "experiment",
            "max_concurrency": 2,
            "langgraph_url": "https://example.test",
            "assistant_id": "reviewer",
            "model_id": "anthropic:claude-opus-4-8",
            "reasoning_effort": "high",
            "score_mode": "surfaced_findings",
            "severity_threshold": "medium",
            "cap": 4,
            "unknown": "ignored",
        }
    )

    assert config == {
        "dataset_name": "dataset",
        "experiment_prefix": "experiment",
        "max_concurrency": 2,
        "langgraph_url": "https://example.test",
        "assistant_id": "reviewer",
        "model_id": "anthropic:claude-opus-4-8",
        "reasoning_effort": "high",
        "score_mode": "surfaced_findings",
        "severity_threshold": "medium",
        "cap": 4,
    }


def test_reviewer_eval_config_sets_target_env() -> None:
    with patch.dict(os.environ, {}, clear=True):
        _apply_config_to_env(
            {
                "dataset_name": "dataset",
                "experiment_prefix": "experiment",
                "max_concurrency": 2,
                "langgraph_url": "https://example.test",
                "langsmith_project": "project",
                "assistant_id": "reviewer",
                "model_id": "anthropic:claude-opus-4-8",
                "reasoning_effort": "high",
                "score_mode": "surfaced_findings",
                "severity_threshold": "high",
                "cap": 3,
            }
        )

        assert os.environ["REVIEWER_EVAL_DATASET_NAME"] == "dataset"
        assert os.environ["REVIEWER_EVAL_EXPERIMENT_PREFIX"] == "experiment"
        assert os.environ["REVIEWER_EVAL_MAX_CONCURRENCY"] == "2"
        assert os.environ["LANGGRAPH_URL"] == "https://example.test"
        assert os.environ["LANGSMITH_PROJECT"] == "project"
        assert os.environ["LANGCHAIN_PROJECT"] == "project"
        assert os.environ["REVIEWER_ASSISTANT_ID"] == "reviewer"
        assert os.environ["REVIEWER_EVAL_MODEL_ID"] == "anthropic:claude-opus-4-8"
        assert os.environ["REVIEWER_EVAL_REASONING_EFFORT"] == "high"
        assert os.environ["REVIEWER_EVAL_SCORE_MODE"] == "surfaced_findings"
        assert os.environ["REVIEWER_EVAL_SEVERITY_THRESHOLD"] == "high"
        assert os.environ["REVIEWER_EVAL_CAP"] == "3"


def test_reviewer_eval_config_coerces_langsmith_project() -> None:
    config = _coerce_config({"langsmith_project": "open-swe-evals"})
    assert config == {"langsmith_project": "open-swe-evals"}


def test_apply_langsmith_project_uses_config_default() -> None:
    with patch.dict(os.environ, {}, clear=True):
        _apply_langsmith_project("my-eval-project")
        assert os.environ["LANGSMITH_PROJECT"] == "my-eval-project"
        assert os.environ["LANGCHAIN_PROJECT"] == "my-eval-project"
        assert os.environ["LANGSMITH_TRACING"] == "true"


def test_apply_langsmith_project_falls_back_to_default() -> None:
    with patch.dict(os.environ, {}, clear=True):
        _apply_langsmith_project(None)
        assert os.environ["LANGSMITH_PROJECT"] == DEFAULT_LANGSMITH_PROJECT


def test_apply_langsmith_project_uses_resolved_config_over_env() -> None:
    with patch.dict(os.environ, {"LANGSMITH_PROJECT": "from-env"}, clear=True):
        _apply_langsmith_project("from-config")
        assert os.environ["LANGSMITH_PROJECT"] == "from-config"
        assert os.environ["LANGCHAIN_PROJECT"] == "from-config"


def test_load_env_config_reads_all_supported_keys() -> None:
    env = {
        "REVIEWER_EVAL_DATASET_NAME": "dataset-env",
        "REVIEWER_EVAL_EXPERIMENT_PREFIX": "experiment-env",
        "REVIEWER_EVAL_MAX_CONCURRENCY": "3",
        "LANGGRAPH_URL": "https://lg.env",
        "LANGSMITH_PROJECT": "project-env",
        "REVIEWER_ASSISTANT_ID": "reviewer-env",
        "REVIEWER_EVAL_MODEL_ID": "openai:gpt-5.5",
        "REVIEWER_EVAL_REASONING_EFFORT": "xhigh",
        "REVIEWER_EVAL_SCORE_MODE": "surfaced_findings",
        "REVIEWER_EVAL_SEVERITY_THRESHOLD": "critical",
        "REVIEWER_EVAL_CAP": "1",
    }

    assert _load_env_config(env) == {
        "dataset_name": "dataset-env",
        "experiment_prefix": "experiment-env",
        "max_concurrency": 3,
        "langgraph_url": "https://lg.env",
        "langsmith_project": "project-env",
        "assistant_id": "reviewer-env",
        "model_id": "openai:gpt-5.5",
        "reasoning_effort": "xhigh",
        "score_mode": "surfaced_findings",
        "severity_threshold": "critical",
        "cap": 1,
    }


def test_resolve_config_prefers_cli_then_env_then_toml() -> None:
    with (
        patch.object(
            run_eval,
            "_load_config",
            return_value={
                "dataset_name": "dataset-config",
                "experiment_prefix": "experiment-config",
                "model_id": "anthropic:claude-opus-4-8",
                "reasoning_effort": "high",
                "langsmith_project": "project-config",
            },
        ),
        patch.dict(
            os.environ,
            {
                "REVIEWER_EVAL_MODEL_ID": "google_genai:gemini-3.5-flash",
                "REVIEWER_EVAL_REASONING_EFFORT": "medium",
                "LANGSMITH_PROJECT": "project-env",
            },
            clear=True,
        ),
    ):
        config = _resolve_config(
            {
                "experiment_prefix": "experiment-cli",
                "model_id": "openai:gpt-5.5",
                "reasoning_effort": "xhigh",
            }
        )

    assert config["dataset_name"] == "dataset-config"
    assert config["experiment_prefix"] == "experiment-cli"
    assert config["model_id"] == "openai:gpt-5.5"
    assert config["reasoning_effort"] == "xhigh"
    assert config["langsmith_project"] == "project-env"
