"""Tests for validation pipeline end-to-end."""

from __future__ import annotations

import json
import tempfile
from pathlib import Path

from orxaq.fabric.validation.pipeline import ValidationPipeline
from orxaq.fabric.validation.synthetic import ValidationDataGenerator


class TestValidationPipeline:
    def setup_method(self):
        self.gen = ValidationDataGenerator()
        self.data = self.gen.generate(n=500, seed=42)
        self.true_edges = self.gen.true_edges

    def test_run_returns_metrics(self):
        pipe = ValidationPipeline(algorithm="pc")
        metrics = pipe.run(
            data=self.data,
            true_edges=self.true_edges,
            variables=["gdp_growth", "unemployment", "hpi"],
        )
        assert metrics is not None
        assert metrics.total_true_edges >= 0

    def test_run_consensus(self):
        pipe = ValidationPipeline(algorithm="consensus")
        metrics = pipe.run(
            data=self.data,
            true_edges=self.true_edges,
            variables=["gdp_growth", "unemployment", "hpi"],
        )
        assert metrics is not None

    def test_predicted_edges_populated(self):
        pipe = ValidationPipeline(algorithm="pc")
        pipe.run(
            data=self.data,
            true_edges=self.true_edges,
            variables=["gdp_growth", "unemployment", "hpi"],
        )
        assert isinstance(pipe.predicted_edges, list)

    def test_metrics_property(self):
        pipe = ValidationPipeline(algorithm="pc")
        assert pipe.metrics is None
        pipe.run(
            data=self.data,
            true_edges=self.true_edges,
            variables=["gdp_growth", "unemployment", "hpi"],
        )
        assert pipe.metrics is not None

    def test_load_data_directly(self):
        pipe = ValidationPipeline()
        pipe.load_data(self.data)
        assert len(pipe._data) == 500

    def test_load_ground_truth_directly(self):
        pipe = ValidationPipeline()
        edges = [("A", "B"), ("B", "C")]
        pipe.load_ground_truth(edges)
        assert pipe.true_edges == edges


class TestPipelineErrors:
    def test_discover_without_data_raises(self):
        pipe = ValidationPipeline()
        try:
            pipe.discover()
            assert False, "Should have raised"
        except ValueError as e:
            assert "No data" in str(e)

    def test_load_data_no_path_raises(self):
        pipe = ValidationPipeline()
        try:
            pipe.load_data()
            assert False, "Should have raised"
        except ValueError:
            pass

    def test_load_ground_truth_no_path_raises(self):
        pipe = ValidationPipeline()
        try:
            pipe.load_ground_truth()
            assert False, "Should have raised"
        except ValueError:
            pass


# ── CSV loading coverage (lines 48-54) ──────────────────────


class TestPipelineCSVLoading:
    """Cover lines 48-54 (CSV file loading path)."""

    def test_load_from_csv(self):
        """Load data from a CSV file."""
        with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
            f.write("A,B,C\n")
            for i in range(20):
                f.write(f"{i},{i * 2},{i * 3}\n")
            csv_path = f.name
        try:
            pipe = ValidationPipeline(data_path=csv_path)
            pipe.load_data()
            assert len(pipe._data) == 20
            assert set(pipe._variables) == {"A", "B", "C"}
        finally:
            Path(csv_path).unlink()

    def test_load_ground_truth_from_json(self):
        """Load ground truth edges from a JSON file."""
        dag = {"edges": [{"source": "A", "target": "B"}, {"source": "B", "target": "C"}]}
        with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
            json.dump(dag, f)
            json_path = f.name
        try:
            pipe = ValidationPipeline(ground_truth_path=json_path)
            pipe.load_ground_truth()
            assert pipe.true_edges == [("A", "B"), ("B", "C")]
        finally:
            Path(json_path).unlink()
