from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from decimal import Decimal


class Restaurant(models.Model):
    """
    Restaurant model with GPS coordinates and delivery settings.
    Similar to Zomato/Swiggy restaurant profiles.
    """
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    location = models.CharField(max_length=100)  # City/Area name
    address = models.TextField(blank=True)  # Full address
    cuisine = models.CharField(max_length=100)
    rating = models.FloatField(default=0.0, validators=[MinValueValidator(0.0), MaxValueValidator(5.0)])
    
    # GPS Coordinates for location-based booking
    latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    
    # Delivery settings
    delivery_radius_km = models.FloatField(default=5.0, help_text="Maximum delivery distance in kilometers")
    is_delivery_available = models.BooleanField(default=True)
    is_dine_in_available = models.BooleanField(default=True)
    is_takeaway_available = models.BooleanField(default=True)
    
    # Operating hours
    opening_time = models.TimeField(null=True, blank=True)
    closing_time = models.TimeField(null=True, blank=True)
    
    # Table configuration for Dine-In
    tables_available = models.IntegerField(default=0)
    max_party_size = models.IntegerField(default=10)
    
    # Pricing info
    average_cost_for_two = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    table_booking_fee = models.DecimalField(max_digits=6, decimal_places=2, default=50.00, help_text="Fee to book a table")
    
    # Image
    image = models.ImageField(upload_to='restaurant_images/', null=True, blank=True)
    
    owner = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name="restaurants", null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return self.name


class MenuCategory(models.Model):
    """
    Custom dynamic menu categories with icon and ordering.
    """
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='menu_categories')
    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='subcategories', help_text="Parent category if this is a subcategory")
    name = models.CharField(max_length=150)
    icon = models.CharField(max_length=50, default='🍽️')
    description = models.TextField(blank=True)
    order = models.IntegerField(default=0)
    is_active = models.BooleanField(default=True)
    show_subcategories_as_grouped_list = models.BooleanField(default=False, help_text="If true, subcategories and their items will be shown on a single continuous page")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['order', 'name']
        verbose_name_plural = "Menu Categories"

    def __str__(self):
        return f"{self.icon} {self.name} ({self.restaurant.name})"


class MenuItem(models.Model):
    """
    Menu items for a restaurant with categories and dietary info.
    """
    CATEGORY_CHOICES = [
        ('STARTER', 'Starter'),
        ('MAIN_COURSE', 'Main Course'),
        ('DESSERT', 'Dessert'),
        ('BEVERAGE', 'Beverage'),
        ('SNACKS', 'Snacks'),
        ('BIRYANI', 'Biryani'),
        ('THALI', 'Thali'),
        ('CHINESE', 'Chinese'),
        ('SOUTH_INDIAN', 'South Indian'),
        ('NORTH_INDIAN', 'North Indian'),
    ]
    
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='menu_items')
    custom_category = models.ForeignKey(MenuCategory, on_delete=models.SET_NULL, null=True, blank=True, related_name='items')
    aahar_item_id = models.IntegerField(null=True, blank=True, help_text="Original item ID from Aahar POS")
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    category = models.CharField(max_length=100, default='Uncategorized')
    image = models.ImageField(upload_to='menu_items/', null=True, blank=True)
    custom_image = models.ImageField(upload_to='menu_items/custom/', null=True, blank=True,
                                     help_text="HotelFinder-uploaded image; shown in preference to the Aahar-synced image.")
    is_available = models.BooleanField(default=True)
    is_vegetarian = models.BooleanField(default=False)
    is_vegan = models.BooleanField(default=False)
    spice_level = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(5)])
    preparation_time_minutes = models.IntegerField(default=15)
    show_detail_screen = models.BooleanField(default=True, help_text="If false, clicking this item won't open the detail modal/screen.")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['category', 'name']

    def __str__(self):
        return f"{self.name} - ₹{self.price}"


class ItemVariant(models.Model):
    """
    Dynamic variants for a menu item (e.g. Classic Single, Cheese Loaded +₹25, Half/Full, Veg/Paneer).
    """
    menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE, related_name='variants')
    name = models.CharField(max_length=100)
    price_adjustment = models.DecimalField(max_digits=8, decimal_places=2, default=0.00, help_text="Extra price added to base item price")
    is_default = models.BooleanField(default=False)
    is_available = models.BooleanField(default=True)
    is_vegetarian = models.BooleanField(default=True, null=True, blank=True)
    diet_type = models.CharField(max_length=20, choices=[
        ('REGULAR', 'Regular / Neutral'),
        ('VEG', 'Veg'),
        ('PANEER', 'Paneer'),
        ('NON_VEG', 'Non-Veg'),
    ], default='REGULAR')
    order = models.IntegerField(default=0)

    class Meta:
        ordering = ['order', 'id']

    def __str__(self):
        sign = f"+₹{self.price_adjustment}" if self.price_adjustment > 0 else "Base"
        return f"{self.name} ({sign})"


class ItemFeature(models.Model):
    """
    Flavors, spice levels, toppings, or custom notes for a menu item.
    """
    FEATURE_TYPE_CHOICES = [
        ('FLAVOR', 'Flavor Option'),
        ('SPICE', 'Spice Level'),
        ('TOPPING', 'Topping / Extra'),
        ('CUSTOM', 'Custom Note'),
    ]

    menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE, related_name='features')
    feature_type = models.CharField(max_length=50, choices=FEATURE_TYPE_CHOICES, default='FLAVOR')
    name = models.CharField(max_length=150)
    price = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
    is_available = models.BooleanField(default=True)
    order = models.IntegerField(default=0)

    class Meta:
        ordering = ['feature_type', 'order', 'id']

    def __str__(self):
        return f"[{self.get_feature_type_display()}] {self.name}"


class Table(models.Model):
    """
    Restaurant tables for Dine-In.
    """
    SHAPE_CHOICES = [
        ('ROUND', 'Round'),
        ('RECTANGLE', 'Rectangle'),
        ('SQUARE', 'Square'),
    ]

    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='tables')
    table_number = models.CharField(max_length=10)
    capacity = models.IntegerField(default=4, validators=[MinValueValidator(1)])
    shape = models.CharField(max_length=20, choices=SHAPE_CHOICES, default='SQUARE')
    
    # Optional: Coordinates for visual layout (0-100% or pixels)
    position_x = models.IntegerField(default=0)
    position_y = models.IntegerField(default=0)
    
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('restaurant', 'table_number')
        ordering = ['table_number']

    def __str__(self):
        return f"Table {self.table_number} ({self.capacity} pax)"


class Booking(models.Model):
    """
    Unified booking model for Dine-In, Delivery, and Take Away.
    Like Zomato/Swiggy order system.
    """
    BOOKING_TYPE_CHOICES = [
        ('DINE_IN', 'Dine In'),
        ('DELIVERY', 'Online Delivery'),
        ('TAKEAWAY', 'Take Away'),
    ]
    
    STATUS_CHOICES = [
        ('PENDING', 'Pending'),
        ('CONFIRMED', 'Confirmed'),
        ('PREPARING', 'Preparing'),
        ('READY', 'Ready for Pickup'),
        ('PARTNER_ASSIGNED', 'Delivery Partner Assigned'),
        ('OUT_FOR_DELIVERY', 'Out for Delivery'),
        ('PICKED_UP', 'Picked Up by Partner'),
        ('DELIVERED', 'Delivered'),
        ('COMPLETED', 'Completed'),
        ('CANCELLED', 'Cancelled'),
    ]
    
    PAYMENT_STATUS_CHOICES = [
        ('UNPAID', 'Unpaid'),
        ('PAID', 'Paid'),
        ('REFUNDED', 'Refunded'),
    ]
    
    PAYMENT_MODE_CHOICES = [
        ('COD', 'Cash/Pay at Restaurant'),
        ('ONLINE_QR', 'Online QR Payment'),
    ]
    
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='bookings')
    customer = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name='restaurant_bookings')
    delivery_partner = models.ForeignKey("users.User", on_delete=models.SET_NULL, null=True, blank=True, related_name='deliveries')
    booking_type = models.CharField(max_length=20, choices=BOOKING_TYPE_CHOICES)
    
    # Customer details
    customer_name = models.CharField(max_length=100)
    contact_number = models.CharField(max_length=15)
    email = models.EmailField(blank=True)
    
    # For Dine-In (Table Reservation)
    allocated_tables = models.ManyToManyField(Table, blank=True, related_name='bookings')
    reservation_date = models.DateField(null=True, blank=True)
    reservation_time = models.TimeField(null=True, blank=True)
    party_size = models.IntegerField(null=True, blank=True, validators=[MinValueValidator(1)])
    special_requests = models.TextField(blank=True)
    
    # For Delivery/Takeaway - Customer Location
    delivery_address = models.TextField(blank=True)
    delivery_latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    delivery_longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    distance_km = models.FloatField(null=True, blank=True)
    estimated_delivery_time = models.DateTimeField(null=True, blank=True)
    
    # Order details
    order_notes = models.TextField(blank=True)
    subtotal = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    booking_fee = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
    delivery_charge = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
    tax_amount = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
    total_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='PENDING')
    payment_status = models.CharField(max_length=20, choices=PAYMENT_STATUS_CHOICES, default='UNPAID')
    payment_mode = models.CharField(max_length=20, choices=PAYMENT_MODE_CHOICES, default='COD')
    
    # Location warning flags
    is_distance_warning = models.BooleanField(default=False, help_text="True if customer location is beyond delivery radius")
    distance_warning_message = models.CharField(max_length=255, blank=True)
    
    is_loyalty_evaluated = models.BooleanField(default=False, help_text="True if this booking has been evaluated by the loyalty RulesEngine")
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.booking_type} - {self.customer_name} - {self.restaurant.name}"

    def calculate_total(self):
        """Calculate total from booking items"""
        items_total = sum(item.total_price for item in self.items.all())
        self.subtotal = items_total
        delivery_charge = Decimal(str(self.delivery_charge))
        tax_amount = Decimal(str(self.tax_amount))
        self.total_amount = self.subtotal + delivery_charge + tax_amount
        return self.total_amount


class BookingItem(models.Model):
    """
    Individual items in a booking/order.
    """
    booking = models.ForeignKey(Booking, on_delete=models.CASCADE, related_name='items')
    menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1, validators=[MinValueValidator(1)])
    unit_price = models.DecimalField(max_digits=8, decimal_places=2)
    total_price = models.DecimalField(max_digits=10, decimal_places=2)
    special_instructions = models.TextField(blank=True)

    def save(self, *args, **kwargs):
        self.total_price = self.unit_price * self.quantity
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.quantity}x {self.menu_item.name}"


class AaharConfig(models.Model):
    """
    Stores the link between a local Restaurant and its Aahar counterpart.
    Enables communication between HotelFinder and Aahar systems.
    """
    restaurant = models.OneToOneField(Restaurant, on_delete=models.CASCADE, related_name='aahar_config')
    aahar_restaurant_service_id = models.CharField(max_length=50, help_text="restaurant_service_id from Aahar")
    aahar_domain = models.CharField(max_length=255, help_text="Aahar hotel domain e.g. aatithya.vaiditech.in")
    aahar_api_token = models.CharField(max_length=500, blank=True, help_text="Secure API token for Multi-Tenant Aahar routing")
    is_multitenant = models.BooleanField(default=True, help_text="If false, maps exactly via single service category")
    is_active = models.BooleanField(default=True)
    linked_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Aahar Configuration"
        verbose_name_plural = "Aahar Configurations"

    def __str__(self):
        return f"{self.restaurant.name} ↔ Aahar ({self.aahar_restaurant_service_id})"


class AaharOrderSync(models.Model):
    """
    Stores orders received/fetched from Aahar for a linked restaurant.
    """
    PAYMENT_STATUS_CHOICES = [
        ('UNPAID', 'Unpaid'),
        ('PAID', 'Paid'),
        ('REFUNDED', 'Refunded'),
    ]

    aahar_config = models.ForeignKey(AaharConfig, on_delete=models.CASCADE, related_name='synced_orders')
    aahar_order_id = models.IntegerField(help_text="order_id from Aahar")
    aahar_order_number = models.CharField(max_length=50, help_text="order_number from Aahar")
    invoice = models.CharField(max_length=100, help_text="Invoice number from Aahar")
    is_transfer = models.CharField(max_length=50, blank=True, null=True, default='others')
    room_number = models.CharField(max_length=20, blank=True, default='')
    booking_id = models.CharField(max_length=50, blank=True, default='')
    order_data = models.JSONField(help_text="Full order JSON from Aahar")
    grand_total = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    payment_status = models.CharField(max_length=20, choices=PAYMENT_STATUS_CHOICES, default='UNPAID')
    payment_mode = models.CharField(max_length=20, blank=True, default='')
    status = models.CharField(max_length=50, default='PLACED', help_text="Order status from Aahar POS")
    synced_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Aahar Order Sync"
        verbose_name_plural = "Aahar Order Syncs"
        unique_together = ('aahar_config', 'aahar_order_id')
        ordering = ['-synced_at']

    def __str__(self):
        return f"Aahar Order #{self.aahar_order_number} - ₹{self.grand_total} ({self.payment_status})"


# ==================== Delivery Partner Models ====================

class DeliveryContract(models.Model):
    COMMISSION_TYPE_CHOICES = [
        ('FLAT_FEE', 'Flat Fee Per Order'),
        ('PERCENTAGE', 'Percentage of Order'),
    ]
    STATUS_CHOICES = [
        ('PENDING', 'Pending Approval'),
        ('ACTIVE', 'Active'),
        ('REJECTED', 'Rejected'),
        ('INACTIVE', 'Inactive / Terminated'),
    ]

    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='delivery_contracts')
    delivery_partner = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name='delivery_contracts')
    
    commission_type = models.CharField(max_length=20, choices=COMMISSION_TYPE_CHOICES, default='FLAT_FEE')
    commission_value = models.DecimalField(max_digits=10, decimal_places=2)
    
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='PENDING')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('restaurant', 'delivery_partner')

    def __str__(self):
        return f"{self.delivery_partner.username} - {self.restaurant.name} ({self.status})"

class DeliveryCommissionLedger(models.Model):
    booking = models.OneToOneField(Booking, on_delete=models.CASCADE, related_name='commission_ledger')
    delivery_partner = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name='commissions')
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='commissions')
    
    commission_amount = models.DecimalField(max_digits=10, decimal_places=2) 
    is_settled = models.BooleanField(default=False)
    settled_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Commission for {self.booking.id} - ₹{self.commission_amount}"


class DeliveryLocationLog(models.Model):
    """
    GPS breadcrumb trail for live delivery tracking.
    Each row = one location update from the delivery partner.
    """
    booking = models.ForeignKey(Booking, on_delete=models.CASCADE, related_name='location_logs')
    delivery_partner = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name='location_logs')
    latitude = models.DecimalField(max_digits=9, decimal_places=6)
    longitude = models.DecimalField(max_digits=9, decimal_places=6)
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-timestamp']

    def __str__(self):
        return f"Location for Booking #{self.booking.id} at {self.timestamp}"


# ==================== Restaurant Finder (Zomato) Models ====================

class RestaurantFinderConfig(models.Model):
    """
    Stores the link between a local Restaurant and Restaurant Finder (Zomato-like) via Aahar.
    Enables two-way communication.
    """
    aahar_config = models.OneToOneField(AaharConfig, on_delete=models.CASCADE, related_name='restaurant_finder_config', null=True, blank=True)
    api_url = models.URLField(max_length=500, help_text="Base URL for the Restaurant Finder API", blank=True, null=True)
    brand_name = models.CharField(max_length=200, help_text="Brand name displayed on Restaurant Finder")
    outlet_id = models.CharField(max_length=100, help_text="Outlet ID provided by Restaurant Finder")
    api_key = models.CharField(max_length=255, help_text="API Key for secure communication")
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Restaurant Finder Configuration"
        verbose_name_plural = "Restaurant Finder Configurations"

    def __str__(self):
        return f"{self.aahar_config.restaurant.name} (via Aahar) ↔ Restaurant Finder ({self.outlet_id})"


# ==================== Loyalty Program Models ====================

class LoyaltyProgram(models.Model):
    """Per-restaurant loyalty program. Owner configures coin value and active rules."""
    restaurant = models.OneToOneField(Restaurant, on_delete=models.CASCADE, related_name='loyalty_program')
    program_name = models.CharField(max_length=200, default='Loyalty Program')
    is_active = models.BooleanField(default=False)
    coin_value_in_rupees = models.DecimalField(
        max_digits=6, decimal_places=2, default=1.00,
        help_text="1 coin = ₹X. e.g. 1.00 means 1 coin = ₹1"
    )
    redemption_cap_percent = models.DecimalField(
        max_digits=5, decimal_places=2, default=50.00,
        help_text="Max % of bill payable by coins (Iron Law 1)"
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.restaurant.name} — {self.program_name}"


class LoyaltyRule(models.Model):
    """
    Owner-configurable rule. Built-in types with JSON trigger config.
    Phase 2 adds SUBSCRIPTION and WALLET_TOPUP types.
    Phase 3 adds SOCIETY_VAULT and SUMMIT types.
    """
    RULE_TYPE_CHOICES = [
        ('WELCOME_HOOK',   'Welcome Hook (Squad Drop)'),
        ('REFERRAL',       'Referral (Sherpa Link)'),
        ('SUBSCRIPTION',   'Subscription Pass (Liquid Gold)'),
        ('WALLET_TOPUP',   'Wallet Top-up Bonus (Stash SIP)'),
        ('SOCIETY_VAULT',  'Society Vault'),
        ('MILESTONE_SPEND','Milestone Spend Bonus'),
        ('SUMMIT',         'Ultimate Summit (Kathmandu)'),
        ('DEAD_HOUR_DROP', 'Dead-Hour Drop'),
        ('CUSTOM',         'Custom Rule'),
    ]

    program = models.ForeignKey(LoyaltyProgram, on_delete=models.CASCADE, related_name='rules')
    rule_type = models.CharField(max_length=30, choices=RULE_TYPE_CHOICES)
    is_active = models.BooleanField(default=True)
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)

    # Flexible trigger config per rule_type. Examples:
    # WELCOME_HOOK:   {"min_spend": 500, "first_order_only": true}
    # REFERRAL:       {"coins_per_referral": 99}
    # SUBSCRIPTION:   {"monthly_price": 399, "min_food_pair": 99}
    # WALLET_TOPUP:   {"min_topup": 1000, "bonus_percent": 50}
    # SUMMIT:         {"target_spend": 7000, "max_vips": 100}
    trigger_config = models.JSONField(default=dict, help_text="Rule trigger parameters")

    reward_coins = models.DecimalField(
        max_digits=10, decimal_places=2, default=0,
        help_text="Coins awarded when this rule triggers"
    )
    reward_expiry_hours = models.IntegerField(
        null=True, blank=True,
        help_text="Hours until awarded coins expire. Null = never expires (Iron Law 3)"
    )

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.program.restaurant.name} — {self.get_rule_type_display()}"


class CustomerWallet(models.Model):
    """One wallet per customer per restaurant. Holds coin balance and lifetime stats."""
    customer = models.ForeignKey(
        "users.User", on_delete=models.CASCADE, related_name='loyalty_wallets'
    )
    restaurant = models.ForeignKey(
        Restaurant, on_delete=models.CASCADE, related_name='customer_wallets'
    )
    coin_balance = models.DecimalField(max_digits=12, decimal_places=2, default=0)

    # Tracks only actual cash paid (excludes coin redemptions) — Iron Law 4 / Summit
    lifetime_cash_spent = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    total_orders = models.IntegerField(default=0)

    # Referral (Sherpa Link)
    referral_code = models.CharField(max_length=20, unique=True, blank=True)
    referred_by = models.ForeignKey(
        "users.User", on_delete=models.SET_NULL, null=True, blank=True,
        related_name='referrals_made'
    )

    # Kathmandu Summit
    is_summit_vip = models.BooleanField(default=False)
    summit_vip_at = models.DateTimeField(null=True, blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('customer', 'restaurant')

    def __str__(self):
        return f"{self.customer.username} @ {self.restaurant.name} — {self.coin_balance} coins"


class CoinTransaction(models.Model):
    """
    Immutable ledger. Every coin movement (earn / redeem / expire) is one row.
    Never update or delete rows — only insert.
    """
    TRANSACTION_TYPE_CHOICES = [
        ('EARNED',       'Earned from Order'),
        ('REDEEMED',     'Redeemed at Checkout'),
        ('EXPIRED',      'Expired'),
        ('REFERRAL',     'Referral Reward'),
        ('TOPUP_BONUS',  'Wallet Top-up Bonus'),
        ('ADMIN_CREDIT', 'Admin Credit'),
        ('ADMIN_DEBIT',  'Admin Debit'),
    ]

    wallet = models.ForeignKey(CustomerWallet, on_delete=models.CASCADE, related_name='transactions')
    transaction_type = models.CharField(max_length=20, choices=TRANSACTION_TYPE_CHOICES)
    # Positive = credit, negative = debit
    coins = models.DecimalField(max_digits=10, decimal_places=2)

    source_rule = models.ForeignKey(
        LoyaltyRule, on_delete=models.SET_NULL, null=True, blank=True
    )
    source_booking = models.ForeignKey(
        'Booking', on_delete=models.SET_NULL, null=True, blank=True,
        related_name='coin_transactions'
    )

    # Iron Law 3: expiry tracked per transaction batch
    expires_at = models.DateTimeField(null=True, blank=True)
    is_expired = models.BooleanField(default=False)

    notes = models.CharField(max_length=255, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        sign = '+' if self.coins > 0 else ''
        return f"{sign}{self.coins} ({self.transaction_type}) — {self.wallet.customer.username}"


# ==================== Phase 2 — Subscription + Wallet Top-up ====================

class LoyaltySubscription(models.Model):
    STATUS_CHOICES = [
        ('ACTIVE',    'Active'),
        ('EXPIRED',   'Expired'),
        ('CANCELLED', 'Cancelled'),
    ]
    wallet = models.ForeignKey(CustomerWallet, on_delete=models.CASCADE, related_name='subscriptions')
    rule = models.ForeignKey(LoyaltyRule, on_delete=models.SET_NULL, null=True, blank=True)
    amount_paid = models.DecimalField(max_digits=8, decimal_places=2)
    payment_reference = models.CharField(max_length=100, blank=True)
    valid_from = models.DateField()
    valid_until = models.DateField()
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='ACTIVE')
    last_used_date = models.DateField(null=True, blank=True)
    total_uses = models.IntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.wallet.customer.username} sub @ {self.wallet.restaurant.name} ({self.status})"


class WalletTopup(models.Model):
    wallet = models.ForeignKey(CustomerWallet, on_delete=models.CASCADE, related_name='topups')
    rule = models.ForeignKey(LoyaltyRule, on_delete=models.SET_NULL, null=True, blank=True)
    cash_paid = models.DecimalField(max_digits=8, decimal_places=2)
    coins_credited = models.DecimalField(max_digits=10, decimal_places=2)
    payment_reference = models.CharField(max_length=100, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Topup ₹{self.cash_paid} → {self.coins_credited} coins ({self.wallet.customer.username})"


# ==================== Phase 3 — Khata + Society Vault ====================

class KhataAccount(models.Model):
    STATUS_CHOICES = [
        ('ACTIVE',   'Active'),
        ('OVERDUE',  'Overdue'),
        ('BLOCKED',  'Blocked'),
    ]
    wallet = models.OneToOneField(CustomerWallet, on_delete=models.CASCADE, related_name='khata')
    lifelines_total = models.IntegerField(default=5)
    lifelines_used = models.IntegerField(default=0)
    current_tab_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    tab_due_date = models.DateField(null=True, blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='ACTIVE')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    @property
    def lifelines_remaining(self):
        return max(0, self.lifelines_total - self.lifelines_used)

    def __str__(self):
        return f"Khata {self.wallet.customer.username} @ {self.wallet.restaurant.name} ({self.status})"


class KhataTransaction(models.Model):
    khata = models.ForeignKey(KhataAccount, on_delete=models.CASCADE, related_name='khata_transactions')
    booking = models.ForeignKey('Booking', on_delete=models.SET_NULL, null=True, blank=True)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    is_cleared = models.BooleanField(default=False)
    cleared_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Khata tx ₹{self.amount} ({'cleared' if self.is_cleared else 'pending'})"


class LoyaltyGroup(models.Model):
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='loyalty_groups')
    admin = models.ForeignKey("users.User", on_delete=models.CASCADE, related_name='managed_groups')
    group_name = models.CharField(max_length=200)
    vault_balance = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    vault_percentage = models.DecimalField(max_digits=5, decimal_places=2, default=5.00,
                                            help_text="% of each member bill added to vault")
    semester_start = models.DateField(null=True, blank=True)
    semester_end = models.DateField(null=True, blank=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.group_name} @ {self.restaurant.name}"


class LoyaltyGroupMember(models.Model):
    group = models.ForeignKey(LoyaltyGroup, on_delete=models.CASCADE, related_name='members')
    wallet = models.ForeignKey(CustomerWallet, on_delete=models.CASCADE, related_name='group_memberships')
    joined_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('group', 'wallet')

    def __str__(self):
        return f"{self.wallet.customer.username} in {self.group.group_name}"


# ==================== Phase 4 — Dead-Hour Drops ====================

class DeadHourDrop(models.Model):
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='dead_hour_drops')
    message = models.TextField()
    discount_code = models.CharField(max_length=50, blank=True)
    valid_until = models.DateTimeField(null=True, blank=True)
    total_recipients = models.IntegerField(default=0)
    created_by = models.ForeignKey("users.User", on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Drop for {self.restaurant.name} at {self.created_at:%Y-%m-%d %H:%M}"


class RestaurantFinderOrderSync(models.Model):
    """
    Stores orders received from Restaurant Finder via Webhook.
    """
    PAYMENT_STATUS_CHOICES = [
        ('UNPAID', 'Unpaid'),
        ('PAID', 'Paid'),
        ('REFUNDED', 'Refunded'),
    ]

    config = models.ForeignKey(RestaurantFinderConfig, on_delete=models.CASCADE, related_name='synced_orders')
    rf_order_id = models.CharField(max_length=100, help_text="Unique order ID from Restaurant Finder")
    order_data = models.JSONField(help_text="Full order JSON received from Webhook")
    grand_total = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    payment_status = models.CharField(max_length=20, choices=PAYMENT_STATUS_CHOICES, default='UNPAID')
    payment_mode = models.CharField(max_length=50, blank=True, default='')
    status = models.CharField(max_length=50, default='RECEIVED')
    synced_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Restaurant Finder Order Sync"
        verbose_name_plural = "Restaurant Finder Order Syncs"
        unique_together = ('config', 'rf_order_id')
        ordering = ['-synced_at']

    def __str__(self):
        return f"RF Order #{self.rf_order_id} - ₹{self.grand_total} ({self.payment_status})"

class Offer(models.Model):
    """
    Ongoing offers and discounts for the restaurant landing page.
    """
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='offers', null=True, blank=True)
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    discount_percentage = models.DecimalField(max_digits=5, decimal_places=2, default=0.00, help_text="e.g. 20.00 for 20%")
    image = models.ImageField(upload_to='offers/', null=True, blank=True)
    is_active = models.BooleanField(default=True)
    valid_until = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.title} ({self.discount_percentage}% OFF)"


class Combo(models.Model):
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, related_name='combos')
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    service_category_id = models.CharField(max_length=50)        # Aahar service id
    service_category_name = models.CharField(max_length=200, blank=True)
    price = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)  # null -> computed sum
    image = models.ImageField(upload_to='combos/', null=True, blank=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.name} - {self.restaurant.name}"


class ComboItem(models.Model):
    combo = models.ForeignKey(Combo, on_delete=models.CASCADE, related_name='combo_items')
    menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)

    def __str__(self):
        return f"{self.quantity}x {self.menu_item.name} in {self.combo.name}"


class SyankoConfiguration(models.Model):
    """
    Stores global configuration overrides from Syanko Flare (Admin UI),
    such as HERO_PRODUCT, RECOMMENDED_ITEMS, MEALS, BRAND, and FEATURES.
    """
    key = models.CharField(max_length=100, unique=True)
    value = models.JSONField(default=dict)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['key']

    def __str__(self):
        return self.key
