"""
Simple test for rolled-over loans properties without Hypothesis
"""

from django.test import TestCase
from django.utils import timezone
from datetime import timedelta
from decimal import Decimal

from loans.models import Loan, LoanProduct, LoanApplication
from users.models import CustomUser


class TestRolledOverLoansSimple(TestCase):
    """Simple tests for rolled-over loans properties"""
    
    def setUp(self):
        """Set up test data"""
        # Create test user
        self.user = CustomUser.objects.create_user(
            username='testuser',
            email='test@example.com',
            phone_number='+254700000000',
            first_name='Test',
            last_name='User',
            role='borrower'
        )
        
        # Create test loan product
        self.product = LoanProduct.objects.create(
            name='Test Product',
            product_type='boost',
            description='Test product',
            min_amount=Decimal('1000'),
            max_amount=Decimal('50000'),
            interest_rate=Decimal('10.0'),
            processing_fee=Decimal('5.0'),
            min_duration=7,
            max_duration=90,
            available_repayment_methods=['monthly']
        )
    
    def create_loan(self, is_rolled_over=False, is_deleted=False, status='active'):
        """Helper to create a loan with specified properties"""
        # Create application
        application = LoanApplication.objects.create(
            borrower=self.user,
            loan_product=self.product,
            requested_amount=Decimal('10000'),
            requested_duration=30,
            purpose='Test loan',
            status='approved'
        )
        
        # Create loan
        loan = Loan.objects.create(
            application=application,
            borrower=self.user,
            principal_amount=Decimal('10000'),
            interest_amount=Decimal('1000'),
            processing_fee=Decimal('500'),
            total_amount=Decimal('11500'),
            disbursement_date=timezone.now(),
            due_date=timezone.now() + timedelta(days=30),
            duration_days=30,
            status=status,
            is_rolled_over=is_rolled_over,
            is_deleted=is_deleted
        )
        
        return loan
    
    def test_property_14_rolled_over_loans_page_exclusivity(self):
        """
        Feature: reports-system-enhancement, Property 14: Rolled-over loans page exclusivity
        Validates: Requirements 4.5
        
        For any loan displayed on the rolled-over loans page, it should have either
        status equal to 'rolled_over' OR is_rolled_over flag equal to true.
        """
        # Create 3 rolled-over loans
        rolled_over_loans = []
        for i in range(3):
            loan = self.create_loan(is_rolled_over=True, status='rolled_over')
            rolled_over_loans.append(loan)
        
        # Create 2 active loans (should not appear)
        active_loans = []
        for i in range(2):
            loan = self.create_loan(is_rolled_over=False, status='active')
            active_loans.append(loan)
        
        # Create 1 paid loan (should not appear)
        paid_loan = self.create_loan(is_rolled_over=False, status='paid')
        
        # Query for rolled-over loans (simulating the view logic)
        queryset = Loan.objects.filter(status='rolled_over') | Loan.objects.filter(is_rolled_over=True)
        queryset = queryset.distinct()
        
        # Property: All returned loans should be rolled over
        for loan in queryset:
            self.assertTrue(
                loan.status == 'rolled_over' or loan.is_rolled_over,
                f"Loan {loan.loan_number} appears in rolled-over page but is not rolled over"
            )
        
        # Property: All rolled-over loans should be in the result
        self.assertEqual(
            queryset.count(),
            3,
            f"Expected 3 rolled-over loans, got {queryset.count()}"
        )
        
        # Property: No active or paid loans should appear
        for loan in active_loans:
            self.assertNotIn(loan, queryset, f"Active loan {loan.loan_number} should not appear")
        
        self.assertNotIn(paid_loan, queryset, f"Paid loan {paid_loan.loan_number} should not appear")
    
    def test_property_29_rollover_statistics_exclusion(self):
        """
        Feature: reports-system-enhancement, Property 29: Rollover statistics exclusion
        Validates: Requirements 11.5
        
        For any rollover statistics calculation, loans with is_deleted flag set to true
        should not contribute to the statistics.
        """
        # Create 3 active rolled-over loans (should be included in statistics)
        active_rolled_over = []
        for i in range(3):
            loan = self.create_loan(is_rolled_over=True, is_deleted=False, status='rolled_over')
            active_rolled_over.append(loan)
        
        # Create 2 deleted rolled-over loans (should be excluded from statistics)
        deleted_rolled_over = []
        for i in range(2):
            loan = self.create_loan(is_rolled_over=True, is_deleted=True, status='rolled_over')
            deleted_rolled_over.append(loan)
        
        # Query for rollover statistics (excluding deleted)
        stats_queryset = Loan.objects.filter(
            status='rolled_over',
            is_deleted=False
        )
        
        # Property: Count should only include non-deleted rolled-over loans
        self.assertEqual(
            stats_queryset.count(),
            3,
            f"Statistics should include 3 loans, got {stats_queryset.count()}"
        )
        
        # Property: No deleted loans should be in statistics
        for loan in deleted_rolled_over:
            self.assertNotIn(
                loan,
                stats_queryset,
                f"Deleted loan {loan.loan_number} should not be in statistics"
            )
        
        # Property: All active rolled-over loans should be in statistics
        for loan in active_rolled_over:
            self.assertIn(
                loan,
                stats_queryset,
                f"Active rolled-over loan {loan.loan_number} should be in statistics"
            )
        
        # Calculate total amount (simulating statistics calculation)
        total_amount = sum(loan.principal_amount for loan in stats_queryset)
        expected_total = sum(loan.principal_amount for loan in active_rolled_over)
        
        # Property: Total amount should only include non-deleted loans
        self.assertEqual(
            total_amount,
            expected_total,
            f"Total amount should be {expected_total}, got {total_amount}"
        )
