"""
End-to-end smoke test of the money path, runnable without web/Celery infra:

    DJANGO_SETTINGS_MODULE=config.settings.test python smoke_test.py

Proves: order placement -> completion posts commission -> wallet balance ->
idempotent payout request -> background settle -> balance reduced -> the books
stay balanced (every account sums to zero overall).
"""
import os
from decimal import Decimal

import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.test')
django.setup()

from django.utils import timezone  # noqa: E402

from apps.accounts.models import User  # noqa: E402
from apps.catalog.models import Category, Product  # noqa: E402
from apps.ledger import services as ledger  # noqa: E402
from apps.ledger.models import Entry  # noqa: E402
from apps.orders import services as orders  # noqa: E402
from apps.orders.models import Order  # noqa: E402
from apps.payouts import services as payouts  # noqa: E402
from apps.payouts.models import Payout  # noqa: E402
from apps.payouts.tasks import process_payout  # noqa: E402


def check(label, cond):
    print(f'  [{"PASS" if cond else "FAIL"}] {label}')
    assert cond, label


def main():
    from django.core.management import call_command
    call_command('seed_system_accounts', verbosity=0)

    admin = User.objects.create_user('0700000001', 'Admin', 'x', role='admin')
    seller = User.objects.create_user(
        '0711111112', 'Seller', 'x',
        kyc_status=User.KYCStatus.VERIFIED, kyc_verified_at=timezone.now())

    cat = Category.objects.create(name='Watches')
    product = Product.objects.create(
        name='Garner Chrono', selling_price=Decimal('5000'),
        cost_price=Decimal('3500'), commission_percent=10, category=cat,
        stock_quantity=-1)
    expected_commission = product.commission_per_unit() * 2  # qty 2 => 1000

    print('\n1) Place order (qty 2)')
    result = orders.place_order(
        seller=seller,
        items=[{'product_id': product.id, 'quantity': 2}],
        customer_name='Jane', customer_phone='0722')
    order = Order.objects.get(id=result['items'][0]['id'])
    check('order pending_review', order.status == Order.Status.PENDING_REVIEW)
    check('commission not yet posted', not order.commission_posted)
    check('wallet balance 0 before completion',
          ledger.user_wallet_balance(seller) == Decimal('0.00'))

    print('\n2) Drive order to completed (admin)')
    for s in ['approved', 'payment_confirmed', 'in_fulfillment', 'delivered', 'completed']:
        orders.transition_status(order=order, new_status=s, actor=admin, is_admin=True)
        order.refresh_from_db()
    check('order completed', order.status == Order.Status.COMPLETED)
    check('commission posted flag', order.commission_posted)
    check(f'wallet credited {expected_commission}',
          ledger.user_wallet_balance(seller) == expected_commission)

    print('\n3) Idempotent commission (re-complete must not double-pay)')
    ledger.post_commission(user=seller, amount=order.commission, order_id=order.id)
    check('wallet unchanged after duplicate commission post',
          ledger.user_wallet_balance(seller) == expected_commission)

    print('\n4) Request payout (idempotent key)')
    key = 'test-key-123'
    p1 = payouts.request_payout(
        user=seller, amount=Decimal('400'), payout_method='mobile_money',
        provider='mpesa', account_name='Seller', account_number='0711111112',
        idempotency_key=key)
    p2 = payouts.request_payout(
        user=seller, amount=Decimal('400'), payout_method='mobile_money',
        provider='mpesa', account_name='Seller', account_number='0711111112',
        idempotency_key=key)
    check('same payout returned for duplicate key', p1.id == p2.id)
    check('only one payout row', Payout.objects.count() == 1)
    check('funds reserved (balance 1000-400=600)',
          ledger.user_wallet_balance(seller) == Decimal('600.00'))

    print('\n5) Process payout (eager Celery) -> settle')
    process_payout(p1.id)
    p1.refresh_from_db()
    check('payout paid', p1.status == Payout.Status.PAID)
    check('balance still 600 after settle (clearing->cash)',
          ledger.user_wallet_balance(seller) == Decimal('600.00'))

    print('\n6) Reprocess settled payout is a no-op (idempotent)')
    process_payout(p1.id)
    check('still one settle txn',
          Entry.objects.filter(transaction__kind='payout_settle').count() == 2)  # 2 lines, 1 txn

    print('\n7) Overdraw is rejected')
    try:
        payouts.request_payout(
            user=seller, amount=Decimal('999999'), payout_method='mobile_money',
            provider='mpesa', account_name='Seller', account_number='x')
        check('overdraw blocked', False)
    except Exception as exc:
        check(f'overdraw blocked ({type(exc).__name__})', True)

    print('\n8) Books balance globally (double-entry integrity)')
    from django.db.models import Sum
    grand_total = Entry.objects.aggregate(s=Sum('amount'))['s']
    check(f'all entries sum to zero (got {grand_total})', grand_total == Decimal('0.00'))

    print('\nALL CHECKS PASSED ✔')


if __name__ == '__main__':
    main()
