"""Shared fixtures for review tests."""

from __future__ import annotations

import json
import os
from datetime import datetime, timedelta, timezone
from typing import Any

import pytest


@pytest.fixture
def make_trace():
    """Factory for creating trace dicts with sensible defaults."""

    _counter = 0

    def _make(
        *,
        trace_id: str | None = None,
        project: str = "test-project",
        cost: float = 0.01,
        latency: float = 1.0,
        model: str = "gpt-4o",
        provider: str = "openai",
        input_tokens: int = 100,
        output_tokens: int = 50,
        error: str | None = None,
        num_spans: int = 1,
        input_text: str = "hello",
        output_text: str = "world",
        started_at: str | None = None,
        extra_spans: list[dict[str, Any]] | None = None,
        tags: list[str] | None = None,
    ) -> dict[str, Any]:
        nonlocal _counter
        _counter += 1
        tid = trace_id or f"tr-{_counter:04d}"

        now = datetime.now(timezone.utc)
        start = started_at or (now - timedelta(seconds=latency)).isoformat().replace("+00:00", "Z")
        end = now.isoformat().replace("+00:00", "Z") if not started_at else (
            datetime.fromisoformat(start.replace("Z", "+00:00")) + timedelta(seconds=latency)
        ).isoformat().replace("+00:00", "Z")

        spans = []
        for i in range(num_spans):
            span: dict[str, Any] = {
                "span_id": f"sp-{tid}-{i}",
                "name": f"llm-call-{i}",
                "kind": "llm",
                "started_at": start,
                "ended_at": end,
                "status": "error" if error and i == 0 else "ok",
                "model": model,
                "provider": provider,
                "input_tokens": input_tokens,
                "output_tokens": output_tokens,
                "cost": cost / num_spans,
            }
            if error and i == 0:
                span["error"] = error
            spans.append(span)

        if extra_spans:
            spans.extend(extra_spans)

        trace = {
            "trace_id": tid,
            "project": project,
            "input": input_text,
            "output": output_text,
            "started_at": start,
            "ended_at": end,
            "status": "error" if error else "ok",
            "spans": spans,
        }
        if tags is not None:
            trace["tags"] = tags
        return trace

    return _make


@pytest.fixture
def make_evaluation():
    """Factory for creating evaluation dicts."""

    def _make(
        trace_id: str,
        human_score: int | None = 1,
        judge_score: int | None = None,
        human_comment: str | None = None,
        judge_critique: str | None = None,
    ) -> dict[str, Any]:
        ev: dict[str, Any] = {
            "trace_id": trace_id,
            "created_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
        }
        if human_score is not None:
            ev["human_score"] = human_score
        if judge_score is not None:
            ev["judge_score"] = judge_score
        if human_comment is not None:
            ev["human_comment"] = human_comment
        if judge_critique is not None:
            ev["judge_critique"] = judge_critique
        return ev

    return _make


@pytest.fixture
def traces_dir(tmp_path):
    """Create a temp directory with traces/ and evaluations/ subdirs."""
    traces = tmp_path / "traces"
    evals = tmp_path / "evaluations"
    traces.mkdir()
    evals.mkdir()
    return tmp_path


def write_trace(traces_dir, trace: dict[str, Any]) -> None:
    """Write a trace dict to the traces directory (project-scoped)."""
    project = trace.get("project", "default")
    project_dir = os.path.join(str(traces_dir), "traces", project)
    os.makedirs(project_dir, exist_ok=True)
    path = os.path.join(project_dir, f"{trace['trace_id']}.json")
    with open(path, "w") as f:
        json.dump(trace, f)


def write_evaluation(traces_dir, evaluation: dict[str, Any]) -> None:
    """Write an evaluation dict to the evaluations directory."""
    path = os.path.join(str(traces_dir), "evaluations", f"{evaluation['trace_id']}.json")
    with open(path, "w") as f:
        json.dump(evaluation, f)
