#!/usr/bin/env python
"""
test_ipn_pipeline.py
────────────────────
End-to-end test of the SasaPay IPN pipeline.

1. Sends a real test IPN POST to the live URL (same payload SasaPay sends)
2. Checks the IPN log was created
3. Shows exactly what happened (matched/dropped/processed)
4. Cleans up the test record

Run on the server:
    python test_ipn_pipeline.py

Does NOT create a real repayment — uses a test TransID that won't match
any real borrower, so it exercises the full pipeline safely.
"""

import os, sys, django, json, time
os.environ['DJANGO_SETTINGS_MODULE'] = 'branch_system.settings_production'
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
django.setup()

import requests
from django.conf import settings
from django.db import connection

SEP  = '─' * 68
SEP2 = '═' * 68

SITE_URL = getattr(settings, 'SITE_URL', 'https://grazuri.uzuriapps.xyz').rstrip('/')

# All URL variants to test
URLS_TO_TEST = [
    ('Old PHP path (primary)',  f'{SITE_URL}/SasaPayIPN.php'),
    ('New Django path',         f'{SITE_URL}/payments/sasapay/ipn/'),
]

# Fake IPN payload — mirrors exactly what SasaPay sends
TEST_TRANS_ID = f'TEST_{int(time.time())}'
TEST_PAYLOAD = {
    'MerchantCode':       '1122',
    'BusinessShortCode':  '1122',
    'TransID':            TEST_TRANS_ID,
    'ThirdPartyTransID':  'TESTMPESAREF',
    'FullName':           'Test Pipeline User',
    'FirstName':          'Test',
    'MiddleName':         'Pipeline',
    'LastName':           'User',
    'MSISDN':             'HASHEDPHONE000',
    'TransAmount':        '1.00',
    'BillRefNumber':      '0700000000',  # won't match any real borrower
    'TransactionType':    'Pay Bill',
    'OrgAccountBalance':  '0',
    'InvoiceNumber':      '',
    'PaymentMethod':      'MPESA',
}

def run():
    print()
    print(SEP2)
    print('  SASAPAY IPN PIPELINE — END TO END TEST')
    print(SEP2)
    print(f'  SITE_URL : {SITE_URL}')
    print(f'  Test TransID: {TEST_TRANS_ID}')
    print()

    working_url = None

    for label, url in URLS_TO_TEST:
        print(SEP)
        print(f'  Testing: {label}')
        print(f'  URL    : {url}')

        # ── GET check ────────────────────────────────────────────────────
        try:
            g = requests.get(url, timeout=10)
            print(f'  GET    : HTTP {g.status_code}  → {g.text[:80]}')
        except Exception as e:
            print(f'  GET    : FAILED — {e}')
            print()
            continue

        if g.status_code != 200:
            print(f'  ⚠️  GET returned {g.status_code} — skipping POST test')
            print()
            continue

        # ── POST IPN ──────────────────────────────────────────────────────
        try:
            unique_payload = {**TEST_PAYLOAD, 'TransID': f'{TEST_TRANS_ID}_{label[:3]}'}
            r = requests.post(url, json=unique_payload, timeout=15)
            print(f'  POST   : HTTP {r.status_code}  → {r.text[:120]}')

            if r.status_code == 200:
                try:
                    resp_data = r.json()
                    result_code = resp_data.get('ResultCode', '?')
                    result_desc = resp_data.get('ResultDesc', '')
                    print(f'  Result : Code={result_code}  Desc={result_desc}')
                    if result_code in ('0', 0):
                        print(f'  ✅ URL accepted the IPN')
                        if working_url is None:
                            working_url = url
                    else:
                        print(f'  ⚠️  ResultCode={result_code}')
                except Exception:
                    print(f'  Response was not JSON')
            else:
                print(f'  ❌ HTTP {r.status_code}')
        except Exception as e:
            print(f'  POST   : FAILED — {e}')
        print()

    # ── Check IPN log ────────────────────────────────────────────────────
    print(SEP)
    print('  Checking IPN log entries created by this test...')
    time.sleep(1)  # give DB a moment

    with connection.cursor() as c:
        c.execute("""
            SELECT id, created_at, processing_status, processing_note,
                   JSON_UNQUOTE(JSON_EXTRACT(raw_data, '$.TransID')) AS trans_id,
                   JSON_UNQUOTE(JSON_EXTRACT(raw_data, '$.BillRefNumber')) AS bill_ref
            FROM sasapay_ipn_logs
            WHERE raw_data LIKE %s
            ORDER BY created_at DESC
        """, [f'%{TEST_TRANS_ID}%'])
        rows = c.fetchall()

    if rows:
        print(f'  ✅ {len(rows)} IPN log row(s) created:')
        for row in rows:
            log_id, created, status, note, tid, bref = row
            print(f'    TransID={tid}  status={status}')
            print(f'    Note: {note or "(none — drop reason not set, check server logs)"}')
            if status == 'no_match':
                print('    ✅ Pipeline reached Step 2 (borrower matching) — working correctly')
                print('       "no_match" is expected for a fake phone number')
            elif status == 'processed':
                print('    ✅ Payment was processed (unexpected for test — check if real borrower matched)')
            elif status == 'pending':
                print('    ⚠️  Status is still "pending" — processor may not have run')
            else:
                print(f'    Status: {status}')
    else:
        print('  ❌ No IPN log rows found for this test TransID')
        print('     The POST reached the server but the IPN was not logged.')
        print('     This means _save_sasapay_ipn_log() failed silently.')

    # ── Cleanup test rows ─────────────────────────────────────────────────
    with connection.cursor() as c:
        c.execute(
            "DELETE FROM sasapay_ipn_logs WHERE raw_data LIKE %s",
            [f'%{TEST_TRANS_ID}%']
        )
        deleted = c.rowcount
    if deleted:
        print(f'  (Cleaned up {deleted} test log row(s))')

    # ── Final verdict ─────────────────────────────────────────────────────
    print()
    print(SEP2)
    if working_url:
        print(f'  ✅ WORKING IPN URL CONFIRMED:')
        print(f'     {working_url}')
        print()
        print('  Register this in the SasaPay merchant portal as the IPN URL.')
        print('  No other changes needed — pipeline is fully operational.')
    else:
        print('  ❌ No URL accepted the test IPN successfully.')
        print('     Check server error logs for details.')
    print(SEP2)


if __name__ == '__main__':
    run()
