"""Regression checks for POS evidence and deterministic reconciliation."""

from __future__ import annotations

import sys
import unittest
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(PROJECT_ROOT))

from apps.wp_invoices.services.reconciliation import evidence, reconcile_invoice


def item(description, total, *, quantity=1, unit_price=None, basis="each", line=1):
    line_evidence = evidence(str(total), str(line), 0.95)
    line_evidence.update({"verification": "ocr_verified", "status": "confirmed"})
    return {
        "description": description, "quantity": quantity,
        "transaction_unit": "kg" if basis == "kg" else "each",
        "package_size": None, "unit_price": total if unit_price is None else unit_price,
        "unit_price_basis": basis, "tax_code": "A", "line_total": total,
        "tax_code_evidence": {"evidence_state": "confirmed"},
        "source_text": f"{description} {total} A", "source_line": str(line),
        "evidence": {"line_total": line_evidence},
    }


class ReconciliationChecks(unittest.TestCase):
    def test_hierarchical_surcharge_counts_only_parent_and_rounding(self):
        result = reconcile_invoice(
            items=[], adjustments=[
                {"type": "payment_surcharge", "amount": 0.33, "source_text": "0.33 A"},
                {"type": "payment_surcharge", "amount": 0.11, "source_text": "0.11 B"},
                {"type": "payment_surcharge", "amount": 0.44, "source_text": "Total surcharge 0.44"},
                {"type": "rounding", "amount": 0.00, "source_text": "Rounding 0.00"},
            ], tax_summary={"tax_total": 0, "lines": [{"tax_amount": 0}]},
            subtotal=89.46, total=89.90,
        )
        self.assertEqual(0.44, result["adjustments_sum"])
        self.assertEqual("passed", result["adjustments_reconciled"])
        components = [row for row in result["reconciled_adjustments"] if row["reconciliation_role"] == "component"]
        self.assertEqual([0.33, 0.11], [row["amount"] for row in components])

    def test_source_evidence_cannot_pass_when_count_or_subtotal_fails(self):
        value = item("Product", 3.00)
        value["evidence"]["line_total"]["verification"] = "ocr_verified"
        result = reconcile_invoice(
            items=[value], adjustments=[], tax_summary={"tax_total": 0, "lines": [{"tax_amount": 0}]},
            subtotal=4.00, total=4.00, observed_item_line_count=2,
        )
        self.assertEqual("failed", result["source_evidence_valid"])

    def test_internally_self_consistent_but_unsupported_tax_rows_fail(self):
        result = reconcile_invoice(
            items=[item("Product", 6.81)], adjustments=[],
            tax_summary={"tax_total": 0, "declared_tax_total": 8.90, "lines": [
                {"tax_code": "A", "rate": None, "net_amount": 6.81, "tax_amount": 0,
                 "evidence": {"status": "observed_unverified"}},
                {"tax_code": "A", "rate": None, "net_amount": 19.80, "tax_amount": 0,
                 "evidence": {"status": "observed_unverified"}},
            ]}, subtotal=6.81, total=6.81, observed_item_line_count=1,
        )
        self.assertEqual("failed", result["tax_reconciled"])
        self.assertEqual("failed", result["tax_validation"]["checks"]["required_tax_codes_valid"])
        self.assertEqual("failed", result["tax_validation"]["checks"]["rates_valid"])
        self.assertEqual("failed", result["tax_validation"]["checks"]["source_evidence_valid"])
        self.assertEqual("failed", result["tax_validation"]["checks"]["declared_total_valid"])
        self.assertEqual("failed", result["tax_validation"]["tax_summary_extraction"]["status"])
        self.assertEqual("failed", result["tax_validation"]["tax_summary_vs_items"]["status"])

    def test_aldi_25_rows_reconcile_without_deduplicating_repeats(self):
        items = [item(f"Product {index}", 3.00, line=index) for index in range(1, 20)]
        items.append(item("Product 20", 17.39, line=20))
        items.extend([
            item("Grape White per kg", 4.11, quantity=0.824, unit_price=4.99, basis="kg", line=21),
            item("Capsicum R per kg", 1.96, quantity=0.207, unit_price=9.49, basis="kg", line=22),
            item("Tuna Flav 95g", 3.00, line=23),
            item("Tuna Flav 95g", 3.00, line=24),
            item("Tuna Flav 95g", 3.00, line=25),
        ])
        result = reconcile_invoice(
            items=items,
            adjustments=[{"type": "payment_surcharge", "amount": 0.44,
                          "source_text": "Surcharge 0.50% amount $0.44"}],
            tax_summary={"tax_total": 1.98, "declared_tax_total": 1.98, "lines": [
                {"tax_code": "A", "rate": 0.00, "net_amount": 68.12, "tax_amount": 0.00,
                 "evidence": {"status": "confirmed"}},
                {"tax_code": "B", "rate": 0.10, "net_amount": 19.80, "tax_amount": 1.98,
                 "evidence": {"status": "confirmed"}},
            ]},
            subtotal=89.46, total=89.90, observed_item_line_count=25,
        )
        self.assertEqual(25, result["extracted_item_count"])
        self.assertEqual("passed", result["item_count_reconciled"])
        self.assertEqual("passed", result["subtotal_reconciled"])
        self.assertEqual("passed", result["adjustments_reconciled"])
        self.assertEqual("passed", result["tax_reconciled"])
        self.assertEqual("passed", result["tax_validation"]["tax_summary_extraction"]["status"])
        self.assertEqual("passed", result["tax_validation"]["item_tax_classification"]["status"])
        self.assertEqual("passed", result["tax_validation"]["tax_summary_vs_items"]["status"])
        self.assertEqual(3, sum(value["description"] == "Tuna Flav 95g" for value in items))

    def test_missing_row_and_percentage_as_money_cannot_pass(self):
        bad = item("Tuna Flav 95g", 3.00, basis="A", line=1)
        bad["evidence"]["line_total"] = evidence("3.00", None, 0.95)
        result = reconcile_invoice(
            items=[bad],
            adjustments=[{"type": "discount", "amount": -0.50, "source_text": "0.50%"}],
            tax_summary={"tax_total": 1.98, "lines": [{"tax_amount": 19.80}]},
            subtotal=89.46, total=89.90, observed_item_line_count=25,
        )
        self.assertEqual("failed", result["item_count_reconciled"])
        self.assertEqual("failed", result["subtotal_reconciled"])
        self.assertEqual("failed", result["tax_reconciled"])
        self.assertEqual("failed", result["source_evidence_valid"])
        self.assertIn("percentage_interpreted_as_money", result["issues"])
        self.assertIn("suspicious_extraction", result["issues"])


if __name__ == "__main__":
    unittest.main(verbosity=2)
