"""
Discount management views and utilities for the shopping app.
Handles discount application, validation, and order calculations.
"""

from decimal import Decimal
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.utils import timezone

from .models import Discount, Order, Cart, CartItem


def get_applicable_discounts(cart):
    """Get all discounts applicable to items in the cart"""
    if not cart.items.exists():
        return []
    
    applicable = []
    for item in cart.items.all():
        discount = item.product.get_active_discount()
        if discount and discount not in applicable:
            applicable.append(discount)
    
    return applicable


def calculate_cart_totals(cart, discount=None):
    """
    Calculate cart totals with optional discount
    Returns: {
        'subtotal': decimal,
        'discount_amount': decimal,
        'total': decimal,
        'items_count': int,
        'discount': Discount or None
    }
    """
    subtotal = Decimal('0')
    
    for item in cart.items.all():
        # Get product discount
        product_discount = item.product.get_active_discount()
        if product_discount:
            item_price = product_discount.calculate_discounted_price(item.product.price)
        else:
            item_price = item.product.price
        
        subtotal += item_price * item.quantity
    
    discount_amount = Decimal('0')
    applied_discount = None
    
    # Check if an order-level discount can be applied
    if discount and discount.is_valid():
        if subtotal >= discount.min_purchase:
            discount_amount = discount.calculate_discount_amount(subtotal)
            applied_discount = discount
    
    total = subtotal - discount_amount
    
    return {
        'subtotal': subtotal,
        'discount_amount': discount_amount,
        'total': max(total, Decimal('0')),
        'items_count': sum(item.quantity for item in cart.items.all()),
        'discount': applied_discount,
    }


@login_required
@require_POST
def apply_discount_code(request):
    """
    Apply a discount code to the user's cart
    POST parameters: code
    Returns: JSON response
    """
    code = request.POST.get('code', '').strip().upper()
    
    if not code:
        return JsonResponse({
            'success': False,
            'message': 'Please enter a discount code.'
        }, status=400)
    
    try:
        discount = Discount.objects.get(code__iexact=code)
    except Discount.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': f'Discount code "{code}" not found.'
        }, status=404)
    
    # Validate discount
    if not discount.is_valid():
        return JsonResponse({
            'success': False,
            'message': f'Discount code "{code}" is no longer valid.'
        }, status=400)
    
    # Check per-user limit
    if not discount.can_user_use(request.user):
        return JsonResponse({
            'success': False,
            'message': f'You have already used this discount code the maximum number of times.'
        }, status=400)
    
    # Store in session
    request.session['applied_discount_id'] = discount.id
    
    # Get updated cart totals
    cart = Cart.objects.get(user=request.user)
    totals = calculate_cart_totals(cart, discount)
    
    return JsonResponse({
        'success': True,
        'message': f'Discount code "{code}" applied successfully!',
        'discount': {
            'name': discount.name,
            'value': str(discount.discount_value),
            'type': discount.get_discount_type_display(),
        },
        'totals': {
            'subtotal': str(totals['subtotal']),
            'discount_amount': str(totals['discount_amount']),
            'total': str(totals['total']),
        }
    })


@login_required
@require_POST
def remove_discount_code(request):
    """Remove the applied discount code from the cart"""
    if 'applied_discount_id' in request.session:
        del request.session['applied_discount_id']
        request.session.modified = True
        
        return JsonResponse({
            'success': True,
            'message': 'Discount code removed.'
        })
    
    return JsonResponse({
        'success': False,
        'message': 'No discount code applied.'
    }, status=400)


def get_applied_discount(request):
    """Get the currently applied discount from session"""
    if not request.user.is_authenticated:
        return None
    
    discount_id = request.session.get('applied_discount_id')
    if not discount_id:
        return None
    
    try:
        discount = Discount.objects.get(id=discount_id)
        if discount.is_valid() and discount.can_user_use(request.user):
            return discount
    except Discount.DoesNotExist:
        pass
    
    # Clear invalid discount from session
    if 'applied_discount_id' in request.session:
        del request.session['applied_discount_id']
        request.session.modified = True
    
    return None


def get_product_discount_info(product):
    """Get discount info for a specific product (for display on product pages)"""
    discount = product.get_active_discount()
    
    if not discount:
        return {
            'has_discount': False,
            'original_price': product.price,
            'discounted_price': product.price,
            'discount_amount': Decimal('0'),
            'discount_percent': 0,
        }
    
    original_price = product.price
    discount_amount = discount.calculate_discount_amount(original_price)
    discounted_price = discount.calculate_discounted_price(original_price)
    
    if discount.discount_type == 'percentage':
        discount_percent = discount.discount_value
    else:
        discount_percent = (discount_amount / original_price * 100) if original_price > 0 else 0
    
    return {
        'has_discount': True,
        'original_price': original_price,
        'discounted_price': discounted_price,
        'discount_amount': discount_amount,
        'discount_percent': int(discount_percent),
        'discount_name': discount.name,
    }
