"""
Chase statement parser tests — Story 9.7.

Fixture: tests/fixtures/pdfs/chase_amazon_4086.pdf
Source:  Chase Amazon Prime Visa, account 4086, period 04/14/26–05/13/26
"""
from decimal import Decimal
from datetime import date

import pytest

FIXTURE_PATH = "tests/fixtures/pdfs/chase_amazon_4086.pdf"


@pytest.fixture(scope="module")
def parsed():
    from app.services.pdf_parsers.chase import parse
    txns, errors = parse(FIXTURE_PATH)
    return txns, errors


class TestChaseParserBasics:
    def test_no_errors(self, parsed):
        _, errors = parsed
        assert errors == [], f"Unexpected errors: {errors}"

    def test_transaction_count(self, parsed):
        txns, _ = parsed
        # 2 payments/credits + 11 purchases
        assert len(txns) == 13

    def test_returns_staged_transactions(self, parsed):
        from app.services.pdf_parsers.base import StagedTransaction
        txns, _ = parsed
        for t in txns:
            assert isinstance(t, StagedTransaction)

    def test_issuer_is_chase(self, parsed):
        txns, _ = parsed
        for t in txns:
            assert t.issuer == "chase"

    def test_all_amounts_are_positive(self, parsed):
        txns, _ = parsed
        for t in txns:
            assert t.amount > Decimal("0"), f"Negative amount: {t}"

    def test_all_amounts_are_decimal(self, parsed):
        txns, _ = parsed
        for t in txns:
            assert isinstance(t.amount, Decimal)

    def test_all_dates_are_2026(self, parsed):
        txns, _ = parsed
        for t in txns:
            assert t.date.year == 2026

    def test_all_have_dedup_hash(self, parsed):
        txns, _ = parsed
        for t in txns:
            assert t.dedup_hash and len(t.dedup_hash) == 64

    def test_confidence_score_present(self, parsed):
        txns, _ = parsed
        for t in txns:
            assert t.confidence_score > 0.0


class TestChaseParserCredits:
    def test_payment_is_credit(self, parsed):
        txns, _ = parsed
        payment = next(t for t in txns if "Payment Thank You" in t.merchant_raw)
        assert payment.is_credit is True

    def test_payment_amount(self, parsed):
        txns, _ = parsed
        payment = next(t for t in txns if "Payment Thank You" in t.merchant_raw)
        assert payment.amount == Decimal("700.00")

    def test_payment_date(self, parsed):
        txns, _ = parsed
        payment = next(t for t in txns if "Payment Thank You" in t.merchant_raw)
        assert payment.date == date(2026, 4, 14)

    def test_amazon_refund_is_credit(self, parsed):
        """05/06 Amazon.com refund should be credit (was -10.50)."""
        txns, _ = parsed
        refund = next(
            (t for t in txns if t.date == date(2026, 5, 6) and t.is_credit),
            None,
        )
        assert refund is not None
        assert refund.amount == Decimal("10.50")


class TestChaseParserPurchases:
    def test_anthropic_charge(self, parsed):
        txns, _ = parsed
        charge = next(t for t in txns if "ANTHROPIC" in t.merchant_raw.upper())
        assert charge.is_credit is False
        assert charge.amount == Decimal("5.00")
        assert charge.date == date(2026, 4, 20)

    def test_microsoft_normalized(self, parsed):
        txns, _ = parsed
        ms = next(t for t in txns if "Microsoft" in t.merchant_raw)
        assert ms.merchant_normalized == "Microsoft"
        assert ms.amount == Decimal("12.99")

    def test_amazon_mktpl_normalized_to_amazon(self, parsed):
        txns, _ = parsed
        mktpl = [t for t in txns if "AMAZON MKTPL" in t.merchant_raw]
        assert len(mktpl) > 0
        for t in mktpl:
            assert t.merchant_normalized == "Amazon"

    def test_amazon_prime_normalized(self, parsed):
        txns, _ = parsed
        prime = next(t for t in txns if "AMAZON PRIME" in t.merchant_raw)
        assert prime.merchant_normalized == "Amazon Prime"
        assert prime.amount == Decimal("4.99")

    def test_apple_normalized(self, parsed):
        txns, _ = parsed
        apple = next(t for t in txns if "APPLE.COM" in t.merchant_raw)
        assert apple.merchant_normalized == "Apple"
        assert apple.amount == Decimal("12.98")

    def test_no_interest_charge_included(self, parsed):
        """PURCHASE INTEREST CHARGE should be excluded from output."""
        txns, _ = parsed
        interest = [t for t in txns if "INTEREST CHARGE" in t.merchant_raw.upper()]
        assert interest == []

    def test_purchase_count(self, parsed):
        """Should have 11 purchase transactions (not credits)."""
        txns, _ = parsed
        purchases = [t for t in txns if not t.is_credit]
        assert len(purchases) == 11

    def test_credit_count(self, parsed):
        txns, _ = parsed
        credits = [t for t in txns if t.is_credit]
        assert len(credits) == 2


class TestChaseIssuerDetector:
    def test_detects_chase_from_this_pdf(self):
        import pdfplumber
        from app.services.pdf_parsers.detector import detect_issuer
        with pdfplumber.open(FIXTURE_PATH) as pdf:
            text = pdf.pages[0].extract_text() or ""
        issuer, conf = detect_issuer(text)
        assert issuer == "chase"
        assert conf >= 0.85
