"""
Integration tests for payment workflow
"""
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.utils import timezone
from decimal import Decimal
from datetime import timedelta

from igny8_core.auth.models import Account, Plan, Subscription
from igny8_core.business.billing.models import Invoice, Payment
from igny8_core.business.billing.services.invoice_service import InvoiceService

User = get_user_model()


class PaymentWorkflowIntegrationTest(TestCase):
    """Test complete payment workflow including invoice.subscription FK"""
    
    def setUp(self):
        """Create test data"""
        # Create plan
        self.plan = Plan.objects.create(
            name='Test Plan',
            slug='test-plan',
            price=Decimal('29.00'),
            included_credits=1000,
            max_sites=5,
        )
        
        # Create account
        self.account = Account.objects.create(
            name='Test Account',
            slug='test-account',
            status='pending_payment',
            billing_country='US',
            billing_email='test@example.com',
        )
        
        # Create user
        self.user = User.objects.create_user(
            username='testuser',
            email='testuser@example.com',
            password='testpass123',
            account=self.account,
        )
        
        # Create subscription
        billing_period_start = timezone.now()
        billing_period_end = billing_period_start + timedelta(days=30)
        
        self.subscription = Subscription.objects.create(
            account=self.account,
            plan=self.plan,
            status='pending_payment',
            current_period_start=billing_period_start,
            current_period_end=billing_period_end,
        )
    
    def test_invoice_subscription_fk_relationship(self):
        """Test that invoice.subscription FK works correctly"""
        # Create invoice via service
        billing_period_start = timezone.now()
        billing_period_end = billing_period_start + timedelta(days=30)
        
        invoice = InvoiceService.create_subscription_invoice(
            subscription=self.subscription,
            billing_period_start=billing_period_start,
            billing_period_end=billing_period_end,
        )
        
        # Verify FK relationship
        self.assertIsNotNone(invoice.subscription)
        self.assertEqual(invoice.subscription.id, self.subscription.id)
        self.assertEqual(invoice.subscription.plan.id, self.plan.id)
        
        # Verify can access subscription from invoice
        self.assertEqual(invoice.subscription.account, self.account)
        self.assertEqual(invoice.subscription.plan.name, 'Test Plan')
    
    def test_payment_approval_with_subscription(self):
        """Test payment approval workflow uses invoice.subscription"""
        # Create invoice
        billing_period_start = timezone.now()
        billing_period_end = billing_period_start + timedelta(days=30)
        
        invoice = InvoiceService.create_subscription_invoice(
            subscription=self.subscription,
            billing_period_start=billing_period_start,
            billing_period_end=billing_period_end,
        )
        
        # Create payment
        payment = Payment.objects.create(
            account=self.account,
            invoice=invoice,
            amount=invoice.total,
            currency='USD',
            status='pending_approval',
            payment_method='bank_transfer',
            manual_reference='TEST-REF-001',
        )
        
        # Verify payment links to invoice which links to subscription
        self.assertIsNotNone(payment.invoice)
        self.assertIsNotNone(payment.invoice.subscription)
        self.assertEqual(payment.invoice.subscription.id, self.subscription.id)
        
        # Simulate approval workflow
        payment.status = 'succeeded'
        payment.approved_by = self.user
        payment.approved_at = timezone.now()
        payment.save()
        
        # Update related records
        invoice.status = 'paid'
        invoice.paid_at = timezone.now()
        invoice.save()
        
        subscription = invoice.subscription
        subscription.status = 'active'
        subscription.save()
        
        # Verify workflow completed successfully
        self.assertEqual(payment.status, 'succeeded')
        self.assertEqual(invoice.status, 'paid')
        self.assertEqual(subscription.status, 'active')
        self.assertEqual(subscription.plan.included_credits, 1000)
    
    def test_subscription_dates_not_null_for_paid_plans(self):
        """Test that subscription dates are set for paid plans"""
        self.assertIsNotNone(self.subscription.current_period_start)
        self.assertIsNotNone(self.subscription.current_period_end)
        
        # Verify dates are in future
        self.assertGreater(self.subscription.current_period_end, self.subscription.current_period_start)
    
    def test_invoice_currency_based_on_country(self):
        """Test that invoice currency is set based on billing country"""
        # Test US -> USD
        self.account.billing_country = 'US'
        self.account.save()
        
        billing_period_start = timezone.now()
        billing_period_end = billing_period_start + timedelta(days=30)
        
        invoice_us = InvoiceService.create_subscription_invoice(
            subscription=self.subscription,
            billing_period_start=billing_period_start,
            billing_period_end=billing_period_end,
        )
        self.assertEqual(invoice_us.currency, 'USD')
        
        # Test GB -> GBP
        self.account.billing_country = 'GB'
        self.account.save()
        
        invoice_gb = InvoiceService.create_subscription_invoice(
            subscription=self.subscription,
            billing_period_start=billing_period_start,
            billing_period_end=billing_period_end,
        )
        self.assertEqual(invoice_gb.currency, 'GBP')
        
        # Test IN -> INR
        self.account.billing_country = 'IN'
        self.account.save()
        
        invoice_in = InvoiceService.create_subscription_invoice(
            subscription=self.subscription,
            billing_period_start=billing_period_start,
            billing_period_end=billing_period_end,
        )
        self.assertEqual(invoice_in.currency, 'INR')
    
    def test_invoice_due_date_grace_period(self):
        """Test that invoice due date uses grace period instead of billing_period_end"""
        billing_period_start = timezone.now()
        billing_period_end = billing_period_start + timedelta(days=30)
        
        invoice = InvoiceService.create_subscription_invoice(
            subscription=self.subscription,
            billing_period_start=billing_period_start,
            billing_period_end=billing_period_end,
        )
        
        # Verify due date is invoice_date + 7 days (grace period)
        expected_due_date = invoice.invoice_date + timedelta(days=7)
        self.assertEqual(invoice.due_date, expected_due_date)
        
        # Verify it's NOT billing_period_end
        self.assertNotEqual(invoice.due_date, billing_period_end.date())
