from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.db.models import Q
from datetime import date

from loans.models import LoanApplication
from loans.helper import process_loan_payment, loan_balance
from customers.models import Customer
from ledgers.models import CashAccounts, OrganisationSubAccount
from questbanker_api.utils import get_current_user


class OfficerLoanCustomerSearchView(APIView):
    """Search for customers by name or member number"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        search = request.GET.get('search', '').strip()
        organisation_id = get_current_user(request, 'organisation_id', None)

        if not search or len(search) < 2:
            return Response({
                'status': False,
                'message': 'Please provide at least 2 characters to search'
            }, status=status.HTTP_400_BAD_REQUEST)

        filters = {'is_deleted': False}
        if organisation_id:
            filters['customer_branch__branch_organisation__id'] = organisation_id

        customers = Customer.objects.filter(
            Q(name__icontains=search) | Q(member_number__icontains=search) | Q(old_member_number__icontains=search),
            **filters
        ).select_related('customer_branch', 'branch_customer_type')[:20]

        results = []
        for customer in customers:
            results.append({
                'customer_id': customer.id,
                'name': customer.name,
                'member_number': customer.member_number,
                'old_member_number': customer.old_member_number or '',
                'telephone': customer.telephone or '',
                'customer_type': customer.branch_customer_type.customer_type if customer.branch_customer_type else '',
                'branch_name': customer.customer_branch.name if customer.customer_branch else ''
            })

        return Response({
            'status': True,
            'count': len(results),
            'results': results
        })


class OfficerLoanCustomerLoansView(APIView):
    """Get active loans for a customer"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        customer_id = request.GET.get('customer_id')
        debug = request.GET.get('debug', '').lower() == 'true'

        if not customer_id:
            return Response({
                'status': False,
                'message': 'customer_id is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            customer = Customer.objects.get(id=customer_id, is_deleted=False)
        except Customer.DoesNotExist:
            return Response({
                'status': False,
                'message': 'Customer not found'
            }, status=status.HTTP_404_NOT_FOUND)

        if debug:
            loans = LoanApplication.objects.filter(
                customer=customer
            ).select_related(
                'loan_application_product',
                'organisation_branch',
                'loan_application_disbursement'
            ).order_by('-id')
        else:
            loans = LoanApplication.objects.filter(
                customer=customer,
                status='disbursed',
                is_deleted=False,
                deleted=False
            ).select_related(
                'loan_application_product',
                'organisation_branch',
                'loan_application_disbursement'
            ).order_by('-id')

        results = []
        for loan in loans:
            principal_bal, interest_bal, penalty_bal, written_off_amount = loan_balance(loan.id)
            total_balance = principal_bal + interest_bal + penalty_bal

            disbursement_date = None
            if hasattr(loan, 'loan_application_disbursement') and loan.loan_application_disbursement:
                disbursement_date = loan.loan_application_disbursement.loan_disbursement_date

            loan_data = {
                'loan_id': loan.id,
                'loan_product': loan.loan_application_product.product_name,
                'loan_amount': float(loan.loan_amount),
                'disbursement_date': disbursement_date,
                'principal_balance': float(principal_bal),
                'interest_balance': float(interest_bal),
                'penalty_balance': float(penalty_bal),
                'total_balance': float(total_balance),
                'loan_officer': loan.loan_officer.name if loan.loan_officer else '',
                'branch': loan.organisation_branch.name if loan.organisation_branch else ''
            }

            if debug:
                loan_data['debug_info'] = {
                    'status': loan.status,
                    'is_deleted': loan.is_deleted,
                    'deleted': loan.deleted
                }

            results.append(loan_data)

        return Response({
            'status': True,
            'customer': {
                'customer_id': customer.id,
                'name': customer.name,
                'member_number': customer.member_number,
                'telephone': customer.telephone or ''
            },
            'count': len(results),
            'loans': results
        })


class OfficerLoanPaymentView(APIView):
    """Register a loan payment"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        from ledgers.models import CashAccounts

        loan_id = request.data.get('loan_id')
        principal_paid = float(request.data.get('principal_paid', 0))
        int_paid = float(request.data.get('int_paid', 0))
        penalty_paid = float(request.data.get('penalty_paid', 0))
        payment_method = request.data.get('payment_method', 'cash')
        account = request.data.get('account')  # Chart ID
        account_id = request.data.get('account_id')  # CashAccounts ID
        transaction_date = request.data.get('transaction_date', date.today().strftime('%Y-%m-%d'))
        notes = request.data.get('notes', '')

        # Validation
        if not loan_id:
            return Response({
                'status': False,
                'message': 'loan_id is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        if not account:
            return Response({
                'status': False,
                'message': 'account (cash account) is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        amount_paid = principal_paid + int_paid + penalty_paid
        if amount_paid <= 0:
            return Response({
                'status': False,
                'message': 'At least one payment amount (principal, interest, or penalty) must be greater than 0'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Get loan
        try:
            loan_application = LoanApplication.objects.get(pk=loan_id, status='disbursed', is_deleted=False)
        except LoanApplication.DoesNotExist:
            return Response({
                'status': False,
                'message': 'Loan not found or not active'
            }, status=status.HTTP_404_NOT_FOUND)

        # Verify payment amounts against balances
        principal_bal, interest_bal, penalty_bal, written_off_amount = loan_balance(loan_id)

        if round(principal_paid, 2) > round(principal_bal, 2):
            return Response({
                'status': False,
                'message': f'Principal amount exceeds balance. Available: {principal_bal:,.2f}'
            }, status=status.HTTP_400_BAD_REQUEST)

        if round(int_paid, 2) > round(interest_bal, 2):
            return Response({
                'status': False,
                'message': f'Interest amount exceeds balance. Available: {interest_bal:,.2f}'
            }, status=status.HTTP_400_BAD_REQUEST)

        if round(penalty_paid, 2) > round(penalty_bal, 2):
            return Response({
                'status': False,
                'message': f'Penalty amount exceeds balance. Available: {penalty_bal:,.2f}'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Get account
        try:
            selected_account = OrganisationSubAccount.objects.get(pk=account)
        except OrganisationSubAccount.DoesNotExist:
            return Response({
                'status': False,
                'message': 'Account not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Process payment
        payment_details = {
            'amount_paid': amount_paid,
            'principal_paid': principal_paid,
            'int_paid': int_paid,
            'penalty_paid': penalty_paid,
            'payment_method': payment_method,
            'account': account,
            'date_added': transaction_date,
            'voucher_no': '',
            'cheque': '',
            'loan_id': loan_id,
            'account_id': account_id,
        }

        try:
            # Check ALL loan schedules (including rescheduled)
            from loans.models import LoanRepaymentSchedule, RescheduledLoans
            all_schedules = LoanRepaymentSchedule.objects.filter(
                loan_application_id=loan_id
            ).order_by('payment_number')
            
            active_schedules = all_schedules.filter(status='active')
            rescheduled_schedules = all_schedules.filter(status='rescheduled')
            
            # Check for rescheduled loan
            reschedule = RescheduledLoans.objects.filter(
                loan_application_id=loan_id
            ).order_by('-id').first()
            
            print(f"\n=== LOAN SCHEDULES CHECK ===")
            print(f"Total schedules: {all_schedules.count()}")
            print(f"Active schedules: {active_schedules.count()}")
            print(f"Rescheduled schedules: {rescheduled_schedules.count()}")
            if reschedule:
                print(f"\nRescheduled Loan Found:")
                print(f"  Principal: {reschedule.principal_amount}, Interest: {reschedule.interest_expected}")
            print(f"\nActive Schedules:")
            for sched in active_schedules[:5]:
                print(f"  Schedule {sched.payment_number}: Principal={sched.principal_expected}, Interest={sched.interest_expected}")
            print(f"\nRescheduled Schedules:")
            for sched in rescheduled_schedules[:5]:
                print(f"  Schedule {sched.payment_number}: Principal={sched.principal_expected}, Interest={sched.interest_expected}")
            print("=" * 50)
            
            # Add detailed logging before payment processing
            print(f"\n=== PAYMENT PROCESSING START ===")
            print(f"Loan ID: {loan_id}")
            print(f"Payment details: {payment_details}")
            print(f"Request user: {request.user}")
            print(f"Request branch: {get_current_user(request, 'organisation_branch_id', None)}")
            print("=" * 50)
            
            payment = process_loan_payment(payment_details, request)
            
            print(f"\n=== PAYMENT PROCESSING RESULT ===")
            print(f"Payment function returned: {payment}")
            print("=" * 50)

            if payment:
                # Verify payment was actually recorded by checking if balances changed
                principal_bal_new, interest_bal_new, penalty_bal_new, _ = loan_balance(loan_id)
                total_balance_new = principal_bal_new + interest_bal_new + penalty_bal_new

                # Check if balances actually decreased
                expected_new_balance = (principal_bal - principal_paid) + (interest_bal - int_paid) + (penalty_bal - penalty_paid)
                
                # Debug balance verification
                print(f"\n=== BALANCE VERIFICATION ===")
                print(f"Before: Principal={principal_bal}, Interest={interest_bal}, Penalty={penalty_bal}")
                print(f"Paid: Principal={principal_paid}, Interest={int_paid}, Penalty={penalty_paid}")
                print(f"After: Principal={principal_bal_new}, Interest={interest_bal_new}, Penalty={penalty_bal_new}")
                print(f"Expected total: {expected_new_balance}, Actual total: {total_balance_new}")
                print(f"Difference: {abs(total_balance_new - expected_new_balance)}")
                print("=" * 50)
                
                # Allow larger rounding difference (up to 10 units) due to schedule splitting
                if abs(total_balance_new - expected_new_balance) > 10:
                    return Response({
                        'status': False,
                        'message': f'Payment processing failed - balances not updated correctly. Expected: {expected_new_balance:.2f}, Got: {total_balance_new:.2f}'
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                return Response({
                    'status': True,
                    'message': 'Loan payment registered successfully',
                    'data': {
                        'loan_id': loan_id,
                        'customer_name': loan_application.customer.name,
                        'loan_product': loan_application.loan_application_product.product_name,
                        'payment': {
                            'principal_paid': principal_paid,
                            'interest_paid': int_paid,
                            'penalty_paid': penalty_paid,
                            'total_paid': amount_paid,
                            'transaction_date': transaction_date,
                            'payment_method': payment_method
                        },
                        'balances': {
                            'principal_balance': float(principal_bal_new),
                            'interest_balance': float(interest_bal_new),
                            'penalty_balance': float(penalty_bal_new),
                            'total_balance': float(total_balance_new)
                        },
                        'processed_by': {
                            'officer_id': request.user.id,
                            'officer_name': request.user.user_staff.name if hasattr(request.user, 'user_staff') else request.user.username,
                            'username': request.user.username
                        }
                    }
                }, status=status.HTTP_201_CREATED)

            return Response({
                'status': False,
                'message': 'Error processing loan payment - payment function returned False'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        except Exception as e:
            import traceback
            error_details = traceback.format_exc()
            print(f"Mobile loan payment error: {error_details}")
            return Response({
                'status': False,
                'message': f'Error processing loan payment: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class OfficerLoanCashAccountsView(APIView):
    """Get teller's active cash accounts"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        cash_accounts = CashAccounts.objects.filter(
            teller=request.user,
            status='active'
        ).select_related('chart')

        results = []
        for cash_account in cash_accounts:
            results.append({
                'id': cash_account.id,
                'chart_id': cash_account.chart.id,
                'account_name': cash_account.chart.account_name,
                'account_code': cash_account.chart.account_code,
            })

        return Response({
            'status': True,
            'count': len(results),
            'cash_accounts': results
        })
