"""
PRODUCTION SETUP SCRIPT — HAVEN GRAZURI
========================================
Upload to /home/xygbfpsg/phingrazuri/ and run:
    python production_setup.py

Uses direct pymysql connection — no .env needed, no Django settings cache issues.
Safe to run multiple times.
"""
import sys, uuid
from decimal import Decimal
from datetime import date, timedelta, datetime

# ── Direct DB connection — bypasses Django settings entirely ──────────────────
import pymysql

DB = dict(
    host     = 'localhost',
    user     = 'xygbfpsg_graz',
    password = "+MvX9&%PV']]pW}",
    database = 'xygbfpsg_loans',
    port     = 3306,
    charset  = 'utf8mb4',
    autocommit = True,
)

SITE_URL   = 'https://grazuri.uzuriapps.xyz'
AT_USER    = 'Uzuriapps'
AT_KEY     = 'atsk_e810a145ccd3a1089769cd17887da70ae76124ff044fa0ab949429e6b388954e6db55009'
SENDER_ID  = 'HavGrazuri'
SP_ID      = 'e63utew7Vk3RmwKxjuMY3jocycFb5eoMZkzyKrPQ'
SP_SECRET  = '6ysF7fWBESaCNYfsh4aJOWxijTFx4JFIu5LqGFWnMx7TJxKiwaysaiNwe14Wgj9FupB6fhtRFZUas2geZZLjHwbHiShbX8w5bvWjy061Bq1SHX9EQtsBCtnuTLgaOmDV'

PASS = '✅'
FAIL = '❌'
WARN = '⚠️ '
errors = []

print("""
╔══════════════════════════════════════════════════════════╗
║         HAVEN GRAZURI — PRODUCTION SETUP SCRIPT         ║
╚══════════════════════════════════════════════════════════╝
""")

# Connect
try:
    conn = pymysql.connect(**DB)
    cur  = conn.cursor()
    print(f"  {PASS} Connected to {DB['database']} @ {DB['host']} as {DB['user']}")
except Exception as e:
    print(f"  {FAIL} Cannot connect to database: {e}")
    sys.exit(1)

def q(sql, params=None):
    """Execute a query, return rows."""
    cur.execute(sql, params or ())
    return cur.fetchall()

def run(sql, params=None):
    """Execute a statement, ignore errors (for CREATE IF NOT EXISTS etc)."""
    try:
        cur.execute(sql, params or ())
        return True
    except Exception as e:
        return str(e)

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 1 — Add missing columns to `users`
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 1: Fix `users` table columns ────────────────────────────────────")

existing_cols = {r[0] for r in q("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='users'")}

COLS = {
    'approved_by_id':    'INT DEFAULT NULL',
    'approved_at':       'DATETIME(6) DEFAULT NULL',
    'approval_reason':   'LONGTEXT DEFAULT NULL',
    'rejected_by_id':    'INT DEFAULT NULL',
    'rejected_at':       'DATETIME(6) DEFAULT NULL',
    'rejection_reason':  'LONGTEXT DEFAULT NULL',
    'is_approved':       'TINYINT(1) NOT NULL DEFAULT 0',
    'is_verified':       'TINYINT(1) NOT NULL DEFAULT 0',
    'is_phone_verified': 'TINYINT(1) NOT NULL DEFAULT 0',
    'is_email_verified': 'TINYINT(1) NOT NULL DEFAULT 0',
    'verification_date': 'DATETIME(6) DEFAULT NULL',
    'verified_by_id':    'CHAR(32) DEFAULT NULL',
    'created_at':        'DATETIME(6) DEFAULT NULL',
    'updated_at':        'DATETIME(6) DEFAULT NULL',
    'status':            "VARCHAR(20) NOT NULL DEFAULT 'active'",
    'registration_fee_amount':         'DECIMAL(12,2) DEFAULT NULL',
    'registration_fee_paid':           'TINYINT(1) NOT NULL DEFAULT 0',
    'registration_fee_payment_date':   'DATETIME(6) DEFAULT NULL',
    'registration_fee_payment_method': 'VARCHAR(20) DEFAULT NULL',
    'registration_fee_receipt_number': 'VARCHAR(50) DEFAULT NULL',
    'registration_fee_notes':          'LONGTEXT DEFAULT NULL',
    'assigned_date':        'DATETIME(6) DEFAULT NULL',
    'portfolio_manager_id': 'CHAR(32) DEFAULT NULL',
    'other_documents':      'JSON DEFAULT NULL',
    'capital_invested':     'DECIMAL(15,2) DEFAULT NULL',
    'source_of_funds':      'LONGTEXT DEFAULT NULL',
    'expected_turnover':    'DECIMAL(15,2) DEFAULT NULL',
    'county':               "VARCHAR(100) DEFAULT ''",
    'cp_domicile':          "VARCHAR(200) DEFAULT ''",
    'domicile':             "VARCHAR(200) DEFAULT ''",
    'place_of_birth':       "VARCHAR(200) DEFAULT ''",
    'nickname':             "VARCHAR(100) DEFAULT ''",
    'postal_code_business': "VARCHAR(20) DEFAULT ''",
    'business_registration_number': "VARCHAR(100) DEFAULT ''",
    'other_business_type':  "VARCHAR(200) DEFAULT ''",
    'start_time':           'TIME DEFAULT NULL',
    'registration_date':    'DATE DEFAULT NULL',
    'declaration_name':     "VARCHAR(200) DEFAULT ''",
    'personal_pin':         "VARCHAR(50) DEFAULT ''",
    'recommender_name':     "VARCHAR(200) DEFAULT ''",
    'recommender_id':       "VARCHAR(50) DEFAULT ''",
    'recommender_tel':      "VARCHAR(20) DEFAULT ''",
    'recommender_mobile':   "VARCHAR(20) DEFAULT ''",
    'recommender_residence':"VARCHAR(200) DEFAULT ''",
    'guarantor_name':       "VARCHAR(200) DEFAULT ''",
    'guarantor_id':         "VARCHAR(50) DEFAULT ''",
    'guarantor_tel':        "VARCHAR(20) DEFAULT ''",
    'guarantor_mobile':     "VARCHAR(20) DEFAULT ''",
    'guarantor_residence':  "VARCHAR(200) DEFAULT ''",
}

added = 0
for col, defn in COLS.items():
    if col not in existing_cols:
        r = run(f"ALTER TABLE `users` ADD COLUMN `{col}` {defn}")
        if r is True:
            added += 1
        else:
            print(f"   {WARN} {col}: {r}")
print(f"   {PASS} Added {added} missing column(s) to `users`")

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 2 — Create missing tables
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 2: Create missing tables ────────────────────────────────────────")

TABLES = {
'receipts': """CREATE TABLE IF NOT EXISTS `receipts` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `receipt_number` VARCHAR(20) NOT NULL UNIQUE,
    `repayment_id` CHAR(32) DEFAULT NULL, `loan_id` CHAR(32) DEFAULT NULL,
    `borrower_id` CHAR(32) DEFAULT NULL, `amount_paid` DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    `payment_method` VARCHAR(20) NOT NULL DEFAULT 'cash',
    `payment_date` DATETIME(6) NOT NULL, `previous_balance` DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    `new_balance` DECIMAL(12,2) NOT NULL DEFAULT 0.00, `pdf_file` VARCHAR(100) DEFAULT NULL,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'sasapay_ipn_logs': """CREATE TABLE IF NOT EXISTS `sasapay_ipn_logs` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `raw_data` JSON NOT NULL,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'sasapay_stk_results': """CREATE TABLE IF NOT EXISTS `sasapay_stk_results` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `checkout_request_id` VARCHAR(100) NOT NULL DEFAULT '',
    `merchant_loan_ref` VARCHAR(100) NOT NULL DEFAULT '', `result_code` VARCHAR(20) NOT NULL,
    `result_desc` LONGTEXT NOT NULL, `trans_amount` DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'sasapay_disbursement_results': """CREATE TABLE IF NOT EXISTS `sasapay_disbursement_results` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `loan_reference` VARCHAR(100) NOT NULL DEFAULT '',
    `sasapay_transaction_id` VARCHAR(100) NOT NULL DEFAULT '',
    `mpesa_reference` VARCHAR(100) NOT NULL DEFAULT '', `result_code` VARCHAR(20) NOT NULL,
    `result_desc` LONGTEXT NOT NULL, `trans_amount` DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    `merchant_balance` DECIMAL(14,2) NOT NULL DEFAULT 0.00,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'sasapay_unknown_payments': """CREATE TABLE IF NOT EXISTS `sasapay_unknown_payments` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `amount` DECIMAL(12,2) NOT NULL,
    `paid_by` VARCHAR(200) NOT NULL DEFAULT '', `msisdn` VARCHAR(20) NOT NULL DEFAULT '',
    `bill_ref` VARCHAR(100) NOT NULL DEFAULT '', `reference` VARCHAR(100) NOT NULL DEFAULT '',
    `notes` LONGTEXT NOT NULL, `resolved` TINYINT(1) NOT NULL DEFAULT 0,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'sms_logs': """CREATE TABLE IF NOT EXISTS `sms_logs` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `sms_type` VARCHAR(30) NOT NULL DEFAULT 'other',
    `recipients` LONGTEXT NOT NULL, `message` LONGTEXT NOT NULL,
    `sender_id` VARCHAR(20) NOT NULL DEFAULT 'HavGrazuri',
    `status` VARCHAR(20) NOT NULL DEFAULT 'sent', `at_response` JSON DEFAULT NULL,
    `error_message` LONGTEXT NOT NULL, `loan_number` VARCHAR(30) NOT NULL DEFAULT '',
    `borrower_name` VARCHAR(200) NOT NULL DEFAULT '', `amount` DECIMAL(12,2) DEFAULT NULL,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'mpesa_callbacks': """CREATE TABLE IF NOT EXISTS `mpesa_callbacks` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `callback_type` VARCHAR(20) NOT NULL,
    `raw_data` JSON NOT NULL, `ip_address` VARCHAR(39) DEFAULT NULL,
    `user_agent` VARCHAR(500) DEFAULT NULL, `transaction_id` CHAR(32) DEFAULT NULL,
    `processed` TINYINT(1) NOT NULL DEFAULT 0, `response_sent` JSON DEFAULT NULL,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'payment_allocations': """CREATE TABLE IF NOT EXISTS `payment_allocations` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `mpesa_transaction_id` CHAR(32) NOT NULL,
    `loan_id` CHAR(32) NOT NULL, `allocated_amount` DECIMAL(12,2) NOT NULL,
    `repayment_id` CHAR(32) NOT NULL,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'unconfirmed_payments': """CREATE TABLE IF NOT EXISTS `unconfirmed_payments` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `mpesa_transaction_id` CHAR(32) NOT NULL UNIQUE,
    `payment_phone` VARCHAR(17) DEFAULT NULL, `payment_id_number` VARCHAR(50) DEFAULT NULL,
    `suggested_borrower_id` CHAR(32) DEFAULT NULL, `match_type` VARCHAR(20) NOT NULL DEFAULT 'none',
    `status` VARCHAR(20) NOT NULL DEFAULT 'pending', `approved_by_id` CHAR(32) DEFAULT NULL,
    `approved_at` DATETIME(6) DEFAULT NULL, `rejection_reason` LONGTEXT DEFAULT NULL,
    `admin_notes` LONGTEXT DEFAULT NULL, `notes` LONGTEXT DEFAULT NULL,
    `created_at` DATETIME(6) NOT NULL,
    `updated_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'mpesa_configurations': """CREATE TABLE IF NOT EXISTS `mpesa_configurations` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `environment` VARCHAR(20) NOT NULL DEFAULT 'production',
    `consumer_key` VARCHAR(100) NOT NULL, `consumer_secret` VARCHAR(100) NOT NULL,
    `business_short_code` VARCHAR(10) NOT NULL, `passkey` VARCHAR(100) DEFAULT NULL,
    `validation_url` VARCHAR(200) NOT NULL, `confirmation_url` VARCHAR(200) NOT NULL,
    `response_type` VARCHAR(20) NOT NULL DEFAULT 'Completed',
    `is_active` TINYINT(1) NOT NULL DEFAULT 1,
    `created_at` DATETIME(6) NOT NULL,
    `updated_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",

'mpesa_access_tokens': """CREATE TABLE IF NOT EXISTS `mpesa_access_tokens` (
    `id` CHAR(32) NOT NULL PRIMARY KEY, `configuration_id` CHAR(32) NOT NULL,
    `access_token` LONGTEXT NOT NULL, `expires_at` DATETIME(6) NOT NULL,
    `created_at` DATETIME(6) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4""",
}

for tname, ddl in TABLES.items():
    r = run(ddl)
    print(f"   {'✅' if r is True else '⚠️ '} {tname}{'' if r is True else ': '+str(r)[:80]}")

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 3 — Run Django migrations (via manage.py)
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 3: Run Django migrations ────────────────────────────────────────")
import subprocess, os
manage = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'manage.py')
python = sys.executable

# Write a temp .env so manage.py picks up correct credentials
env_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '.env')
env_content = f"""DB_NAME=xygbfpsg_loans
DB_USER=xygbfpsg_graz
DB_PASSWORD=+MvX9&%PV']]pW}}
DB_HOST=localhost
DB_PORT=3306
SITE_URL={SITE_URL}
AT_USERNAME={AT_USER}
AT_API_KEY={AT_KEY}
SMS_SENDER_ID={SENDER_ID}
SASAPAY_CLIENT_ID={SP_ID}
SASAPAY_CLIENT_SECRET={SP_SECRET}
SASAPAY_MERCHANT_CODE=1122
SASAPAY_NETWORK_CODE=63902
SECRET_KEY=(W6B1[bCEAu,1wA[dz7^-prod-key-2024)
DEBUG=False
"""
with open(env_path, 'w') as f:
    f.write(env_content)
print(f"   {PASS} Wrote .env with production credentials")

for cmd in [
    [python, manage, 'makemigrations', 'loans', 'payments', '--no-input'],
    [python, manage, 'migrate', '--no-input'],
]:
    result = subprocess.run(cmd, capture_output=True, text=True,
                            cwd=os.path.dirname(manage))
    out = (result.stdout + result.stderr).strip()
    applied = [l for l in out.splitlines() if 'Applying' in l or 'OK' in l or 'No migrations' in l]
    for l in applied:
        print(f"   {PASS} {l.strip()}")
    if result.returncode != 0:
        # Show first meaningful error line
        err_lines = [l for l in out.splitlines() if l.strip() and 'Warning' not in l]
        if err_lines:
            print(f"   {WARN} Migration issue: {err_lines[-1][:150]}")
    elif not applied:
        print(f"   {PASS} No changes needed")

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 4 — Sync borrowers
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 4: Sync borrowers ───────────────────────────────────────────────")

old_borrowers = q("SELECT id,fname,middlename,lname,email,phone,id_number,status,account FROM borrowers WHERE status='Active' ORDER BY id")
print(f"   Found {len(old_borrowers)} active borrowers in old table")

borrower_map = {}  # old_id -> new_uuid_hex

for row in old_borrowers:
    old_id, fname, middle, lname, email, phone, id_number, status, account = row
    if not phone:
        print(f"   {WARN} Skipping id={old_id} ({fname} {lname}) — no phone")
        continue

    phone = str(phone).strip()
    norm  = ('+254'+phone[1:]) if phone.startswith('0') else \
            ('+'+phone)        if phone.startswith('254') else phone

    # Check if already exists
    existing = q("SELECT id FROM users WHERE phone_number IN (%s,%s,%s) LIMIT 1",
                 [norm, phone, '254'+phone[1:] if phone.startswith('0') else phone])
    if existing:
        uid = existing[0][0]
        borrower_map[old_id] = uid
        # Ensure role=borrower
        run("UPDATE users SET role='borrower', is_active=1 WHERE id=%s AND role!='borrower'", [uid])
        print(f"   {PASS} Existing: {fname} {lname} ({norm})")
        continue

    new_id   = uuid.uuid4().hex
    username = f"borrower_{old_id}"
    if q("SELECT 1 FROM users WHERE username=%s", [username]):
        username = f"borrower_{old_id}_{new_id[:4]}"
    safe_email = email if email else f"borrower_{old_id}@havengrazuri.local"
    if q("SELECT 1 FROM users WHERE email=%s", [safe_email]):
        safe_email = f"b{old_id}_{new_id[:4]}@havengrazuri.local"
    safe_id = id_number.strip() if id_number and id_number.strip() else None
    if safe_id and q("SELECT 1 FROM users WHERE id_number=%s", [safe_id]):
        safe_id = None

    r = run("""INSERT INTO `users`
        (id,username,password,email,first_name,last_name,phone_number,id_number,role,
         is_active,is_staff,is_superuser,date_joined,status,country,other_documents,
         is_verified,is_email_verified,is_phone_verified,registration_fee_paid,is_approved,
         created_at,updated_at)
        VALUES (%s,%s,'',%s,%s,%s,%s,%s,'borrower',1,0,0,NOW(),'active','Kenya','{}',
                0,0,0,0,0,NOW(),NOW())""",
        [new_id, username, safe_email, fname or '', lname or '', norm, safe_id])

    if r is True:
        borrower_map[old_id] = new_id
        print(f"   {PASS} Created: {fname} {lname} ({norm})")
    else:
        print(f"   {FAIL} {fname} {lname}: {r}")
        errors.append(f"Borrower {fname} {lname}: {r}")

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 5 — Sync loans
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 5: Sync loans ───────────────────────────────────────────────────")

if not borrower_map:
    print(f"   {WARN} No borrowers to sync")
else:
    ids = ','.join(['%s']*len(borrower_map))
    old_loans = q(f"SELECT id,baccount,borrower,amount,balance,status,pay_date FROM loan_info WHERE borrower IN ({ids}) ORDER BY id",
                  list(borrower_map.keys()))
    print(f"   Found {len(old_loans)} loans in old table")

    # Get or create product
    prod = q("SELECT id FROM loan_products WHERE is_active=1 LIMIT 1")
    if prod:
        product_id = prod[0][0]
    else:
        product_id = uuid.uuid4().hex
        run("""INSERT INTO loan_products
            (id,name,product_type,description,min_amount,max_amount,interest_rate,
             processing_fee,late_payment_penalty,min_duration,max_duration,duration_months,
             requires_guarantor,requires_collateral,is_active,available_repayment_methods,
             available_durations,max_rollover_count,max_rollover_days,rollover_fee_percentage,
             penalty_mode,penalty_frequency,gl_code,grazuri_account_type,created_at,updated_at)
            VALUES (%s,'Standard Loan','personal','Standard loan product',1000,500000,10,0,0,
                    1,36,1,0,0,1,'[]','[]',3,90,5,'flat','monthly','11001','loan',NOW(),NOW())""",
            [product_id])
        print(f"   {PASS} Created default loan product")

    created = skipped = 0
    for row in old_loans:
        old_id, baccount, old_bor_id, amount, balance, old_status, pay_date = row
        bor_uuid = borrower_map.get(old_bor_id)
        if not bor_uuid:
            continue
        if q("SELECT 1 FROM loans WHERE loan_number=%s", [baccount]):
            skipped += 1
            continue

        amount = float(amount or 0)
        django_status = ('paid'     if old_status == 'P' else
                         'approved' if old_status in ('Pending','pending') else
                         'active')
        due = pay_date if pay_date else (date.today() + timedelta(days=30))

        app_id  = uuid.uuid4().hex
        loan_id = uuid.uuid4().hex
        bor_hex = bor_uuid.replace('-','')

        r1 = run("""INSERT INTO loan_applications
            (id,application_number,requested_amount,requested_duration,purpose,
             status,submitted_at,auto_approved,borrower_id,loan_product_id,repayment_method)
            VALUES (%s,%s,%s,30,'Business working capital','approved',NOW(),0,%s,%s,'mpesa')""",
            [app_id, f"APP-{app_id[:12].upper()}", amount, bor_hex, product_id])

        r2 = run("""INSERT INTO loans
            (id,loan_number,principal_amount,interest_amount,processing_fee,total_amount,
             disbursement_date,due_date,duration_days,status,is_rolled_over,is_deleted,
             amount_paid,registration_fee,borrower_id,application_id,created_at,updated_at)
            VALUES (%s,%s,%s,0,0,%s,CURDATE(),%s,30,%s,0,0,0,0,%s,%s,NOW(),NOW())""",
            [loan_id, baccount, amount, amount, due, django_status, bor_hex, app_id])

        if r1 is True and r2 is True:
            created += 1
            print(f"   {PASS} Loan {baccount} ({django_status})")
        else:
            err = r1 if r1 is not True else r2
            print(f"   {FAIL} Loan {baccount}: {err}")
            errors.append(f"Loan {baccount}: {err}")

    print(f"   Created: {created} | Skipped (exist): {skipped}")

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 6 — Verify IPN endpoint
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 6: Verify IPN endpoint ──────────────────────────────────────────")
ipn_url = f"{SITE_URL}/SasaPayIPN.php"
print(f"   IPN URL: {ipn_url}")
try:
    import urllib.request
    req = urllib.request.Request(ipn_url, method='GET')
    with urllib.request.urlopen(req, timeout=10) as resp:
        print(f"   {PASS} Endpoint reachable (HTTP {resp.status})")
except Exception as e:
    code = getattr(e, 'code', None)
    if code in [405, 403]:
        print(f"   {PASS} Endpoint reachable (HTTP {code} — POST-only, expected)")
    else:
        print(f"   {WARN} {e}")

# ═══════════════════════════════════════════════════════════════════════════════
# STEP 7 — Verify Africa's Talking
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── STEP 7: Verify Africa's Talking ──────────────────────────────────────")
try:
    import africastalking
    africastalking.initialize(AT_USER, AT_KEY)
    sms = africastalking.SMS
    print(f"   {PASS} SMS client OK — username:{AT_USER}, sender:{SENDER_ID}")
except ImportError:
    print(f"   {WARN} africastalking not installed — installing now...")
    import subprocess
    result = subprocess.run(
        [sys.executable, '-m', 'pip', 'install', 'africastalking'],
        capture_output=True, text=True
    )
    if result.returncode == 0:
        import africastalking
        africastalking.initialize(AT_USER, AT_KEY)
        print(f"   {PASS} africastalking installed and SMS client OK")
    else:
        print(f"   {FAIL} Could not install africastalking: {result.stderr[:200]}")
        print(f"         Run manually: pip install africastalking")
        errors.append("africastalking not installed — run: pip install africastalking")
except Exception as e:
    print(f"   {FAIL} SMS client error: {e}")
    errors.append(f"SMS: {e}")

# ═══════════════════════════════════════════════════════════════════════════════
# FINAL SUMMARY
# ═══════════════════════════════════════════════════════════════════════════════
print("\n── FINAL SUMMARY ────────────────────────────────────────────────────────")
total_borrowers = q("SELECT COUNT(*) FROM users WHERE role='borrower'")[0][0]
total_loans     = q("SELECT COUNT(*) FROM loans")[0][0]
active_loans    = q("SELECT COUNT(*) FROM loans WHERE status='active'")[0][0]
total_reps      = q("SELECT COUNT(*) FROM repayments")[0][0]

print(f"   Borrowers in Django : {total_borrowers}")
print(f"   Loans in Django     : {total_loans} ({active_loans} active)")
print(f"   Repayments          : {total_reps}")

cur.close()
conn.close()

if errors:
    print(f"\n   {WARN} {len(errors)} issue(s):")
    for e in errors: print(f"      • {e}")
    sys.exit(1)
else:
    print(f"""
   {PASS} ALL STEPS COMPLETED SUCCESSFULLY

   Payment flow is ready:
   • Customer pays via M-Pesa to SasaPay paybill 1122
   • Uses their phone number as account reference
   • SasaPay calls: {SITE_URL}/SasaPayIPN.php
   • System matches borrower, creates repayment, reduces balance
   • HavGrazuri SMS sent to admins + customer automatically
""")
