
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_required, current_user
from models import db, Cart, CartItem, Product

cart_bp = Blueprint('cart', __name__)

@cart_bp.route('/cart')
@login_required
def view_cart():

  cart = Cart.query.filter_by(user_id=current_user.id).first()
  if not cart:
    cart = Cart(user_id=current_user.id)
    db.session.add(cart)
    db.session.commit()

  items = cart.items
  total = 0
  item_details = []

  for item in items:
    product = Product.query.get(item.product_id)
    if product:
      subtotal = product.price * item.quantity
      total += subtotal
      item_details.append({
          'id': item.id,
          'product': product,
          'quantity': item.quantity,
          'subtotal': subtotal,
          'max_quantity': product.stock
      })

  return render_template('cart.html', items=item_details, total=total)

@cart_bp.route('/add/<int:product_id>')
@login_required
def add_to_cart(product_id):

  cart = Cart.query.filter_by(user_id=current_user.id).first()
  if not cart:
    cart = Cart(user_id=current_user.id)
    db.session.add(cart)
    db.session.commit()

  product = Product.query.get(product_id)
  if not product:
    flash("Product not found", "danger")
    return redirect(url_for('main.products'))

  if product.stock <= 0:
    flash(f"Sorry, {product.name} is out of stock", "danger")
    return redirect(url_for('main.products'))

  cart_item = CartItem.query.filter_by(
      cart_id=cart.id, product_id=product_id).first()

  if cart_item:

    if cart_item.quantity + 1 > product.stock:
      flash(f"Only {product.stock} items available in stock", "warning")
      return redirect(url_for('main.products'))

    cart_item.quantity += 1
  else:

    cart_item = CartItem(cart_id=cart.id, product_id=product_id, quantity=1)
    db.session.add(cart_item)

  db.session.commit()
  flash(f"Added {product.name} to cart!", "success")

  referrer = request.referrer
  if referrer and ('/product/' in referrer or '/products' in referrer):
    return redirect(referrer)
  return redirect(url_for('main.products'))

@cart_bp.route('/remove/<int:item_id>', methods=['POST'])
@login_required
def remove_from_cart(item_id):
  cart_item = CartItem.query.get_or_404(item_id)

  if cart_item.cart.user_id != current_user.id:
    flash("You don't have permission to remove this item", "danger")
    return redirect(url_for('cart.view_cart'))

  product_name = cart_item.product.name
  db.session.delete(cart_item)
  db.session.commit()
  flash(f"{product_name} removed from cart", "info")
  return redirect(url_for('cart.view_cart'))

@cart_bp.route('/update/<int:item_id>', methods=['POST'])
@login_required
def update_cart(item_id):
  cart_item = CartItem.query.get_or_404(item_id)


  if cart_item.cart.user_id != current_user.id:
    flash("You don't have permission to update this item", "danger")
    return redirect(url_for('cart.view_cart'))

  new_quantity = request.form.get('quantity')
  product = Product.query.get(cart_item.product_id)

  try:
    new_quantity = int(new_quantity)
    if new_quantity > 0:
      if new_quantity > product.stock:
        flash(
            f"Only {product.stock} items available in stock. Quantity adjusted.", "warning")
        new_quantity = product.stock

      cart_item.quantity = new_quantity
      db.session.commit()
      flash("Cart updated", "success")
    elif new_quantity == 0:
      db.session.delete(cart_item)
      db.session.commit()
      flash("Item removed from cart", "info")
    else:
      flash("Quantity must be at least 0", "danger")

  except ValueError:
    flash("Invalid quantity", "danger")

  return redirect(url_for('cart.view_cart'))

@cart_bp.route('/clear', methods=['POST'])
@login_required
def clear_cart():
  cart = Cart.query.filter_by(user_id=current_user.id).first()
  if cart:
    items = cart.items
    if items:
      item_count = len(items)

      CartItem.query.filter_by(cart_id=cart.id).delete()
      db.session.commit()
      flash(f"Cart cleared ({item_count} items removed)", "info")
    else:
      flash("Your cart is already empty", "info")

  return redirect(url_for('cart.view_cart'))

@cart_bp.route('/checkout', methods=['GET', 'POST'])
@login_required
def checkout():
  cart = Cart.query.filter_by(user_id=current_user.id).first()
  if not cart or not cart.items:
    flash("Your cart is empty", "warning")
    return redirect(url_for('cart.view_cart'))

  for item in cart.items:
    product = Product.query.get(item.product_id)
    if product.stock < item.quantity:
      flash(
          f"Sorry, {product.name} only has {product.stock} items in stock (you have {item.quantity} in cart)", "danger")
      return redirect(url_for('cart.view_cart'))

  if request.method == 'POST':
    try:
      total = 0
      order_items = []

      for item in cart.items:
        product = Product.query.get(item.product_id)

        product.stock -= item.quantity

        total += product.price * item.quantity

        order_items.append({
            'product_id': product.id,
            'quantity': item.quantity,
            'price': product.price
        })

      from models import Order, OrderItem
      from datetime import datetime

      order = Order(user_id=current_user.id, created_at=datetime.utcnow())
      db.session.add(order)
      db.session.flush()

      for item_data in order_items:
        order_item = OrderItem(
            order_id=order.id,
            product_id=item_data['product_id'],
            quantity=item_data['quantity']
        )
        db.session.add(order_item)

      CartItem.query.filter_by(cart_id=cart.id).delete()

      db.session.commit()

      flash(f"Order placed successfully! Total: ${total:.2f}", "success")
      return redirect(url_for('user.profile'))

    except Exception as e:
      db.session.rollback()
      flash(f"Checkout failed: {str(e)}", "danger")
      return redirect(url_for('cart.view_cart'))

  total = sum(item.product.price * item.quantity for item in cart.items)
  return render_template('checkout.html', cart=cart, total=total)

@cart_bp.route('/count')
@login_required
def cart_count():
  cart = Cart.query.filter_by(user_id=current_user.id).first()
  if cart:
    count = sum(item.quantity for item in cart.items)
  else:
    count = 0
  return str(count)
