"""Candidate ranking tests (CONTRACT §5)."""

from __future__ import annotations

from app.matching.candidates import get_candidates
from app.matching.models import PlannedLine
from tests.conftest import make_invoice


def test_client_match_outranks_amount_match():
    line = PlannedLine(
        source_row=2,
        client_name="Baskit (Duke)",
        planned_amount=40000,
        odoo_customer_id=101,
    )
    invoices = [
        # Right client, slightly off amount.
        make_invoice(1, "Baskit Pty Ltd", 39950, customer_id=101),
        # Wrong client, exact amount -> must rank below the client match.
        make_invoice(2, "Other Corp", 40000, customer_id=999),
    ]
    ranked = get_candidates(line, invoices)
    assert ranked[0].invoice_id == 1
    assert ranked[0].client_match is True


def test_amount_closeness_breaks_ties_within_same_client():
    line = PlannedLine(
        source_row=2,
        client_name="Baskit",
        planned_amount=40000,
        odoo_customer_id=101,
    )
    invoices = [
        make_invoice(1, "Baskit", 45000, customer_id=101),  # delta 5000
        make_invoice(2, "Baskit", 40100, customer_id=101),  # delta 100 (closer)
    ]
    ranked = get_candidates(line, invoices)
    assert ranked[0].invoice_id == 2
    assert abs(ranked[0].amount_delta) < abs(ranked[1].amount_delta)


def test_amount_delta_and_fields_populated():
    line = PlannedLine(source_row=2, client_name="X", planned_amount=1000)
    inv = make_invoice(7, "X Ltd", 1200, customer_id=5)
    (cand,) = get_candidates(line, [inv])
    assert cand.amount_delta == 200.0
    assert cand.invoice_id == 7
    assert 0.0 <= cand.desc_similarity <= 1.0
    assert cand.date_proximity_days == 0  # day 15 == mid-month anchor


def test_ranking_is_deterministic_for_equal_scores():
    line = PlannedLine(source_row=2, client_name="X", planned_amount=1000)
    invoices = [
        make_invoice(3, "X", 1000, customer_id=None),
        make_invoice(1, "X", 1000, customer_id=None),
        make_invoice(2, "X", 1000, customer_id=None),
    ]
    ranked = get_candidates(line, invoices)
    # Equal scores/deltas -> stable tiebreak by invoice_id ascending.
    assert [c.invoice_id for c in ranked] == [1, 2, 3]
