# shop/views.py

import logging
from urllib.parse import urlencode

from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse, HttpResponse
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages

from .models import Category, Product, Order, OrderItem
from .forms import CartAddProductForm, UserRegistrationForm, CheckoutForm
from .cart import Cart
from . import ipay as ipay_util

logger = logging.getLogger(__name__)


# ─── LANDING PAGE ─────────────────────────────────────────────────────────────

def nutriacademi_landing(request):
    return render(request, 'shop/landing/nutriacademi.html')


# ─── SHOP ─────────────────────────────────────────────────────────────────────

def product_list(request, category_slug=None):
    category = None
    categories = Category.objects.all()
    products = Product.objects.filter(available=True)
    if category_slug:
        category = get_object_or_404(Category, slug=category_slug)
        products = products.filter(category=category)
    return render(request, 'shop/product/list.html', {
        'category': category,
        'categories': categories,
        'products': products,
    })


def product_detail(request, id, slug):
    product = get_object_or_404(Product, id=id, slug=slug, available=True)
    cart_product_form = CartAddProductForm()
    return render(request, 'shop/product/detail.html', {
        'product': product,
        'cart_product_form': cart_product_form,
    })


# ─── CART ─────────────────────────────────────────────────────────────────────

@require_POST
def cart_add(request, product_id):
    cart = Cart(request)
    product = get_object_or_404(Product, id=product_id)
    form = CartAddProductForm(request.POST)
    if form.is_valid():
        cd = form.cleaned_data
        cart.add(product=product, quantity=cd['quantity'], override_quantity=cd['update'])
    if request.headers.get('x-requested-with') == 'XMLHttpRequest':
        return JsonResponse({'cart_len': len(cart)})
    return redirect('shop:cart_detail')


def cart_detail(request):
    cart = Cart(request)
    for item in cart:
        item['update_quantity_form'] = CartAddProductForm(initial={
            'quantity': item['quantity'],
            'update': True,
        })
    return render(request, 'shop/cart/detail.html', {'cart': cart})


@require_POST
def cart_remove(request, product_id):
    cart = Cart(request)
    product = get_object_or_404(Product, id=product_id)
    cart.remove(product)
    return redirect('shop:cart_detail')


# ─── CHECKOUT & PAYMENT ───────────────────────────────────────────────────────

@login_required
def checkout(request):
    cart = Cart(request)
    if len(cart) == 0:
        messages.warning(request, 'Your cart is empty.')
        return redirect('shop:product_list')

    user = request.user
    initial = {
        'first_name': user.first_name,
        'last_name':  user.last_name,
        'email':      user.email,
        'city':       'Nairobi',
    }

    if request.method == 'POST':
        form = CheckoutForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data

            # Create the order
            order = Order.objects.create(
                user        = user,
                first_name  = cd['first_name'],
                last_name   = cd.get('last_name', ''),
                email       = cd['email'],
                phone       = cd['phone'],
                address     = cd['address'],
                city        = cd['city'],
                total_price = cart.get_total_price(),
            )

            # Save each cart item as an OrderItem
            for item in cart:
                OrderItem.objects.create(
                    order        = order,
                    product      = item['product'],
                    product_name = item['product'].name,
                    price        = item['price'],
                    quantity     = item['quantity'],
                )

            # Build the iPay callback URL (must be the live public domain in production)
            callback_url = request.build_absolute_uri(
                f'/shop/orders/callback/'
            )

            params = ipay_util.build_payment_params(order, callback_url)
            gateway_url = ipay_util.IPAY_GATEWAY_URL + '?' + urlencode(params)

            return redirect(gateway_url)
    else:
        form = CheckoutForm(initial=initial)

    return render(request, 'shop/orders/checkout.html', {
        'form': cart,
        'checkout_form': form,
        'cart': cart,
    })


@csrf_exempt
def ipay_callback(request):
    """
    iPay posts the payment result here.
    We verify the hash, update the order status, and clear the cart.
    """
    if request.method != 'POST':
        return HttpResponse(status=405)

    data = request.POST.dict()
    order_id = data.get('oid')

    try:
        order = Order.objects.get(id=order_id)
    except Order.DoesNotExist:
        logger.warning("iPay callback for unknown order id=%s", order_id)
        return HttpResponse("OK")

    if not ipay_util.verify_callback(data):
        logger.warning("iPay callback hash mismatch for order id=%s", order_id)
        return HttpResponse("OK")

    status_code = data.get('status', '')
    txn_id = data.get('txncd', data.get('mc', ''))

    if status_code == ipay_util.IPAY_STATUS_SUCCESS:
        order.status = Order.STATUS_PAID
        order.ipay_txn_id = txn_id
        order.save()
        logger.info("Order #%s marked as PAID", order_id)
    else:
        order.status = Order.STATUS_FAILED
        order.save()
        logger.info("Order #%s marked as FAILED (status=%s)", order_id, status_code)

    return HttpResponse("OK")


def order_confirm(request, order_id):
    """
    Customer lands here after iPay redirects them back.
    We look up the order by ID — the cart is cleared on success.
    """
    order = get_object_or_404(Order, id=order_id, user=request.user if request.user.is_authenticated else None)

    # Clear the cart once customer sees confirmation
    if order.status == Order.STATUS_PAID:
        cart = Cart(request)
        cart.clear()

    return render(request, 'shop/orders/confirm.html', {'order': order})


@login_required
def order_history(request):
    orders = Order.objects.filter(user=request.user)
    return render(request, 'shop/orders/history.html', {'orders': orders})


# ─── ACCOUNTS ─────────────────────────────────────────────────────────────────

def account_register(request):
    if request.user.is_authenticated:
        return redirect('shop:account_profile')
    if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            messages.success(request, f'Welcome, {user.first_name or user.username}! Your account has been created.')
            return redirect('shop:product_list')
    else:
        form = UserRegistrationForm()
    return render(request, 'shop/accounts/register.html', {'form': form})


def account_login(request):
    if request.user.is_authenticated:
        return redirect('shop:account_profile')
    if request.method == 'POST':
        username = request.POST.get('username', '').strip()
        password = request.POST.get('password', '')
        user = authenticate(request, username=username, password=password)
        if user:
            login(request, user)
            next_url = request.POST.get('next') or request.GET.get('next') or 'shop:product_list'
            return redirect(next_url)
        else:
            messages.error(request, 'Invalid username or password. Please try again.')
    return render(request, 'shop/accounts/login.html', {
        'next': request.GET.get('next', ''),
    })


@require_POST
def account_logout(request):
    logout(request)
    messages.success(request, 'You have been logged out.')
    return redirect('shop:nutriacademi')


@login_required
def account_profile(request):
    orders = Order.objects.filter(user=request.user)
    return render(request, 'shop/accounts/profile.html', {'orders': orders})
