"""Marketplace PART 1: Catalog and Vendor Layer.

OWNERSHIP MAP (what lives here vs where FKs point):
    OWNS: Category, SubCategory, Brand - marketplace-specific catalog taxonomy
    OWNS: ProductVariant, VariantAttribute - extension of products.Product
    OWNS: ProductImage, ProductVideo - media extension of products.Product
    OWNS: ProductSpecification, ProductTag - detail/discovery extension
    OWNS: ProductSEO - SEO extension of products.Product
    OWNS: Vendor layer (Vendor to VendorPayout) - vendor management domain
    OWNS: VendorContract, ContractPricing - vendor commercial terms domain

DOES NOT OWN (references only):
    products.Product - single authoritative product record
    orders.Order - single authoritative order record
    geo.FranchiseStore - single authoritative franchise identity
"""

from decimal import Decimal
from django.db import models
from django.contrib.auth import get_user_model
from django.core.validators import MinValueValidator
import uuid

User = get_user_model()


# =============================================================================
# PRODUCT CATALOG LAYER
# Marketplace-specific taxonomy. These are distinct from the existing
# products.Product.Category (PHYSICAL/SERVICE/VOUCHER) enum which is an
# opportunity-bundle concept. These categories are for retail marketplace browsing.
# =============================================================================

class Category(models.Model):
    """Top-level marketplace product categories (e.g. 'Health & Wellness', 'Electronics')."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=255, unique=True)
    slug = models.SlugField(unique=True)
    description = models.TextField(blank=True, null=True)
    icon_url = models.URLField(blank=True, null=True)
    image_url = models.URLField(blank=True, null=True)
    is_active = models.BooleanField(default=True)
    display_order = models.IntegerField(default=0)
    seo_title = models.CharField(max_length=255, blank=True)
    seo_description = models.CharField(max_length=500, blank=True)
    seo_keywords = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['display_order', 'name']
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name


class SubCategory(models.Model):
    """Second-level marketplace category under a Category."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    category = models.ForeignKey(Category, on_delete=models.PROTECT, related_name='subcategories')
    name = models.CharField(max_length=255)
    slug = models.SlugField()
    description = models.TextField(blank=True, null=True)
    image_url = models.URLField(blank=True, null=True)
    is_active = models.BooleanField(default=True)
    display_order = models.IntegerField(default=0)
    seo_title = models.CharField(max_length=255, blank=True)
    seo_description = models.CharField(max_length=500, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['display_order', 'name']
        unique_together = ('category', 'slug')
        verbose_name_plural = 'Sub Categories'

    def __str__(self):
        return f'{self.category.name} > {self.name}'


class Brand(models.Model):
    """Product brand (e.g. 'Nike', 'Samsung'). Referenced from products.Product.brand FK."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=255, unique=True)
    slug = models.SlugField(unique=True)
    logo_url = models.URLField(blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    website = models.URLField(blank=True, null=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name


# =============================================================================
# PRODUCT EXTENSION LAYER
# These models extend products.Product with marketplace-specific data.
# SINGLE AUTHORITATIVE PRODUCT: always use products.Product as the anchor.
# All FKs here point to 'products.Product' — the marketplace app never owns Product.
# =============================================================================

class ProductVariant(models.Model):
    """
    Product variant (size, colour, flavour, etc.) for a marketplace product.
    FK to products.Product (not a duplicate Product model).
    Stock tracked here is variant-level; WarehouseStock tracks warehouse-level.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='variants',
    )
    sku = models.CharField(max_length=100, unique=True)
    name = models.CharField(max_length=255, help_text="e.g., 'Red – Size M'")

    # Price override for this variant; null = use product base price
    mrp = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    selling_price = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    buy_price = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)

    # Variant-level stock count (distinct from WarehouseStock; used only when variant tracking needed)
    stock = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [models.Index(fields=['product', 'is_active'])]

    def __str__(self):
        return f'{self.product_id} — {self.name}'


class VariantAttribute(models.Model):
    """Key-value attribute for a variant (e.g. Size: M, Colour: Red)."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    variant = models.ForeignKey(ProductVariant, on_delete=models.CASCADE, related_name='attributes')
    attribute_name = models.CharField(max_length=100)
    attribute_value = models.CharField(max_length=100)

    class Meta:
        unique_together = ('variant', 'attribute_name')

    def __str__(self):
        return f'{self.attribute_name}: {self.attribute_value}'


class ProductImage(models.Model):
    """
    Marketplace product image gallery.
    Note: products.ProductImage uses an ImageField (file upload). This model uses
    URLField (CDN/cloud storage URL). Both coexist in their respective apps.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='marketplace_images',
    )
    image_url = models.URLField()
    alt_text = models.CharField(max_length=255, blank=True)
    display_order = models.PositiveIntegerField(default=0)
    is_primary = models.BooleanField(default=False)
    uploaded_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['display_order']
        indexes = [models.Index(fields=['product', 'is_primary'])]

    def __str__(self):
        return f'{self.product_id} — image {self.display_order}'


class ProductVideo(models.Model):
    """Marketplace product video (YouTube / Vimeo / direct upload). Phase 2 feature."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='marketplace_videos',
    )
    video_url = models.URLField()
    title = models.CharField(max_length=255, blank=True)
    description = models.TextField(blank=True)
    video_type = models.CharField(
        max_length=20,
        choices=[('YOUTUBE', 'YouTube'), ('VIMEO', 'Vimeo'), ('UPLOAD', 'Uploaded')],
        default='YOUTUBE',
    )
    display_order = models.PositiveIntegerField(default=0)
    uploaded_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['display_order']


class ProductSpecification(models.Model):
    """Key-value specification (e.g. Material: Cotton, Weight: 500g)."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='specifications',
    )
    key = models.CharField(max_length=255)
    value = models.CharField(max_length=255)
    display_order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['display_order']
        unique_together = ('product', 'key')


class ProductTag(models.Model):
    """Freeform tags for marketplace product discovery."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='marketplace_tags',
    )
    tag = models.CharField(max_length=100, db_index=True)

    class Meta:
        unique_together = ('product', 'tag')


class ProductSEO(models.Model):
    """
    Extended SEO metadata for a marketplace product.
    products.Product already has meta_title / meta_description / meta_keywords
    for basic use. This model adds Open Graph, schema markup, and canonical URL
    for marketplace product pages. OneToOne: one SEO record per product.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    product = models.OneToOneField(
        'products.Product', on_delete=models.CASCADE, related_name='seo',
    )
    meta_title = models.CharField(max_length=255)
    meta_description = models.CharField(max_length=500)
    meta_keywords = models.TextField(blank=True, help_text="Comma-separated keywords")
    canonical_url = models.URLField(blank=True, null=True)
    og_title = models.CharField(max_length=255, blank=True)
    og_description = models.CharField(max_length=500, blank=True)
    og_image = models.URLField(blank=True, null=True)
    schema_markup = models.JSONField(default=dict, blank=True)
    updated_at = models.DateTimeField(auto_now=True)


# =============================================================================
# VENDOR LAYER
# Vendor is the authoritative seller entity for vendor-managed marketplace products.
# products.Product.vendor FK → Vendor (set when vendor_managed=True).
# =============================================================================

class Vendor(models.Model):
    """
    Marketplace vendor account. Linked to a User via OneToOneField.
    products.Product.vendor → FK here when the product is vendor-managed.
    """
    VENDOR_STATUS_CHOICES = (
        ('PENDING', 'Pending Approval'),
        ('APPROVED', 'Approved'),
        ('SUSPENDED', 'Suspended'),
        ('REJECTED', 'Rejected'),
    )

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='vendor_profile')

    company_name = models.CharField(max_length=255)
    company_registration_number = models.CharField(max_length=100, unique=True)
    tax_id = models.CharField(max_length=100, unique=True)

    business_email = models.EmailField()
    business_phone = models.CharField(max_length=20)
    business_address = models.TextField()
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    pincode = models.CharField(max_length=10)
    country = models.CharField(max_length=100, default='India')

    store_name = models.CharField(max_length=255)
    store_description = models.TextField(blank=True)
    store_logo_url = models.URLField(blank=True, null=True)
    store_banner_url = models.URLField(blank=True, null=True)

    status = models.CharField(
        max_length=20, choices=VENDOR_STATUS_CHOICES, default='PENDING', db_index=True,
    )
    is_active = models.BooleanField(default=False)
    approval_date = models.DateTimeField(null=True, blank=True)
    suspension_reason = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        indexes = [
            models.Index(fields=['status', 'is_active']),
        ]

    def __str__(self):
        return self.company_name


class VendorDocument(models.Model):
    """KYC / verification documents uploaded by vendor during onboarding."""
    DOCUMENT_TYPE_CHOICES = (
        ('REGISTRATION', 'Company Registration'),
        ('TAX', 'Tax Certificate'),
        ('BANK', 'Bank Statement'),
        ('IDENTITY', 'Identity Proof'),
        ('BUSINESS_LICENSE', 'Business License'),
        ('OTHER', 'Other'),
    )

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, related_name='documents')
    document_type = models.CharField(max_length=20, choices=DOCUMENT_TYPE_CHOICES)
    document_number = models.CharField(max_length=100)
    document_file_url = models.URLField()
    expiry_date = models.DateField(null=True, blank=True)
    is_verified = models.BooleanField(default=False)
    verified_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, null=True, blank=True,
        related_name='verified_vendor_docs',
    )
    verified_at = models.DateTimeField(null=True, blank=True)
    uploaded_at = models.DateTimeField(auto_now_add=True)


class VendorBankAccount(models.Model):
    """Verified bank account used for vendor payouts. OneToOne per vendor."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vendor = models.OneToOneField(Vendor, on_delete=models.CASCADE, related_name='bank_account')
    account_holder_name = models.CharField(max_length=255)
    account_number = models.CharField(max_length=20)
    account_type = models.CharField(
        max_length=20, choices=[('SAVINGS', 'Savings'), ('CURRENT', 'Current')],
    )
    ifsc_code = models.CharField(max_length=11)
    bank_name = models.CharField(max_length=255)
    is_verified = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class VendorInventory(models.Model):
    """
    Stock held by a vendor for a specific product.
    SINGLE SOURCE OF TRUTH for vendor-side inventory.
    Use SELECT FOR UPDATE when reading stock during order reservation.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, related_name='inventory')
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='vendor_inventories',
    )
    stock = models.PositiveIntegerField(default=0)
    reserved_stock = models.PositiveIntegerField(default=0)
    reorder_point = models.PositiveIntegerField(default=10)
    last_restocked = models.DateTimeField(null=True, blank=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('vendor', 'product')
        indexes = [models.Index(fields=['product', 'vendor'])]

    @property
    def available_stock(self):
        return max(0, self.stock - self.reserved_stock)

    @property
    def is_low_stock(self):
        return self.available_stock <= self.reorder_point


class VendorEarning(models.Model):
    """
    Per-order earning record for a vendor.
    Business logic (commission calculation) MUST be in VendorEarningService,
    NOT in save(). Fields are set explicitly before creation.
    Idempotency: unique on (vendor, order) — no duplicate earning for same order.
    """
    STATUS_CHOICES = [
        ('PENDING', 'Pending'),
        ('PROCESSED', 'Processed'),
        ('PAID', 'Paid'),
        ('CANCELLED', 'Cancelled'),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, related_name='earnings')
    # CORRECTED: FK to existing orders.Order (not a duplicate marketplace.Order)
    order = models.ForeignKey(
        'orders.Order', on_delete=models.CASCADE, related_name='vendor_earnings',
    )
    gross_amount = models.DecimalField(max_digits=12, decimal_places=2)
    commission_percentage = models.DecimalField(max_digits=5, decimal_places=2)
    commission_amount = models.DecimalField(
        max_digits=12, decimal_places=2,
        help_text="Set by VendorEarningService before save. Do NOT rely on save() to compute.",
    )
    net_amount = models.DecimalField(
        max_digits=12, decimal_places=2,
        help_text="gross_amount - commission_amount. Set explicitly by service.",
    )
    status = models.CharField(
        max_length=20, choices=STATUS_CHOICES, default='PENDING', db_index=True,
    )
    created_at = models.DateTimeField(auto_now_add=True)
    payout_date = models.DateTimeField(null=True, blank=True)

    class Meta:
        unique_together = ('vendor', 'order')
        indexes = [
            models.Index(fields=['vendor', 'status']),
            models.Index(fields=['status', 'created_at']),
        ]


class VendorPayout(models.Model):
    """
    Payout disbursement to a vendor for a billing period.
    Pattern: set status=PROCESSING before initiating bank transfer (idempotency guard).
    Never re-process a payout that is already PROCESSING or COMPLETED.
    """
    STATUS_CHOICES = [
        ('PENDING', 'Pending'),
        ('PROCESSING', 'Processing'),
        ('COMPLETED', 'Completed'),
        ('FAILED', 'Failed'),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, related_name='payouts')
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    period_start = models.DateField()
    period_end = models.DateField()
    status = models.CharField(
        max_length=20, choices=STATUS_CHOICES, default='PENDING', db_index=True,
    )
    transaction_id = models.CharField(max_length=100, null=True, blank=True)
    failure_reason = models.TextField(blank=True, null=True)
    paid_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [models.Index(fields=['vendor', 'status'])]


# =============================================================================
# VENDOR CONTRACT LAYER
# Commercial terms between the company and a vendor.
# =============================================================================

class VendorContract(models.Model):
    """Commercial contract between the platform and a vendor."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, related_name='contracts')
    contract_number = models.CharField(max_length=100, unique=True)
    start_date = models.DateField()
    end_date = models.DateField()
    base_commission_percentage = models.DecimalField(
        max_digits=5, decimal_places=2, default=Decimal('10.00'),
    )
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        indexes = [models.Index(fields=['vendor', 'is_active'])]

    def __str__(self):
        return f'Contract: {self.vendor.company_name} — {self.contract_number}'


class ContractPricing(models.Model):
    """
    Product-level pricing rule within a vendor contract.
    CORRECTED: franchise FK points to geo.FranchiseStore (not removed FranchiseHead).
    Precedence rule: FRANCHISE > PINCODE > GLOBAL (use priority in service layer).
    """
    PRICING_TIER_CHOICES = (
        ('GLOBAL', 'Global'),
        ('PINCODE', 'Pincode-based'),
        ('FRANCHISE', 'Franchise-store-based'),
    )

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    contract = models.ForeignKey(
        VendorContract, on_delete=models.CASCADE, related_name='pricing_rules',
    )
    product = models.ForeignKey(
        'products.Product', on_delete=models.CASCADE, related_name='contract_pricing',
    )
    pricing_tier = models.CharField(
        max_length=20, choices=PRICING_TIER_CHOICES, default='GLOBAL',
    )
    pincode = models.CharField(max_length=10, null=True, blank=True)
    # CORRECTED: FK to geo.FranchiseStore (canonical franchise entity)
    franchise_store = models.ForeignKey(
        'geo.FranchiseStore',
        on_delete=models.SET_NULL, null=True, blank=True,
        related_name='contract_pricing_rules',
        help_text="Franchise store this pricing rule applies to (FRANCHISE tier only)",
    )
    buy_price = models.DecimalField(max_digits=12, decimal_places=2)
    sell_price = models.DecimalField(max_digits=12, decimal_places=2)
    margin_percentage = models.DecimalField(max_digits=5, decimal_places=2)
    valid_from = models.DateTimeField()
    valid_until = models.DateTimeField()

    class Meta:
        unique_together = ('contract', 'product', 'pricing_tier', 'pincode', 'franchise_store')
        indexes = [
            models.Index(fields=['product', 'pricing_tier', 'valid_until']),
        ]


class ContractMargin(models.Model):
    """
    Category-level margin configuration within a contract (Phase 2 feature).
    Example: all 'New Launch' products get 15% margin during the launch period.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    contract = models.ForeignKey(
        VendorContract, on_delete=models.CASCADE, related_name='margins',
    )
    margin_type = models.CharField(
        max_length=50, help_text="e.g. 'Premium Products', 'New Launch', 'Seasonal'",
    )
    margin_percentage = models.DecimalField(max_digits=5, decimal_places=2)
    applicable_from = models.DateField()
    applicable_until = models.DateField()

