import pytest

from cascade.evaluations import CascadeEval, CascadeEvalError
import cascade.evaluations as eval_mod


class _FakeResponse:
    def __init__(self, status_code=200, payload=None):
        self.status_code = status_code
        self._payload = payload if payload is not None else {}
        self.content = b"x"
        self.text = str(self._payload)

    def json(self):
        return self._payload


def test_create_task_rejects_invalid_mode():
    c = CascadeEval(endpoint="http://localhost:8000", api_key="k")
    with pytest.raises(ValueError, match="mode must be 'batch' or 'scheduled'"):
        c.create_task(name="bad", mode="hourly", scorer_ids=["s1"])


def test_create_task_includes_optional_filters(monkeypatch):
    c = CascadeEval(endpoint="http://localhost:8000", api_key="k")
    captured = {}

    def _fake_request(method, path, body=None, params=None):
        captured["method"] = method
        captured["path"] = path
        captured["body"] = body
        return {"task_id": "t1"}

    monkeypatch.setattr(c, "_request", _fake_request)

    out = c.create_task(
        name="batch task",
        mode="batch",
        scorer_ids=["s1", "s2"],
        trace_ids=["tr1"],
        trace_filter={"name_prefix": "Travel"},
        span_filter={"span_type": "llm"},
        config={"priority": "high"},
        description="desc",
        project_filter="sdk_showcase",
    )

    assert out["task_id"] == "t1"
    assert captured["method"] == "POST"
    assert captured["path"] == "/evaluations/tasks"
    assert captured["body"]["trace_ids"] == ["tr1"]
    assert captured["body"]["trace_filter"] == {"name_prefix": "Travel"}
    assert captured["body"]["span_filter"] == {"span_type": "llm"}
    assert captured["body"]["project_filter"] == "sdk_showcase"


def test_task_lifecycle_endpoints(monkeypatch):
    c = CascadeEval(endpoint="http://localhost:8000", api_key="k")
    calls = []

    def _fake_request(method, path, body=None, params=None):
        calls.append((method, path, body, params))
        return {"ok": True}

    monkeypatch.setattr(c, "_request", _fake_request)

    c.get_task("t1")
    c.run_task("t1")
    c.pause_task("t1")
    c.resume_task("t1")
    c.get_task_results("t1", limit=10, offset=5)

    assert calls == [
        ("GET", "/evaluations/tasks/t1", None, None),
        ("POST", "/evaluations/tasks/t1/run", None, None),
        ("POST", "/evaluations/tasks/t1/pause", None, None),
        ("POST", "/evaluations/tasks/t1/resume", None, None),
        ("GET", "/evaluations/tasks/t1/results", None, {"limit": 10, "offset": 5}),
    ]


def test_request_with_requests_surfaces_http_errors(monkeypatch):
    c = CascadeEval(endpoint="http://localhost:8000", api_key="k")

    def _fake_request(*args, **kwargs):
        return _FakeResponse(
            status_code=400,
            payload={"detail": "invalid scorer ids"},
        )

    monkeypatch.setattr(eval_mod._requests, "request", _fake_request)

    with pytest.raises(CascadeEvalError) as exc:
        c._request_with_requests("POST", "http://localhost:8000/api/evaluations/tasks", body={"x": 1})

    assert exc.value.status_code == 400
    assert "invalid scorer ids" in str(exc.value)
