"""
Golden tests for the generic engine (formerly parity tests).

History: before R6 cutover these ran each legacy matcher (matchers/*.py)
side-by-side with the engine on identical fixtures and asserted identical
matched/unmatched splits — that gate passed (34/34) and the legacy matchers
were deleted. The legacy-verified expected values are now baked in below as
the golden truth; a regression in loader/normalizer/matcher behaviour that
changes any split fails here.

Templates come from the REAL contract examples in
docs/contracts/recon_rule_examples/ — the same documents seeded in R6.
"""

import pandas as pd

from engine import pipeline
from helpers import csv_b64, xlsx_b64, load_example


def run_engine_stage(stage, templates, files, context=None):
    rule_set = {"name": "golden", "stages": [stage]}
    result = pipeline.run(rule_set, templates, files, context or {})
    return result["stages"][0]


# ── bank card vs gateway (4-key primary, 3-key fallback) ────────────────────

def card_fixtures():
    bank = pd.DataFrame({
        "CARD NUMBER": ["411111XXXXXX1111", "522222XXXXXX2222", "533333XXXXXX3333"],
        "TERMINAL NUMBER": ["T001", "T002", "T003"],
        "APPROV CODE": ["123456", "111111", "222222"],
        "DOMESTIC AMT": [500, 750, 900],
        "INTNL AMT": [0, 0, 0],
    })
    gateway = pd.DataFrame({
        "card_num": ["411111XXXXXX1111", "522222XXXXXX2222"],
        "terminal_id": ["T001", "T002"],
        "total_amount": [500, 750],
        "approval_code": ["123456", "999999"],  # 2nd approval differs → 3-key
        "processing_id": ["P1", "P2"],
        "transaction_id": ["TXN1", "TXN2"],
        "email": ["a@x.com", "b@x.com"],
        "paymenttype": ["CARD", "CARD"],
    })
    return bank, gateway


def test_golden_bank_card_vs_gateway():
    bank, gateway = card_fixtures()

    ruleset = load_example("card_3way.ruleset.json")
    stage = ruleset["stages"][0]  # bank_card_vs_gateway
    engine = run_engine_stage(
        stage,
        {
            "hdfc_card_mpr": load_example("hdfc_card_mpr.template.json"),
            "momentspay_gateway": load_example("momentspay_gateway.template.json"),
        },
        {"hdfc_card_mpr": xlsx_b64(bank), "momentspay_gateway": csv_b64(gateway)},
    )

    # Golden values verified against legacy matchers/card.py before deletion.
    assert engine["matched_count"] == 2
    assert engine["unmatched_a_count"] == 1
    assert engine["tier_counts"] == {"exact-4key": 1, "3key": 1}
    assert sorted(r["card_last4"] for r in engine["matched_rows"]) == ["1111", "2222"]
    assert {r["transaction_id"] for r in engine["matched_rows"]} == {"TXN1", "TXN2"}
    assert engine["matched_amount"] == 1250.0


# ── bank UPI vs gateway (single 4-key tier: VPA + terminal + amount + RRN) ──

def upi_fixtures():
    bank = pd.DataFrame({
        "PAYER VPA": ["user@upi", "someone@ybl", "other@paytm"],
        "EXTERNAL TID": ["U001", "U002", "U003"],
        "Transaction Amount": [250, 480, 730],
        "RRN NO": ["111222333444", "555666777888", "999888777666"],
    })
    gateway = pd.DataFrame({
        "card_num": ["user@upi", "someone@ybl"],
        "terminal_id": ["U001", "U002"],
        "total_amount": [250, 480],
        "approval_code": ["000001", "000002"],
        "rrn_no": ["111222333444", "555666777888"],
        "processing_id": ["P1", "P2"],
        "transaction_id": ["TXN1", "TXN2"],
        "email": ["a@x.com", "b@x.com"],
        "paymenttype": ["UPI", "UPI"],
    })
    return bank, gateway


def test_golden_bank_upi_vs_gateway():
    bank, gateway = upi_fixtures()

    ruleset = load_example("upi_3way.ruleset.json")
    stage = ruleset["stages"][0]  # bank_upi_vs_gateway
    engine = run_engine_stage(
        stage,
        {
            "bank_upi_settlement": load_example("bank_upi_settlement.template.json"),
            "momentspay_gateway": load_example("momentspay_gateway.template.json"),
        },
        {"bank_upi_settlement": xlsx_b64(bank), "momentspay_gateway": csv_b64(gateway)},
    )

    # Golden values verified against legacy matchers/upi.py before deletion.
    assert engine["matched_count"] == 2
    assert engine["unmatched_a_count"] == 1
    assert sorted(r["payer_vpa"] for r in engine["matched_rows"]) == ["someone@ybl", "user@upi"]


# ── AMEX vs internal system (2-key: amount + approval) ───────────────────────

def amex_fixtures():
    internal = pd.DataFrame({
        "Amount": [1500, 2000, 999],
        "Approval No": ["111111", "222222", "333333"],
        "Doc Date": ["15/06/2026", "15/06/2026", "15/06/2026"],
        "Unit/Location": ["HDP", "BBW", "HDP"],
        "payment mode": ["AMEX", "AMEX", "UPI"],  # UPI row filtered out
    })
    amex = pd.DataFrame({
        "Amount": [1500, 2500],
        "Approval Code": ["111111", "444444"],
        "Reference": ["REF1", "REF2"],
    })
    return internal, amex


def test_golden_amex():
    internal, amex = amex_fixtures()

    ruleset = load_example("amex_2way.ruleset.json")
    stage = ruleset["stages"][0]  # internal_vs_amex
    engine = run_engine_stage(
        stage,
        {
            "internal_billing_export": load_example("internal_billing_export.template.json"),
            "amex_settlement": load_example("amex_settlement.template.json"),
        },
        {"internal_billing_export": xlsx_b64(internal), "amex_settlement": csv_b64(amex)},
    )

    # Golden values verified against legacy matchers/amex.py before deletion
    # (legacy OUTER-merge unmatched of 2 = engine's unmatched_a 1 + unmatched_b 1).
    assert engine["matched_count"] == 1
    assert engine["unmatched_a_count"] == 1
    assert engine["unmatched_b_count"] == 1


# ── internal vs bank card (3-key: last4 + amount + approval) ─────────────────

def his_bank_card_fixtures():
    internal = pd.DataFrame({
        "Card No/Cheque": ["411111XXXXXX1111", "522222XXXXXX2222", "633333XXXXXX9999"],
        "Amount": [1500, 2000, 999],
        "Approval No": ["123456", "111111", "222222"],
        "Doc Date": ["15/06/2026", "15/06/2026", "15/06/2026"],
        "Unit/Location": ["HDP", "BBW", "HDP"],
        "payment mode": ["Credit Card", "Debit Card", "UPI"],  # UPI filtered
        "IP/MRNO": ["MR1", "MR2", "MR3"],
        "Doc No": ["D1", "D2", "D3"],
    })
    bank = pd.DataFrame({
        "CARD NUMBER": ["411111XXXXXX1111", "744444XXXXXX4444"],
        "TERMINAL NUMBER": ["T001", "T002"],
        "APPROV CODE": ["123456", "555555"],
        "DOMESTIC AMT": [1500, 3000],
        "INTNL AMT": [0, 0],
    })
    return internal, bank


def test_golden_internal_vs_bank_card():
    internal, bank = his_bank_card_fixtures()

    stage = {
        "stage": "internal_vs_bank_card_direct",
        "side_a": {
            "source": "template:internal_billing_export",
            "filters": [{"field": "payment_mode", "op": "in",
                         "values": ["DEBIT CARD", "CREDIT CARD"]}],
        },
        "side_b": {"source": "template:hdfc_card_mpr"},
        "tiers": [{
            "name": "card-amount-approval",
            "keys": [["card_last4", "card_last4"], ["amount", "amount"],
                      ["approval_code", "approval_code"]],
        }],
        "output": {"matched_sheet": "M", "unmatched_sheet": "U"},
    }
    engine = run_engine_stage(
        stage,
        {
            "internal_billing_export": load_example("internal_billing_export.template.json"),
            "hdfc_card_mpr": load_example("hdfc_card_mpr.template.json"),
        },
        {"internal_billing_export": xlsx_b64(internal), "hdfc_card_mpr": xlsx_b64(bank)},
    )

    # Golden values verified against legacy matchers/his_bank_card.py before deletion.
    assert engine["matched_count"] == 1
    assert engine["unmatched_a_count"] == 1
    assert engine["unmatched_b_count"] == 1


# ── internal vs bank UPI (3-key: VPA + amount + RRN) ─────────────────────────

def his_bank_upi_fixtures():
    internal = pd.DataFrame({
        "Card No/Cheque": ["user@upi", "someone@ybl", "411111XXXXXX1111"],
        "Amount": [800, 900, 999],
        "Txn ref no.(RRN)": ["111222333444", "000000000001", "000000000002"],
        "Doc Date": ["15/06/2026", "15/06/2026", "15/06/2026"],
        "Unit/Location": ["HDP", "BBW", "HDP"],
        "payment mode": ["UPI", "UPI", "Credit Card"],  # card row filtered
    })
    bank = pd.DataFrame({
        "PAYER VPA": ["user@upi", "other@paytm"],
        "EXTERNAL TID": ["U001", "U002"],
        "Transaction Amount": [800, 700],
        "RRN NO": ["111222333444", "999888777666"],
    })
    return internal, bank


def test_golden_internal_vs_bank_upi():
    internal, bank = his_bank_upi_fixtures()

    stage = {
        "stage": "internal_vs_bank_upi_direct",
        "side_a": {
            "source": "template:internal_billing_export",
            "filters": [{"field": "payment_mode", "op": "eq", "value": "UPI"}],
        },
        "side_b": {"source": "template:bank_upi_settlement"},
        "tiers": [{
            "name": "vpa-amount-rrn",
            "keys": [["card_last4", "payer_vpa"], ["amount", "amount"], ["rrn", "rrn"]],
        }],
        "output": {"matched_sheet": "M", "unmatched_sheet": "U"},
    }
    engine = run_engine_stage(
        stage,
        {
            "internal_billing_export": load_example("internal_billing_export.template.json"),
            "bank_upi_settlement": load_example("bank_upi_settlement.template.json"),
        },
        {"internal_billing_export": xlsx_b64(internal), "bank_upi_settlement": xlsx_b64(bank)},
    )

    # Golden values verified against legacy matchers/his_bank_upi.py before deletion.
    assert engine["matched_count"] == 1
    assert engine["unmatched_a_count"] == 1
    assert engine["unmatched_b_count"] == 1
