from .stripe_utils import stripe_service
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from .models import Product, Order, OrderItem, GuestUser, OrderStatus
from django.db.models import Sum
from .forms import GuestCheckoutForm
import stripe
from django.conf import settings
from django.urls import reverse
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

from . import cart

# Shared helper methods
def _check_stripe_config():
    """Check if Stripe API keys are properly configured"""
    return hasattr(settings, 'STRIPE_SECRET_KEY') and settings.STRIPE_SECRET_KEY

def _create_stripe_line_items(order_items):
    """Create line items for Stripe checkout from order items"""
    line_items = []
    for item in order_items:
        item_price = int(float(item.price) * 100)  # Convert to cents

        line_items.append({
            'price_data': {
                'currency': 'eur',
                'product_data': {
                    'name': item.product.title,
                    'description': f"Color: {item.color.name if item.color else 'N/A'}, Size: {item.size.name if item.size else 'N/A'}",
                },
                'unit_amount': item_price,
            },
            'quantity': item.quantity,
        })
    return line_items

def _create_stripe_checkout_session(request, order, line_items):
    """Create a Stripe checkout session for the order"""
    # Create success and cancel URLs
    success_url = request.build_absolute_uri(reverse('shop:payment_success', args=[order.id]))
    cancel_url = request.build_absolute_uri(reverse('shop:payment_cancel', args=[order.id]))

    # Create metadata to identify this order
    metadata = {
        'order_id': str(order.id),
    }

    # Set up customer information
    customer_email = None

    # Add user info to metadata if available
    if request.user.is_authenticated:
        metadata['user_id'] = str(request.user.id)
        customer_email = request.user.email
    elif order.guest_user:
        metadata['guest_email'] = order.guest_user.email
        customer_email = order.guest_user.email
    elif 'guest_email' in request.session:
        metadata['guest_email'] = request.session.get('guest_email', '')
        customer_email = request.session.get('guest_email', '')

    try:
        # Use the service to create the session
        checkout_session = stripe_service.create_checkout_session(
            customer_email=customer_email,
            line_items=line_items,
            success_url=success_url,
            cancel_url=cancel_url,
            metadata=metadata,
        )

        # Save the checkout session ID to the order
        order.stripe_checkout_session_id = checkout_session.id
        order.save()

        return checkout_session

    except Exception as e:
        print(f"Stripe error: {str(e)}")
        raise

# View functions
def product_list(request):
    products = Product.objects.all()
    cart_items = cart.get_cart_items(request)
    total = cart.get_cart_total(request)
    return render(request, 'shop/product_list.html', {
        'products': products,
        'cart_items': cart_items,
        'total': total
    })

def view_cart(request):
    """Display the shopping cart"""
    cart_items = cart.get_cart_items(request)
    total = cart.get_cart_total(request)
    total_quantity = cart_items.aggregate(total_quantity=Sum('quantity'))['total_quantity']
    display_data = prepare_item_display_data(cart_items, is_cart=True)
    context = {
        'display_data': display_data,
        'total': total,
        'total_quantity': total_quantity,
        'settings': settings,  # Add this line to pass settings to template
    }

    # Add Stripe publishable key for authenticated users
    if request.user.is_authenticated:
        context['stripe_publishable_key'] = settings.STRIPE_PUBLISHABLE_KEY

    return render(request, 'shop/cart.html', context)

@ensure_csrf_cookie
def add_to_cart_view(request, product_id):
    """Add a product to the cart"""
    product = get_object_or_404(Product, id=product_id)
    quantity = int(request.POST.get('quantity', 1))
    color_id = request.POST.get('color')
    size_id = request.POST.get('size')

    cart_item = cart.add_to_cart(request, product_id, quantity, color_id, size_id)
    message = f'{cart_item.quantity} x {product.title} dans le panier',

    # Check if this is an AJAX request
    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        cart_items = cart.get_cart_items(request)
        total = cart.get_cart_total(request)
        return JsonResponse({
            'success': True,
            'message': message,
            'cart_total': total,
            'cart_count': cart_items.count()
        })

    # For non-AJAX requests, fall back to the original behavior
    messages.success(request, message)
    return redirect('shop:product_list')

def update_cart_view(request, product_id):
    """Update cart item quantity"""
    if request.method == 'POST':
        quantity = int(request.POST.get('quantity', 0))
        cart.update_cart_item(request, product_id, quantity)
    return redirect('shop:view_cart')

def remove_from_cart_view(request, product_id):
    """Remove item from cart"""
    cart.remove_from_cart(request, product_id)
    return redirect('shop:view_cart')

def clear_cart(request):
    """Clear the cart"""
    cart.clear_cart(request)
    messages.success(request, "Your cart has been cleared.")
    return redirect('shop:product_list')

def create_order(request):
    """Create an order from the current cart"""
    cart_items = cart.get_cart_items(request)

    # Check if cart is empty
    if not cart_items.exists():
        return None

    total_price = sum(item.get_total_price() for item in cart_items)

    # Check if total price is valid
    if total_price <= 0:
        return None

    if request.user.is_authenticated:
        # Authenticated user order
        order = Order.objects.create(
            user=request.user,
            total_price=total_price,
            stripe_mode=stripe_service.mode  # Add this line

        )
    else:
        # Guest user order
        try:
            guest_user = GuestUser.objects.get(email=request.session['guest_email'])
            order = Order.objects.create(
                guest_user=guest_user,
                total_price=total_price,
                stripe_mode=stripe_service.mode  # Add this line

            )
        except (KeyError, GuestUser.DoesNotExist):
            # No guest user information, create order without user
            order = Order.objects.create(
                total_price=total_price,
                stripe_mode=stripe_service.mode  # Add this line
            )

    # Create order items
    for cart_item in cart_items:
        OrderItem.objects.create(
            order=order,
            product=cart_item.product,
            quantity=cart_item.quantity,
            color=cart_item.color,
            size=cart_item.size,
            price=cart_item.product.price
        )

    # Note: Cart is not cleared here, only after successful payment
    return order

def checkout(request):
    """Handle checkout process for both authenticated and guest users"""
    # Check if cart is empty
    cart_items = cart.get_cart_items(request)
    if not cart_items.exists():
        messages.error(request, "Your cart is empty. Please add items before checkout.")
        return redirect('shop:product_list')

    if request.user.is_authenticated:
        # Create order for authenticated user and go directly to payment
        return _handle_authenticated_checkout(request)

    # Handle guest checkout
    if request.method == 'GET':
        form = GuestCheckoutForm()
        return render(request, 'shop/checkout.html', {'form': form})
    elif request.method == 'POST':
        return _handle_guest_checkout_post(request)

    return redirect('shop:product_list')

def _handle_authenticated_checkout(request):
    """Helper function to handle checkout for authenticated users"""
    order = create_order(request)

    if not order:
        messages.error(request, "There was an issue creating your order. Please try again.")
        return redirect('shop:view_cart')

    return redirect('shop:payment', order_id=order.id)

def _handle_guest_checkout_post(request):
    """Helper function to handle POST requests for guest checkout"""
    form = GuestCheckoutForm(request.POST)
    if form.is_valid():
        # Create or get guest user
        email = form.cleaned_data['email']
        phone = form.cleaned_data['phone']
        guest_user, created = GuestUser.objects.get_or_create(
            email=email,
            defaults={'phone': phone}
        )

        # Store email in session
        request.session['guest_email'] = email

        # Create order
        order = create_order(request)

        if not order:
            messages.error(request, "There was an issue creating your order. Please try again.")
            return redirect('shop:view_cart')

        return redirect('shop:payment', order_id=order.id)

    # Form invalid
    return render(request, 'shop/checkout.html', {'form': form})

def payment(request, order_id):
    """Handle payment for an existing order"""
    order = get_object_or_404(Order, id=order_id)
    order.status = OrderStatus.PENDING
    order.payment_status = 'PENDING'
    order_items = order.items.all()

    # Check for valid order
    if not order_items.exists() or order.total_price <= 0:
        messages.error(request, "Cannot process an empty order.")
        return redirect('shop:product_list')

    # Log payment processing
    print(f"Processing payment for order #{order_id}, total: {order.total_price}")

    # Check Stripe configuration
    if not _check_stripe_config():
        messages.error(request, "Stripe API keys not configured properly.")
        return redirect('shop:view_cart')

    # Create line items
    line_items = _create_stripe_line_items(order_items)

    if not line_items:
        messages.error(request, "Cannot create payment with no items.")
        return redirect('shop:view_cart')

    # Create checkout session
    try:
        checkout_session = _create_stripe_checkout_session(request, order, line_items)
        checkout_session_id = checkout_session.id
    except Exception as e:
        messages.error(request, f"Payment processing error: {str(e)}")
        return redirect('shop:view_cart')

    display_data = prepare_item_display_data(order_items, is_cart=False)

    # Render payment page
    return render(request, 'shop/payment.html', {
        'order': order,
        'display_data': display_data,
        'checkout_session_id': checkout_session_id,
        'stripe_publishable_key': settings.STRIPE_PUBLISHABLE_KEY,
    })

def payment_success(request, order_id):
    """Handle successful payment"""
    order = get_object_or_404(Order, id=order_id)

    # Clear cart after successful payment
    cart.clear_cart(request)

    # Only update if not already processed by webhook
    if not order.webhook_processed:
        print(f"Updating order {order_id} via redirect (not webhook)")
        order.status = OrderStatus.PAID
        order.payment_status = 'PAID'
        order.save()
    else:
        print(f"Order {order_id} already processed by webhook")

    # Get order items for template
    order_items = order.items.all()
    display_data = prepare_item_display_data(order_items, is_cart=False)

    return render(request, 'shop/payment_success.html', {
        'order': order,
        'display_data': display_data,
    })

def payment_cancel(request, order_id):
    """Handle cancelled payment"""
    order = get_object_or_404(Order, id=order_id)

    # Only update if not already processed by webhook
    if not order.webhook_processed:
        print(f"Updating order {order_id} to CANCELED via redirect (not webhook)")
        order.status = OrderStatus.CANCELED
        order.payment_status = 'FAILED'
        order.save()
    else:
        print(f"Order {order_id} already processed by webhook")

    messages.warning(request, "Your payment was cancelled.")
    return render(request, 'shop/payment_cancel.html', {'order': order})

@require_POST
def create_checkout_session(request):
    """API endpoint to create a Stripe checkout session directly from cart"""
    if not request.user.is_authenticated:
        return JsonResponse({'error': 'User must be authenticated'}, status=403)

    # Create the order
    order = create_order(request)

    if not order:
        return JsonResponse({'error': 'Could not create order from cart'}, status=400)

    # Get order items
    order_items = order.items.all()

    # Create line items
    line_items = _create_stripe_line_items(order_items)

    # Create checkout session
    try:
        checkout_session = _create_stripe_checkout_session(request, order, line_items)
        return JsonResponse({'id': checkout_session.id})
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=400)

@require_POST
def update_cart_item(request):
    """Update a cart item quantity (increase/decrease)"""
    item_id = request.POST.get('item_id')
    action = request.POST.get('action')

    try:
        cart_item = cart.get_cart_item(request, item_id)

        if action == 'increase':
            # Increase quantity by 1
            cart_item.quantity += 1
            cart_item.save()
            messages.success(request, "Quantity increased.")

        elif action == 'decrease' and cart_item.quantity > 1:
            # Decrease quantity by 1
            cart_item.quantity -= 1
            cart_item.save()
            messages.success(request, "Quantity decreased.")

    except Exception as e:
        messages.error(request, f"Error updating cart: {str(e)}")

    return redirect('shop:view_cart')

@require_POST
def remove_from_cart(request):
    """Remove an item from cart by item_id"""
    item_id = request.POST.get('item_id')

    try:
        cart_item = cart.get_cart_item(request, item_id)
        cart_item.delete()
        messages.success(request, "Item removed from cart.")
    except Exception as e:
        messages.error(request, f"Error removing item: {str(e)}")

    return redirect('shop:view_cart')

def prepare_item_display_data(items, is_cart=True):
    """
    Transform cart items or order items into a standardized format for display

    Args:
        items: QuerySet of CartItem or OrderItem
        is_cart: True if items are CartItems, False if OrderItems

    Returns:
        Dictionary with standardized item data
    """
    prepared_items = []
    total_quantity = 0
    total_price = 0

    for item in items:
        if is_cart:
            # For CartItem
            item_data = {
                'id': item.id,
                'product_title': item.product.title,
                'product_description': item.product.description if item.product.description else None,
                'color_name': item.color.name if item.color else 'N/A',
                'color_hex': item.color.colorHex if item.color else '#FFFFFF',
                'secondary_color_hex': item.color.secondary_hex_color if item.color and item.color.secondary_hex_color else None,
                'size_name': item.size.name if item.size else 'N/A',
                'quantity': item.quantity,
                'total_price': item.get_total_price()
            }
            total_price += item.get_total_price()
        else:
            # For OrderItem
            item_data = {
                'id': item.id,
                'product_title': item.product.title,
                'product_description': item.product.description if item.product.description else None,
                'color_name': item.color.name if item.color else 'N/A',
                'color_hex': item.color.colorHex if item.color else '#FFFFFF',
                'secondary_color_hex': item.color.secondary_hex_color if item.color and item.color.secondary_hex_color else None,
                'size_name': item.size.name if item.size else 'N/A',
                'quantity': item.quantity,
                'total_price': item.get_total_price()
            }
            total_price += item.get_total_price()

        total_quantity += item.quantity
        prepared_items.append(item_data)

    return {
        'items': prepared_items,
        'total_quantity': total_quantity,
        'total_price': total_price
    }


def simulate_payment_success(request):
    """Debug function to simulate successful payment without Stripe"""
    # Create an order from the cart
    order = create_order(request)

    if not order:
        messages.error(request, "Could not create order from cart")
        return redirect('shop:view_cart')

    # Clear the cart
    cart.clear_cart(request)

    return redirect('shop:payment_success', order_id=order.id)

def simulate_payment_failure(request):
    """Debug function to simulate failed payment without Stripe"""
    # Create an order from the cart
    order = create_order(request)

    if not order:
        messages.error(request, "Could not create order from cart")
        return redirect('shop:view_cart')

    return redirect('shop:payment_cancel', order_id=order.id)


@require_POST
@csrf_exempt
def stripe_webhook(request):
    """Handle Stripe webhook events"""
    payload = request.body
    sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')

    # Log the received webhook for debugging
    print(f"Webhook received: {sig_header}")

    if not sig_header:
        print("No signature header")
        return HttpResponse(status=400)

    try:
        # Use the service to verify the webhook
        event = stripe_service.verify_webhook_signature(payload, sig_header)

        # Log the event type and mode
        mode = "TEST" if stripe_service.is_test_mode else "LIVE"
        print(f"{mode} webhook event type: {event['type']}")

    except ValueError as e:
        print(f"Invalid payload: {str(e)}")
        return HttpResponse(status=400)
    except stripe.error.SignatureVerificationError as e:
        print(f"Invalid signature: {str(e)}")
        return HttpResponse(status=400)

    # Handle the event based on type
    event_type = event['type']

    if event_type == 'checkout.session.completed':
        handle_checkout_session_completed(event['data']['object'])
    elif event_type == 'payment_intent.succeeded':
        handle_payment_intent_succeeded(event['data']['object'])
    elif event_type == 'payment_intent.payment_failed':
        handle_payment_intent_failed(event['data']['object'])

    # Return success response
    return HttpResponse(status=200)

def handle_checkout_session_completed(session):
    """Handle completed checkout session webhook"""
    print(f"Processing checkout.session.completed for session {session.id}")

    # Get order from metadata
    order_id = session.get('metadata', {}).get('order_id')
    if not order_id:
        print(f"Warning: No order_id in metadata for session {session.id}")
        return

    try:
        order = Order.objects.get(id=order_id)

        # Update order status if not already processed
        if not order.webhook_processed:
            print(f"Updating order {order_id} to PAID via webhook")
            order.status = OrderStatus.PAID
            order.payment_status = 'PAID'
            order.webhook_processed = True
            order.save()

            # You could add additional processing here
            # - Send order confirmation email
            # - Update inventory
            # - Etc.
        else:
            print(f"Order {order_id} already processed by webhook")

    except Order.DoesNotExist:
        print(f"Error: Order {order_id} not found for session {session.id}")

def handle_payment_intent_succeeded(payment_intent):
    """Handle successful payment intent webhook"""
    print(f"Processing payment_intent.succeeded for intent {payment_intent.id}")

    # If you're using payment intents directly, handle them here
    # For Checkout Sessions, you'll likely rely on checkout.session.completed instead

def handle_payment_intent_failed(payment_intent):
    """Handle failed payment intent webhook"""
    print(f"Processing payment_intent.payment_failed for intent {payment_intent.id}")

    # Get order from metadata
    order_id = payment_intent.get('metadata', {}).get('order_id')
    if not order_id:
        print(f"No order_id in metadata for payment intent {payment_intent.id}")
        return

    try:
        order = Order.objects.get(id=order_id)

        # Update order status
        if not order.webhook_processed or order.payment_status != 'FAILED':
            print(f"Updating order {order_id} to FAILED via webhook")
            order.status = OrderStatus.CANCELED
            order.payment_status = 'FAILED'
            order.webhook_processed = True
            order.save()

    except Order.DoesNotExist:
        print(f"Error: Order {order_id} not found for payment intent {payment_intent.id}")
