"""Tests for the comparison engine."""

import json

import pytest

from agent_scout.comparison import (
    ComparisonEngine,
    ComparisonField,
    ComparisonItem,
)


@pytest.fixture
def engine():
    return ComparisonEngine()


@pytest.fixture
def sample_items():
    return [
        ComparisonItem(
            name="Product A",
            source="Store 1",
            url="https://store1.com/a",
            values={"price": 100.0, "rating": 4.5, "reviews": 200},
        ),
        ComparisonItem(
            name="Product B",
            source="Store 2",
            url="https://store2.com/b",
            values={"price": 80.0, "rating": 4.0, "reviews": 150},
        ),
        ComparisonItem(
            name="Product C",
            source="Store 3",
            url="https://store3.com/c",
            values={"price": 120.0, "rating": 4.8, "reviews": 300},
        ),
    ]


@pytest.fixture
def sample_fields():
    return [
        ComparisonField(name="price", weight=2.0, higher_is_better=False, unit="$"),
        ComparisonField(name="rating", weight=1.5, higher_is_better=True),
        ComparisonField(name="reviews", weight=0.5, higher_is_better=True),
    ]


def test_compare_empty(engine):
    result = engine.compare([], [])
    assert result.items == []
    assert result.best_item is None


def test_compare_single_item(engine):
    items = [ComparisonItem(name="Solo", values={"price": 50.0})]
    fields = [ComparisonField(name="price", higher_is_better=False)]
    result = engine.compare(items, fields)
    assert len(result.items) == 1
    assert result.items[0].rank == 1
    assert result.best_item is not None
    assert result.best_item.item.name == "Solo"


def test_compare_ranking(engine, sample_items, sample_fields):
    result = engine.compare(sample_items, sample_fields)
    assert len(result.items) == 3
    # Verify ranked in order
    assert result.items[0].rank == 1
    assert result.items[1].rank == 2
    assert result.items[2].rank == 3
    # Best item should have highest score
    assert result.best_item == result.items[0]
    assert result.items[0].total_score >= result.items[1].total_score


def test_lower_is_better_field(engine):
    """Price: lower is better, so cheapest should score highest."""
    items = [
        ComparisonItem(name="Cheap", values={"price": 10.0}),
        ComparisonItem(name="Expensive", values={"price": 100.0}),
    ]
    fields = [ComparisonField(name="price", higher_is_better=False)]
    result = engine.compare(items, fields)
    assert result.items[0].item.name == "Cheap"


def test_higher_is_better_field(engine):
    items = [
        ComparisonItem(name="Low", values={"rating": 1.0}),
        ComparisonItem(name="High", values={"rating": 5.0}),
    ]
    fields = [ComparisonField(name="rating", higher_is_better=True)]
    result = engine.compare(items, fields)
    assert result.items[0].item.name == "High"


def test_weighted_scoring(engine):
    """Heavy weight on price should favor cheapest even with lower rating."""
    items = [
        ComparisonItem(name="Cheap but low rated", values={"price": 10.0, "rating": 2.0}),
        ComparisonItem(name="Pricey but top rated", values={"price": 100.0, "rating": 5.0}),
    ]
    fields = [
        ComparisonField(name="price", weight=10.0, higher_is_better=False),
        ComparisonField(name="rating", weight=0.1, higher_is_better=True),
    ]
    result = engine.compare(items, fields)
    assert result.items[0].item.name == "Cheap but low rated"


def test_missing_values(engine):
    items = [
        ComparisonItem(name="Full", values={"price": 50.0, "rating": 4.0}),
        ComparisonItem(name="Partial", values={"price": 40.0}),
    ]
    fields = [
        ComparisonField(name="price", higher_is_better=False),
        ComparisonField(name="rating", higher_is_better=True),
    ]
    result = engine.compare(items, fields)
    assert len(result.items) == 2


def test_to_table(engine, sample_items, sample_fields):
    result = engine.compare(sample_items, sample_fields)
    table = engine.to_table(result)
    assert "Rank" in table
    assert "Name" in table
    assert "Product A" in table
    assert "Product B" in table
    assert "Product C" in table


def test_to_json(engine, sample_items, sample_fields):
    result = engine.compare(sample_items, sample_fields)
    json_str = engine.to_json(result)
    data = json.loads(json_str)
    assert "items" in data
    assert "best" in data
    assert len(data["items"]) == 3


def test_to_markdown(engine, sample_items, sample_fields):
    result = engine.compare(sample_items, sample_fields)
    md = engine.to_markdown(result)
    assert "| Rank |" in md
    assert "**BEST**" in md


def test_same_values_all_score_one(engine):
    """When all items have the same value, they should all get max score."""
    items = [
        ComparisonItem(name="A", values={"price": 50.0}),
        ComparisonItem(name="B", values={"price": 50.0}),
    ]
    fields = [ComparisonField(name="price", higher_is_better=False)]
    result = engine.compare(items, fields)
    assert result.items[0].total_score == result.items[1].total_score


def test_summary_includes_best(engine, sample_items, sample_fields):
    result = engine.compare(sample_items, sample_fields)
    assert result.summary
    assert result.best_item.item.name in result.summary
