from django.db import models, transaction
from decimal import Decimal
from apps.core.models import BaseModel
# from apps.business.schemes.models import opportunity_bundle

class Product(BaseModel):

    class Category(models.TextChoices):
        PHYSICAL = "PHYSICAL", "Physical Product"
        SERVICE = "SERVICE", "Service"
        VOUCHER = "VOUCHER", "Voucher"

    class ProductType(models.TextChoices):
        STANDARD = "STANDARD", "Standard"
        PREMIUM_VOUCHER = "PREMIUM_VOUCHER", "Premium Voucher"
        TWM_COINS = "TWM_COINS", "TWM Coins"

    name = models.CharField(max_length=255)
    sort_order = models.PositiveIntegerField(
        default=1000,
        db_index=True,
        help_text="Lower values appear first in product listings.",
    )
    hsn_code = models.CharField(max_length=20, blank=True, null=True, help_text="HSN/SAC code for GST invoicing")
    category = models.CharField(max_length=32, choices=Category.choices)
    product_type = models.CharField(max_length=32, choices=ProductType.choices, default=ProductType.STANDARD)
    description = models.TextField(blank=True, null=True)
    base_cost = models.DecimalField(max_digits=12, decimal_places=2)
    gst_percentage = models.DecimalField(max_digits=6, decimal_places=3)
    opportunity_bundle = models.ForeignKey("schemes.OpportunityBundle", null=True, blank=True, on_delete=models.SET_NULL, db_index=True)
    is_pooling_enabled = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    # TWM Coins product type fields (only relevant when category=VOUCHER, product_type=TWM_COINS)
    twm_coin_amount = models.DecimalField(
        max_digits=12, decimal_places=2, null=True, blank=True,
        help_text="Coins to credit to the buyer's TWM wallet on purchase (TWM_COINS type only)",
    )
    twm_coin_expiry_days = models.PositiveIntegerField(
        null=True, blank=True,
        help_text="Expiry days for awarded coins (0 or null = no expiry, TWM_COINS type only)",
    )

    # Multi-wallet payment configuration
    allow_main_wallet = models.BooleanField(default=True, help_text="Allow payment via main earnings wallet")
    allow_repurchase = models.BooleanField(default=False, help_text="Allow payment via repurchase wallet")
    allow_supercoins = models.BooleanField(default=True, help_text="Allow partial/full payment using Super Coins")
    allow_twm = models.BooleanField(default=True, help_text="Allow up to twm_max_percentage via TWM Coins")
    twm_max_percentage = models.PositiveIntegerField(default=50, help_text="Maximum percentage payable via TWM Coins (0–100)")
    allow_part_payment = models.BooleanField(
        default=False,
        help_text="Allow bundle checkout with partial payment mode",
    )
    part_payment_percentage = models.PositiveIntegerField(
        default=50,
        help_text="Initial payment percentage when part payment is selected (1-99)",
    )
    part_payment_initial_amount = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        null=True,
        blank=True,
        help_text="Initial fixed amount when part payment is selected. If null, fallback to the conversion product's base_cost.",
    )
    part_payment_cooling_days = models.PositiveIntegerField(
        default=180,
        help_text="Cooling period in days before pending part payments are converted",
    )
    part_payment_conversion_product = models.ForeignKey(
        'self',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='part_payment_source_products',
        help_text="Fallback product/service assigned when part payment cooling period elapses",
    )
    default_dispatch_address = models.ForeignKey(
        'invoice.DispatchAddress',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='products',
        help_text="Default dispatch address for this product",
    )
    # -------------------------------------------------------------------------
    # MARKETPLACE EXTENSION FIELDS
    # These fields extend the existing opportunity-bundle Product for use in the
    # retail marketplace. All are nullable so existing bundle records are unaffected.
    # -------------------------------------------------------------------------

    # Marketplace identity
    slug = models.SlugField(
        max_length=255, unique=True, null=True, blank=True,
        help_text="URL slug for marketplace product page",
    )
    sku = models.CharField(
        max_length=100, unique=True, null=True, blank=True,
        help_text="Unique marketplace SKU (auto-generated or vendor-provided)",
    )
    mrp = models.DecimalField(
        max_digits=12, decimal_places=2, null=True, blank=True,
        help_text="Maximum Retail Price for marketplace display",
    )

    # Marketplace catalog classification
    marketplace_category = models.ForeignKey(
        'marketplace.Category',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='products',
        help_text="Marketplace-specific category (separate from bundle product_type)",
    )
    marketplace_subcategory = models.ForeignKey(
        'marketplace.SubCategory',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='products',
    )
    brand = models.ForeignKey(
        'marketplace.Brand',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='branded_products',
    )

    # Vendor ownership (null = company-owned product)
    vendor = models.ForeignKey(
        'marketplace.Vendor',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='vendor_products',
        help_text="Set if this product is listed and fulfilled by a marketplace vendor",
    )

    # Commerce capability flags
    # is_opportunity_bundle is derived: bool(self.opportunity_bundle_id)
    vendor_managed = models.BooleanField(
        default=False,
        help_text="Product catalog and inventory managed by vendor",
    )
    franchise_fulfilled = models.BooleanField(
        default=False,
        help_text="Product can be fulfilled by franchise stores",
    )
    digital_product = models.BooleanField(
        default=False,
        help_text="No physical inventory or shipping required",
    )
    rating_enabled = models.BooleanField(default=True)
    review_enabled = models.BooleanField(default=True)
    is_featured = models.BooleanField(default=False)

    # Marketplace publish status (null = not listed in marketplace)
    MARKETPLACE_STATUS_CHOICES = [
        ('DRAFT', 'Draft'),
        ('PENDING_APPROVAL', 'Pending Approval'),
        ('ACTIVE', 'Active'),
        ('INACTIVE', 'Inactive'),
        ('DISCONTINUED', 'Discontinued'),
    ]
    marketplace_status = models.CharField(
        max_length=20,
        choices=MARKETPLACE_STATUS_CHOICES,
        null=True, blank=True,
        db_index=True,
        help_text="Marketplace publish status (null = bundle-only product, not marketplace-listed)",
    )

    # Cached rating aggregates — updated via signal in marketplace.community, never edited directly
    average_rating = models.DecimalField(
        max_digits=3, decimal_places=2,
        default=Decimal('0.00'),
        help_text="Cached average review rating (0.00–5.00). Updated by signal.",
    )
    total_ratings = models.PositiveIntegerField(
        default=0,
        help_text="Total published review count. Updated by signal.",
    )

    class Meta:
        ordering = ['sort_order', 'created_at', 'id']
        constraints = [
            models.CheckConstraint(
                condition=models.Q(twm_max_percentage__gte=0) & models.Q(twm_max_percentage__lte=100),
                name="products_twm_max_percentage_range",
            ),
            models.CheckConstraint(
                condition=models.Q(part_payment_percentage__gte=1) & models.Q(part_payment_percentage__lte=99),
                name="products_part_payment_percentage_range",
            ),
            models.CheckConstraint(
                condition=models.Q(part_payment_cooling_days__gte=1),
                name="products_part_payment_cooling_days_positive",
            ),
        ]

    def __str__(self):
        return self.name


class ProductImage(BaseModel):
    product = models.ForeignKey(Product, related_name='images', on_delete=models.CASCADE, db_index=True)
    image = models.ImageField(upload_to='products/')
    alt_text = models.CharField(max_length=255, blank=True)
    is_primary = models.BooleanField(default=False, db_index=True)
    sort_order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['sort_order', 'created_at']
        indexes = [
            models.Index(fields=['product', 'is_primary']),
            models.Index(fields=['product', 'sort_order']),
        ]

    def save(self, *args, **kwargs):
        with transaction.atomic():
            super().save(*args, **kwargs)
            if self.is_primary:
                ProductImage.objects.filter(product=self.product, is_primary=True).exclude(pk=self.pk).update(is_primary=False)

    def __str__(self):
        return f"{self.product_id} image"
