"""
Order views for creating and managing orders
"""
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from cart.models import Cart, CartItem
from orders.models import Order, OrderItem


def generate_order_number():
    """
    Generate a unique order number
    Format: 2 capital letters + 8 digits + 2 capital letters
    Example: AB12345678CD
    """
    import random
    import string
    
    # Generate 2 random capital letters
    prefix = ''.join(random.choices(string.ascii_uppercase, k=2))
    
    # Generate 8 random digits
    digits = ''.join(random.choices(string.digits, k=8))
    
    return f"{prefix}{digits}"


def create_order(request):
    """Create order from cart"""
    if request.method != 'POST':
        return redirect('frontend:checkout')
    
    # Only allow authenticated users to create orders
    if not request.user.is_authenticated:
        messages.error(request, 'Please login to place an order.')
        return redirect('frontend:login')
    
    # Get cart
    cart = Cart.objects.filter(user=request.user).first()
    
    if not cart or not cart.items.exists():
        messages.error(request, 'Your cart is empty!')
        return redirect('frontend:cart')
    
    # Get form data
    shipping_data = {
        'first_name': request.POST.get('first_name', ''),
        'last_name': request.POST.get('last_name', ''),
        'email': request.POST.get('email', ''),
        'phone': request.POST.get('phone', ''),
        'address': request.POST.get('address', ''),
        'city': request.POST.get('city', ''),
        'state': request.POST.get('state', ''),
        'pincode': request.POST.get('pincode', ''),
    }
    same_as_shipping = request.POST.get('same_as_shipping', 'on') == 'on'
    
    billing_data = {
        'first_name': request.POST.get('billing_first_name', ''),
        'last_name': request.POST.get('billing_last_name', ''),
        'phone': request.POST.get('billing_phone', ''),
        'address': request.POST.get('billing_address', ''),
        'city': request.POST.get('billing_city', ''),
        'state': request.POST.get('billing_state', ''),
        'pincode': request.POST.get('billing_pincode', ''),
    }
    
    # Validate required fields
    required_fields = ['first_name', 'last_name', 'email', 'phone', 'address', 'city', 'state', 'pincode']
    for field in required_fields:
        if not shipping_data[field]:
            messages.error(request, f"Please provide {field.replace('_', ' ').title()}")
            return redirect('frontend:checkout')
    
    if not same_as_shipping:
        billing_required_fields = ['first_name', 'last_name', 'phone', 'address', 'city', 'state', 'pincode']
        for field in billing_required_fields:
            if not billing_data[field]:
                messages.error(request, f"Please provide billing {field.replace('_', ' ').title()}")
                return redirect('frontend:checkout')
    
    payment_method = request.POST.get('payment_method', 'cod')
    
    try:
        # Generate unique order number
        order_number = generate_order_number()
        
        # Create or get an address for the user
        from accounts.models import Address
        
        full_name = f"{shipping_data['first_name']} {shipping_data['last_name']}".strip()
        
        # Try to find existing address or create new one
        shipping_address, created = Address.objects.get_or_create(
            user=request.user,
            address_line1=shipping_data['address'],
            city=shipping_data['city'],
            state=shipping_data['state'],
            pincode=shipping_data['pincode'],
            defaults={
                'full_name': full_name,
                'phone': shipping_data['phone'],
                'country': 'India',
                'is_default': False,
            }
        )
        
        if same_as_shipping:
            billing_address = shipping_address
        else:
            billing_full_name = f"{billing_data['first_name']} {billing_data['last_name']}".strip()
            billing_address, _ = Address.objects.get_or_create(
                user=request.user,
                address_line1=billing_data['address'],
                city=billing_data['city'],
                state=billing_data['state'],
                pincode=billing_data['pincode'],
                defaults={
                    'full_name': billing_full_name,
                    'phone': billing_data['phone'],
                    'country': 'India',
                    'is_default': False,
                }
            )
        
        # Create the order
        order = Order.objects.create(
            order_number=order_number,
            order_code=order_number,
            user=request.user,
            shipping_address=shipping_address,
            billing_address=billing_address,
            payment_method=payment_method,
            subtotal=cart.subtotal,
            shipping_cost=cart.shipping_cost,  # Use cart's calculated shipping
            tax=cart.tax,  # Use cart's calculated tax
            total=cart.total,
            status=Order.OrderStatus.PENDING,
            is_paid=False  # Will be updated after payment verification
        )
        
        # Create order items from cart
        for cart_item in cart.items.all():
            OrderItem.objects.create(
                order=order,
                product=cart_item.product,
                product_name=cart_item.product.name,
                product_sku=cart_item.product.sku,
                quantity=cart_item.quantity,
                unit_price=cart_item.unit_price,
                total_price=cart_item.total_price,
                variation=cart_item.variation
            )
        
        # Clear cart
        cart.items.all().delete()
        
        # Handle different payment methods
        if payment_method == 'online':
            # For online payment, redirect to payment page
            # TODO: Integrate Razorpay/Stripe when configured
            messages.warning(request, 'Online payment is coming soon! Order placed with COD.')
            order.payment_method = 'cod'  # Fallback to COD for now
            order.save()
        
        messages.success(request, f'Order {order.order_code} placed successfully!')
        
        # Redirect to success page
        return redirect('orders:order_success', order_id=order.id)
        
    except Exception as e:
        messages.error(request, f'Error creating order: {str(e)}')
        return redirect('frontend:checkout')


def order_success(request, order_id):
    """Order success page"""
    try:
        order = Order.objects.get(id=order_id)
        
        # Ensure user can only view their own orders
        if not request.user.is_authenticated or (order.user and order.user != request.user):
            messages.error(request, 'Order not found!')
            return redirect('frontend:index')
            
        return render(request, 'orders/success.html', {'order': order})
    except Order.DoesNotExist:
        messages.error(request, 'Order not found!')
        return redirect('frontend:index')


@login_required
def order_invoice(request, order_code):
    """Generate invoice for order"""
    order = get_object_or_404(Order, Q(order_code=order_code) | Q(order_number=order_code))
    
    # Check permissions (user owns order OR user is vendor for some items OR user is staff)
    is_owner = order.user == request.user
    is_staff = request.user.is_staff or request.user.is_superuser
    
    # Check if user is a vendor and has items in this order
    is_vendor = hasattr(request.user, 'vendor_profile')
    vendor_items = []
    if is_vendor:
        vendor_items = OrderItem.objects.filter(order=order, product__vendor=request.user.vendor_profile)
        if vendor_items.exists():
            is_vendor_for_order = True
        else:
            is_vendor_for_order = False
    else:
        is_vendor_for_order = False

    if not (is_owner or is_staff or is_vendor_for_order):
        messages.error(request, 'You do not have permission to view this invoice.')
        return redirect('frontend:index')
    
    vendor_total = 0
    vendor_tax = 0
    vendor_grand_total = 0
    invoice_vendor = None
    
    # Get tax rate
    try:
        from ai_features.models import AIConfiguration
        config = AIConfiguration.get_settings()
        tax_rate = getattr(config, 'tax_rate_percent', 18)
    except:
        tax_rate = 18
    
    if is_vendor_for_order and not is_staff and not is_owner:
        # Vendor View: Show only vendor's items
        for item in vendor_items:
            vendor_total += item.total_price
        
        # Calculate tax for vendor items
        from decimal import Decimal
        vendor_tax = vendor_total * (Decimal(str(tax_rate)) / Decimal('100'))
        
        # Check vendor's billing policy
        vendor = request.user.vendor_profile
        if vendor.billing_policy == 'VENDOR':
            invoice_vendor = vendor
            # If vendor handles billing, they might handle shipping too
            # For now, we'll just add the order's shipping cost if it exists
            # (Assuming simple single-vendor order or vendor handles all shipping)
            # Refinement: Only add shipping if this vendor is the ONLY vendor?
            # Or just show what the customer paid.
            pass
        else:
            invoice_vendor = None # Show Platform details
            
        vendor_grand_total = vendor_total + vendor_tax
        if invoice_vendor and order.shipping_cost > 0:
             vendor_grand_total += order.shipping_cost
            
    else:
        # Admin/Customer View: Show all items
        # Check if the order belongs to a single vendor
        from vendors.models import Vendor
        distinct_vendors = Vendor.objects.filter(products__orderitem__order=order).distinct()
        
        if distinct_vendors.count() == 1:
            vendor = distinct_vendors.first()
            if vendor.billing_policy == 'VENDOR':
                invoice_vendor = vendor
            else:
                invoice_vendor = None # Show Platform details
        else:
            # Mixed vendors or no vendor -> Platform Billing
            invoice_vendor = None

    context = {
        'order': order,
        'items': vendor_items if (is_vendor_for_order and not is_staff and not is_owner) else order.items.all(),
        'is_vendor_view': is_vendor_for_order and not is_staff and not is_owner,
        'vendor_total': vendor_total,
        'vendor_tax': vendor_tax,
        'vendor_grand_total': vendor_grand_total,
        'invoice_vendor': invoice_vendor,
    }
    
    return render(request, 'orders/invoice.html', context)
