from django.core.management.base import BaseCommand
from django.utils import timezone
from payments.models import Payment, UnreconciledPayment
from customers.models import Customer
from django.db.models import Q
import json

class Command(BaseCommand):
    help = 'Reconcile paybill payments and find missing transactions'

    def add_arguments(self, parser):
        parser.add_argument(
            '--days',
            type=int,
            default=30,
            help='Number of days to look back for unreconciled payments (default: 30)'
        )
        parser.add_argument(
            '--auto-resolve',
            action='store_true',
            help='Automatically resolve payments where customer can be identified'
        )

    def handle(self, *args, **options):
        days = options['days']
        auto_resolve = options['auto_resolve']

        self.stdout.write(f"=== Paybill Payment Reconciliation Report ===")
        self.stdout.write(f"Looking back {days} days for unreconciled payments...")

        # Get unreconciled payments from the last N days
        cutoff_date = timezone.now() - timezone.timedelta(days=days)
        unreconciled = UnreconciledPayment.objects.filter(
            status='pending',
            transaction_time__gte=cutoff_date
        ).order_by('-transaction_time')

        if not unreconciled.exists():
            self.stdout.write(self.style.SUCCESS("✅ No unreconciled payments found"))
            return

        self.stdout.write(f"Found {unreconciled.count()} unreconciled payments:")

        resolved_count = 0

        for payment in unreconciled:
            self.stdout.write(f"\n--- Payment {payment.transaction_id} ---")
            self.stdout.write(f"Amount: KES {payment.amount}")
            self.stdout.write(f"Phone: {payment.phone_number}")
            self.stdout.write(f"Account Ref: {payment.account_reference}")
            self.stdout.write(f"Customer Name: {payment.customer_name}")
            self.stdout.write(f"Time: {payment.transaction_time}")

            # Try to find matching customer
            customer = self.find_customer_for_payment(payment)

            if customer:
                self.stdout.write(self.style.SUCCESS(f"✅ Found matching customer: {customer.customer_id} - {customer.display_name}"))

                if auto_resolve:
                    try:
                        # Resolve the payment
                        resolved_payment = payment.resolve_to_customer(
                            customer=customer,
                            resolved_by_user=None,  # System resolved
                            notes="Auto-resolved by reconciliation command"
                        )
                        self.stdout.write(self.style.SUCCESS(f"✅ Auto-resolved as payment {resolved_payment.payment_id}"))
                        resolved_count += 1
                    except Exception as e:
                        self.stdout.write(self.style.ERROR(f"❌ Failed to auto-resolve: {str(e)}"))
                else:
                    self.stdout.write("🔄 Use --auto-resolve to automatically resolve this payment")
            else:
                self.stdout.write(self.style.WARNING("⚠️ No matching customer found"))
                self.stdout.write("Manual review required via /payments/unreconciled/")

        if auto_resolve and resolved_count > 0:
            self.stdout.write(f"\n=== Summary ===")
            self.stdout.write(self.style.SUCCESS(f"✅ Auto-resolved {resolved_count} payments"))
            remaining = unreconciled.filter(status='pending').count()
            self.stdout.write(f"⚠️ {remaining} payments still require manual review")

        # Show recent successful payments for comparison
        self.stdout.write(f"\n=== Recent Successful M-Pesa Payments ===")
        recent_successful = Payment.objects.filter(
            payment_method='mpesa',
            status='completed',
            created_at__gte=cutoff_date
        ).order_by('-created_at')[:5]

        if recent_successful.exists():
            for payment in recent_successful:
                self.stdout.write(f"✅ {payment.payment_id}: KES {payment.amount} - {payment.customer.display_name if payment.customer else 'No customer'}")
        else:
            self.stdout.write(self.style.WARNING("⚠️ No recent successful M-Pesa payments found"))

    def find_customer_for_payment(self, payment):
        """Try to find a customer for an unreconciled payment"""

        # Try by customer ID (account reference)
        if payment.account_reference and payment.account_reference != "UNKNOWN":
            customer = Customer.objects.filter(customer_id=payment.account_reference).first()
            if customer:
                return customer

        # Try by phone number variations
        phone_formats = [payment.phone_number]

        # Add variations of the phone number
        if payment.phone_number.startswith('254'):
            phone_formats.append('0' + payment.phone_number[3:])  # 0712345678
            phone_formats.append('+' + payment.phone_number)      # +254712345678
        elif payment.phone_number.startswith('0'):
            phone_formats.append('254' + payment.phone_number[1:])  # 254712345678
            phone_formats.append('+254' + payment.phone_number[1:]) # +254712345678
        elif payment.phone_number.startswith('+254'):
            phone_formats.append(payment.phone_number[1:])        # 254712345678
            phone_formats.append('0' + payment.phone_number[4:])  # 0712345678

        # Try to find customer with any of these phone formats
        for phone_format in phone_formats:
            customer = Customer.objects.filter(phone=phone_format).first()
            if customer:
                return customer

        # Try by name matching (fuzzy)
        if payment.first_name and payment.last_name:
            customers = Customer.objects.filter(
                Q(full_name__icontains=payment.first_name) |
                Q(full_name__icontains=payment.last_name) |
                Q(contact_person_first_name__icontains=payment.first_name) |
                Q(contact_person_last_name__icontains=payment.last_name)
            )

            if customers.count() == 1:
                return customers.first()

        return None