"""Tests for capture layer — GroundTracker and TemplateLibrary."""

import pytest
from uuid import uuid4

from xyglue.capture.ground_tracker import GroundTracker, GroundRecord
from xyglue.capture.templates import TemplateLibrary, ProvenTemplate, TemplateCandidate
from xyglue.thinking.models import (
    ThinkingResult, BenchmarkMap, ClassifiedMap, Path, Constraint,
)


def _make_thinking_result(goal: str = "test", domain: str = "web") -> ThinkingResult:
    """Helper to create a ThinkingResult for testing."""
    return ThinkingResult(
        goal_text=goal,
        benchmark_map=BenchmarkMap(domain=domain),
        classified_map=ClassifiedMap(constraints=[
            Constraint(element_name="test_habit", constraint_type="habit"),
        ]),
        paths=[
            Path(id="A", description="diverge"),
            Path(id="B", description="hybrid"),
            Path(id="C", description="optimized"),
        ],
    )


class TestGroundRecord:
    def test_basic_record(self):
        r = GroundRecord(run_id=uuid4(), goal_text="Build API", benchmark_domain="web")
        assert r.goal_text == "Build API"
        assert r.benchmark_domain == "web"

    def test_to_dict(self):
        r = GroundRecord(run_id=uuid4(), goal_text="test")
        d = r.to_dict()
        assert "run_id" in d
        assert "goal_text" in d


class TestGroundTracker:
    @pytest.fixture
    def tracker(self):
        return GroundTracker()

    def test_record(self, tracker):
        tr = _make_thinking_result("Build API", "web")
        record = tracker.record(
            run_id=uuid4(), thinking_result=tr,
            winning_path="A", paths_attempted=["A"],
            quality_score=0.9, was_healed=False, heal_count=0,
        )
        assert isinstance(record, GroundRecord)
        assert record.winning_path == "A"

    def test_find_similar(self, tracker):
        tr = _make_thinking_result("Build API", "web")
        tracker.record(
            run_id=uuid4(), thinking_result=tr,
            winning_path="A", paths_attempted=["A"],
            quality_score=0.9, was_healed=False, heal_count=0,
        )
        similar = tracker.find_similar("web")
        assert len(similar) == 1

    def test_stats(self, tracker):
        tr = _make_thinking_result("test", "web")
        tracker.record(
            run_id=uuid4(), thinking_result=tr,
            winning_path="A", paths_attempted=["A"],
            quality_score=0.95, was_healed=False, heal_count=0,
        )
        stats = tracker.get_stats()
        assert stats["total_runs"] == 1
        assert stats["path_a_wins"] == 1


class TestTemplateCandidate:
    def test_add_score_pass(self):
        tc = TemplateCandidate(goal_text="test", domain="web")
        result = tc.add_score(0.96, threshold=0.95)
        assert result is True
        assert tc.validation_count == 1

    def test_add_score_fail_resets(self):
        tc = TemplateCandidate(goal_text="test", domain="web")
        tc.add_score(0.96, threshold=0.95)
        result = tc.add_score(0.5, threshold=0.95)
        assert result is False
        assert tc.validation_count == 0


class TestProvenTemplate:
    def test_basic_template(self):
        t = ProvenTemplate(domain="web", goal_text="Build API", winning_path="A", avg_quality_score=0.96)
        assert t.avg_quality_score == 0.96
        assert t.domain == "web"


class TestTemplateLibrary:
    @pytest.fixture
    def library(self):
        return TemplateLibrary()

    def test_submit_candidate_validating(self, library):
        tr = _make_thinking_result("Build API", "web")
        status = library.submit_candidate(tr, winning_path="A", quality_score=0.96)
        assert status == "validating"

    def test_submit_candidate_rejected(self, library):
        tr = _make_thinking_result("Build API", "web")
        status = library.submit_candidate(tr, winning_path="A", quality_score=0.5)
        assert status == "rejected"

    def test_submit_candidate_promoted(self, library):
        tr = _make_thinking_result("Build API", "web")
        library.submit_candidate(tr, winning_path="A", quality_score=0.96)
        status = library.submit_candidate(tr, winning_path="A", quality_score=0.97)
        assert status == "promoted"

    def test_find_templates_after_promotion(self, library):
        tr = _make_thinking_result("Build API", "web")
        library.submit_candidate(tr, winning_path="A", quality_score=0.96)
        library.submit_candidate(tr, winning_path="A", quality_score=0.97)
        templates = library.find_templates("web")
        assert len(templates) == 1

    def test_single_failure_resets(self, library):
        tr = _make_thinking_result("Build API", "web")
        library.submit_candidate(tr, winning_path="A", quality_score=0.96)
        status = library.submit_candidate(tr, winning_path="A", quality_score=0.5)
        assert status == "reset"

    def test_quality_threshold_095(self, library):
        assert library.quality_threshold == 0.95

    def test_stats(self, library):
        stats = library.get_stats()
        assert stats["proven_templates"] == 0
