from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from django.utils import timezone
from loans.models import LoanProduct, LoanApplication, Loan
from decimal import Decimal
import random
from faker import Faker
import uuid

User = get_user_model()
fake = Faker()

class Command(BaseCommand):
    help = 'Generate 10 sample clients with 2 loans each'

    def generate_phone_number(self):
        """Generate a valid Kenyan phone number"""
        return f"+254{random.randint(700000000, 799999999)}"

    def generate_id_number(self):
        """Generate a random ID number"""
        return str(random.randint(10000000, 39999999))

    def create_sample_client(self):
        """Create a sample client with realistic data"""
        first_name = fake.first_name()
        last_name = fake.last_name()
        username = f"{first_name.lower()}{random.randint(100, 999)}"
        
        business_types = ['retail', 'agriculture', 'transport', 'manufacturing', 'services', 'technology']
        
        user = User.objects.create_user(
            username=username,
            password='testpass123',
            first_name=first_name,
            last_name=last_name,
            email=f"{username}@example.com",
            phone_number=self.generate_phone_number(),
            id_number=self.generate_id_number(),
            role='borrower',
            date_of_birth=fake.date_of_birth(minimum_age=21, maximum_age=65),
            gender=random.choice(['M', 'F']),
            marital_status=random.choice(['single', 'married', 'divorced', 'widowed']),
            nationality='Kenyan',
            business_name=fake.company(),
            business_type=random.choice(business_types),
            business_address=fake.address(),
            monthly_income=Decimal(str(random.randint(30000, 200000))),
            capital_invested=Decimal(str(random.randint(100000, 1000000))),
            expected_turnover=Decimal(str(random.randint(500000, 2000000))),
            physical_address=fake.street_address(),
            city=random.choice(['Nairobi', 'Mombasa', 'Kisumu', 'Nakuru', 'Eldoret']),
            county=random.choice(['Nairobi', 'Mombasa', 'Kisumu', 'Nakuru', 'Uasin Gishu']),
            postal_code=str(random.randint(10000, 99999))
        )
        return user

    def create_loan_application(self, user, loan_product):
        """Create a sample loan application"""
        # Calculate a realistic loan amount based on income and loan product limits
        income_based_max = user.monthly_income * Decimal('3')
        income_based_min = user.monthly_income * Decimal('0.5')
        
        # Use the more restrictive of the limits
        max_loan = min(income_based_max, loan_product.max_amount)
        min_loan = max(income_based_min, loan_product.min_amount)
        
        # If min_loan > max_loan, use the loan product limits
        if min_loan > max_loan:
            min_loan = loan_product.min_amount
            max_loan = loan_product.max_amount
        
        requested_amount = Decimal(str(random.randint(
            int(min_loan),
            int(max_loan)
        )))
        
        application = LoanApplication.objects.create(
            borrower=user,
            loan_product=loan_product,
            requested_amount=requested_amount,
            requested_duration=random.randint(
                loan_product.min_duration,
                loan_product.max_duration
            ),
            purpose=random.choice([
                'Business expansion',
                'Working capital',
                'Equipment purchase',
                'Stock purchase',
                'Emergency funds'
            ]),
            repayment_method=random.choice(['daily', 'weekly', 'monthly']),
            status='approved',
            application_number=f"LA{str(uuid.uuid4())[:8].upper()}",
            submitted_at=timezone.now() - timezone.timedelta(days=random.randint(1, 30))
        )
        
        # Calculate amounts
        application.interest_amount = (application.requested_amount * loan_product.interest_rate / Decimal('100'))
        application.processing_fee_amount = (application.requested_amount * loan_product.processing_fee / Decimal('100'))
        application.total_amount = application.requested_amount + application.interest_amount + application.processing_fee_amount
        application.save()
        
        return application

    def create_loan(self, application):
        """Create an active loan from an approved application"""
        # Set disbursement date in the past
        disbursement_date = application.submitted_at + timezone.timedelta(days=random.randint(1, 5))
        
        loan = Loan.objects.create(
            application=application,
            borrower=application.borrower,
            loan_number=f"L{str(uuid.uuid4())[:8].upper()}",
            principal_amount=application.requested_amount,
            interest_amount=application.interest_amount,
            processing_fee=application.processing_fee_amount,
            total_amount=application.total_amount,
            disbursement_date=disbursement_date,
            due_date=disbursement_date + timezone.timedelta(days=application.requested_duration),
            duration_days=application.requested_duration,
            status=random.choice(['active', 'active', 'active', 'paid'])  # 75% chance of being active
        )
        
        # If loan is paid, add some repayments
        if loan.status == 'paid':
            loan.amount_paid = loan.total_amount
            loan.last_payment_date = timezone.now() - timezone.timedelta(days=random.randint(1, 10))
            loan.save()
        else:
            # For active loans, add some partial repayments
            paid_percentage = random.uniform(0.2, 0.8)  # Pay between 20% and 80%
            loan.amount_paid = loan.total_amount * Decimal(str(paid_percentage))
            loan.last_payment_date = timezone.now() - timezone.timedelta(days=random.randint(1, 10))
            loan.save()
        
        return loan

    def handle(self, *args, **options):
        # Get existing loan products
        loan_products = LoanProduct.objects.filter(product_type__in=['boost', 'boost_plus', 'mwamba', 'imara'])
        if not loan_products.exists():
            self.stdout.write(self.style.ERROR('No loan products found! Please create loan products first.'))
            return
        
        # Create 10 sample clients
        self.stdout.write('Creating sample clients...')
        clients = []
        for i in range(10):
            client = self.create_sample_client()
            clients.append(client)
            self.stdout.write(f'Created client {i+1}/10: {client.get_full_name()}')
        
        # Create 2 loans for each client
        self.stdout.write('\nCreating loans for clients...')
        for client in clients:
            # Create first loan
            loan_product1 = random.choice(loan_products)
            application1 = self.create_loan_application(client, loan_product1)
            loan1 = self.create_loan(application1)
            self.stdout.write(f'Created loan 1 ({loan_product1.name}) for {client.get_full_name()}: {loan1.loan_number}')
            
            # Create second loan
            loan_product2 = random.choice(loan_products)
            application2 = self.create_loan_application(client, loan_product2)
            loan2 = self.create_loan(application2)
            self.stdout.write(f'Created loan 2 ({loan_product2.name}) for {client.get_full_name()}: {loan2.loan_number}')
        
        # Print summary
        total_loans = Loan.objects.filter(borrower__in=clients).count()
        active_loans = Loan.objects.filter(borrower__in=clients, status='active').count()
        paid_loans = Loan.objects.filter(borrower__in=clients, status='paid').count()
        
        self.stdout.write(self.style.SUCCESS(f'''
Successfully generated sample data:
- Created 10 clients
- Created {total_loans} total loans
  - {active_loans} active loans
  - {paid_loans} paid loans
'''))