import json
import logging
from decimal import Decimal
from django.core.cache import cache
from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password
from restaurant.models import Restaurant, MenuItem, Booking, BookingItem
from restaurant.whatsapp_service import send_reply
import track
from django.conf import settings

# Initialize Interakt track API key
track.api_key = settings.INTERAKT_SECRET_KEY

logger = logging.getLogger(__name__)

# State Constants
STATE_START = 'START'
STATE_MENU_BROWSING = 'MENU_BROWSING'
STATE_ADDING_ITEM = 'ADDING_ITEM'
STATE_ORDER_TYPE = 'ORDER_TYPE'
STATE_CONFIRM = 'CONFIRM'

User = get_user_model()

def get_session(phone_number):
    session = cache.get(f"whatsapp_session_{phone_number}")
    if not session:
        session = {
            'phone_number': phone_number,
            'state': STATE_START,
            'restaurant_id': None,
            'category': None,
            'cart': [],  # List of dicts: {'item_id': 1, 'qty': 2}
        }
        save_session(phone_number, session)
    return session

def save_session(phone_number, session):
    cache.set(f"whatsapp_session_{phone_number}", session, timeout=300)  # 5 minutes expiry

def clear_session(phone_number):
    cache.delete(f"whatsapp_session_{phone_number}")

def get_or_create_user(phone_number):
    """Clean the phone number and auto-create the user if missing."""
    cleaned = phone_number.replace('whatsapp:', '').replace('+', '').strip()
    
    # Try finding existing by phone or username
    user = User.objects.filter(phone=cleaned).first()
    if not user:
        user = User.objects.filter(username=cleaned).first()
        
    if not user:
        logger.info(f"Auto-creating user for WhatsApp number: {cleaned}")
        user = User.objects.create(
            username=cleaned,
            phone=cleaned,
            role='CUSTOMER',
            password=make_password('12345678')
        )
        
        if track.api_key:
            try:
                track.user(user_id=cleaned, phone_number=cleaned, traits={'username': cleaned, 'role': 'CUSTOMER'})
            except Exception as e:
                logger.error(f"Interakt track.user error: {e}")
                
    return user, cleaned

def get_cart_subtotal(session):
    subtotal = Decimal('0.00')
    for cart_item in session['cart']:
        item = MenuItem.objects.filter(id=cart_item['item_id']).first()
        if item:
            subtotal += item.price * cart_item['qty']
    return subtotal

def format_cart_summary(session):
    if not session['cart']:
        return "Your cart is empty."
        
    msg_lines = ["🛒 *Your Cart:*"]
    subtotal = Decimal('0.00')
    
    for cart_item in session['cart']:
        item = MenuItem.objects.filter(id=cart_item['item_id']).first()
        if item:
            item_total = item.price * cart_item['qty']
            subtotal += item_total
            msg_lines.append(f"{cart_item['qty']}x {item.name} - ₹{item_total}")
            
    msg_lines.append(f"\n*Subtotal: ₹{subtotal}*")
    return "\n".join(msg_lines), subtotal

def process_whatsapp_message(phone_number, text):
    """
    Main state machine for processing incoming WhatsApp messages.
    """
    session = get_session(phone_number)
    text = text.strip()
    text_lower = text.lower()
    
    # Global Reset Commands
    if text_lower in ['hi', 'hello', 'menu', 'start', 'restart']:
        session['state'] = STATE_START
        session['cart'] = []
        save_session(phone_number, session)
        
    user, clean_phone = get_or_create_user(phone_number)
    state = session.get('state', STATE_START)
    restaurant_id = session.get('restaurant_id')

    # --- STATE: START (List Restaurants) ---
    if state == STATE_START:
        restaurants = Restaurant.objects.filter(is_active=True)
        if not restaurants.exists():
            return send_reply(phone_number, "Sorry, no restaurants are currently available for ordering.")
            
        msg = "Welcome to *HotelFinder*! 🍽️\nWe're glad to have you.\n\nWhich restaurant would you like to order from? Reply with a number:\n"
        valid_rests = []
        for i, rest in enumerate(restaurants, 1):
            valid_rests.append(rest.id)
            msg += f"{i}️⃣ {rest.name}\n"
            
        session['valid_restaurants'] = valid_rests
        session['state'] = STATE_MENU_BROWSING
        save_session(phone_number, session)
        return send_reply(phone_number, msg)

    # --- STATE: MENU BROWSING (Show all items for the restaurant) ---
    elif state == STATE_MENU_BROWSING:
        if text_lower == 'c':
            return goto_order_type(phone_number, session)
            
        try:
            choice = int(text)
            valid_rests = session.get('valid_restaurants', [])
            if 1 <= choice <= len(valid_rests):
                restaurant_id = valid_rests[choice - 1]
                session['restaurant_id'] = restaurant_id
                restaurant = Restaurant.objects.get(id=restaurant_id)
                
                items = MenuItem.objects.filter(restaurant=restaurant, is_available=True)
                msg = f"You selected *{restaurant.name}*!\n\nHere is our menu:\n\n"
                
                valid_items = []
                for i, item in enumerate(items, 1):
                    valid_items.append(item.id)
                    msg += f"*{i}*. {item.name} - ₹{item.price}\n"
                    
                msg += "\nReply with the *Item Number* followed by *Quantity* (e.g., `2 1` for 1x of Item #2).\nReply `C` to view Cart & Checkout. Reply `0` to change restaurant."
                
                session['valid_items'] = valid_items
                session['state'] = STATE_ADDING_ITEM
                save_session(phone_number, session)
                return send_reply(phone_number, msg)
            elif text == '0':
                session['state'] = STATE_START
                save_session(phone_number, session)
                return process_whatsapp_message(phone_number, "menu")
            else:
                return send_reply(phone_number, "Invalid choice. Please reply with a valid number.")
        except ValueError:
            return send_reply(phone_number, "Please reply with a number.")

    # --- STATE: ADDING ITEM ---
    elif state == STATE_ADDING_ITEM:
        if text == '0':
            session['state'] = STATE_START
            save_session(phone_number, session)
            return process_whatsapp_message(phone_number, "menu")
        elif text_lower == 'c':
            return goto_order_type(phone_number, session)
            
        parts = text.split()
        if len(parts) >= 1:
            try:
                item_idx = int(parts[0])
                qty = int(parts[1]) if len(parts) > 1 else 1
                
                valid_items = session.get('valid_items', [])
                if 1 <= item_idx <= len(valid_items):
                    item_id = valid_items[item_idx - 1]
                    item = MenuItem.objects.get(id=item_id)
                    
                    # Add to cart
                    cart = session.get('cart', [])
                    # Check if already in cart
                    found = False
                    for c_item in cart:
                        if c_item['item_id'] == item_id:
                            c_item['qty'] += qty
                            found = True
                            break
                    if not found:
                        cart.append({'item_id': item_id, 'qty': qty})
                    
                    session['cart'] = cart
                    save_session(phone_number, session)
                    
                    msg = f"✅ *{qty}x {item.name}* added to your cart!\n\nReply with another Item & Qty to add more.\nReply `0` to change restaurant.\nReply `C` to view Cart & Checkout."
                    return send_reply(phone_number, msg)
                else:
                    return send_reply(phone_number, "Invalid item number. Please try again.")
            except ValueError:
                return send_reply(phone_number, "Format error. Please reply like `1 2` (Item 1, Quantity 2).")

    # --- STATE: ORDER TYPE ---
    elif state == STATE_ORDER_TYPE:
        if text == '0':
            session['state'] = STATE_START
            save_session(phone_number, session)
            return process_whatsapp_message(phone_number, "menu")
            
        order_types = ['TAKEAWAY', 'DELIVERY', 'DINE_IN']
        try:
            choice = int(text)
            if 1 <= choice <= len(order_types):
                selected_type = order_types[choice - 1]
                session['order_type'] = selected_type
                
                # Calculate totals
                subtotal = get_cart_subtotal(session)
                tax = subtotal * Decimal('0.05') # 5% tax assumption
                total = subtotal + tax
                session['tax'] = float(tax)
                session['total'] = float(total)
                
                session['state'] = STATE_CONFIRM
                save_session(phone_number, session)
                
                msg = f"Great! *{selected_type.replace('_', ' ').title()}* selected.\n\n"
                msg += f"Subtotal: ₹{subtotal}\n"
                msg += f"Taxes: ₹{tax:.2f}\n"
                msg += f"*Total Amount: ₹{total:.2f}*\n\n"
                msg += "Reply `Y` to confirm your order or `N` to cancel."
                return send_reply(phone_number, msg)
            else:
                return send_reply(phone_number, "Please select 1, 2, or 3.")
        except ValueError:
            return send_reply(phone_number, "Please reply with a valid number (1, 2, or 3).")

    # --- STATE: CONFIRM ---
    elif state == STATE_CONFIRM:
        if text_lower in ['y', 'yes']:
            # Place Order
            cart = session.get('cart', [])
            if not cart:
                return send_reply(phone_number, "Your cart is empty. Reply 'Menu' to start over.")
                
            subtotal = get_cart_subtotal(session)
            tax = Decimal(str(session.get('tax', 0.0)))
            total = Decimal(str(session.get('total', 0.0)))
            order_type = session.get('order_type', 'TAKEAWAY')
            
            # Create Booking
            restaurant = Restaurant.objects.get(id=restaurant_id)
            booking = Booking.objects.create(
                restaurant=restaurant,
                customer=user,
                booking_type=order_type,
                customer_name=user.username or "WhatsApp Customer",
                contact_number=clean_phone,
                subtotal=subtotal,
                tax_amount=tax,
                total_amount=total,
                status='COMPLETED' if order_type == 'TAKEAWAY' else 'PENDING',
                payment_status='UNPAID',
                payment_mode='COD'
            )
            
            # Add Items
            for cart_item in cart:
                item = MenuItem.objects.get(id=cart_item['item_id'])
                BookingItem.objects.create(
                    booking=booking,
                    menu_item=item,
                    quantity=cart_item['qty'],
                    unit_price=item.price,
                    total_price=item.price * cart_item['qty']
                )
                
            if track.api_key:
                try:
                    track.event(
                        user_id=clean_phone,
                        event="Order Placed",
                        traits={
                            "order_id": booking.id,
                            "restaurant_name": restaurant.name,
                            "order_type": order_type,
                            "subtotal": float(subtotal),
                            "total_amount": float(total),
                        }
                    )
                except Exception as e:
                    logger.error(f"Interakt track.event error: {e}")
            
            clear_session(phone_number)
            msg = f"🎉 Your order (ID: #{booking.id}) has been placed successfully!\nWe are preparing your food. Thank you for choosing {restaurant.name}!"
            return send_reply(phone_number, msg)
            
        elif text_lower in ['n', 'no']:
            clear_session(phone_number)
            return send_reply(phone_number, "Order cancelled. Reply 'Menu' whenever you're hungry again!")
        else:
            return send_reply(phone_number, "Please reply `Y` to confirm or `N` to cancel.")

    # Fallback
    return send_reply(phone_number, "I didn't understand that. Reply 'Menu' to see our offerings.")

def goto_order_type(phone_number, session):
    cart_summary, subtotal = format_cart_summary(session)
    if not session['cart']:
        return send_reply(phone_number, "Your cart is empty. Reply `0` to browse the menu.")
        
    msg = f"{cart_summary}\n\n"
    msg += "How would you like your order?\n"
    msg += "1. 🛍️ Takeaway (Default)\n"
    msg += "2. 🛵 Delivery\n"
    msg += "3. 🍽️ Dine-in\n\n"
    msg += "Reply with a number to choose. Or `0` to go back."
    
    session['state'] = STATE_ORDER_TYPE
    save_session(phone_number, session)
    return send_reply(phone_number, msg)
