# app/modules/marketplace/models/marketplace_product.py
"""Marketplace Product model for multi-marketplace product integration.

This model stores canonical product data from various marketplaces (Letzshop,
Amazon, eBay, CodesWholesale, etc.) in a universal format. It supports:
- Physical and digital products
- Multi-language translations (via MarketplaceProductTranslation)
- Flexible attributes for marketplace-specific data
- Google Shopping fields for Letzshop compatibility

Money values are stored as integer cents (e.g., €105.91 = 10591).
Weight is stored as integer grams (e.g., 1.5kg = 1500g).
See docs/architecture/money-handling.md for details.
"""

from enum import Enum

from sqlalchemy import (
    Boolean,
    Column,
    Index,
    Integer,
    String,
)
from sqlalchemy.dialects.sqlite import JSON
from sqlalchemy.orm import relationship

from app.core.database import Base
from app.utils.money import cents_to_euros, euros_to_cents
from models.database.base import TimestampMixin


class ProductType(str, Enum):
    """Product type classification."""

    PHYSICAL = "physical"
    DIGITAL = "digital"
    SERVICE = "service"
    SUBSCRIPTION = "subscription"


class DigitalDeliveryMethod(str, Enum):
    """Digital product delivery methods."""

    DOWNLOAD = "download"
    EMAIL = "email"
    IN_APP = "in_app"
    STREAMING = "streaming"
    LICENSE_KEY = "license_key"


class MarketplaceProduct(Base, TimestampMixin):
    """Canonical product data from marketplace sources.

    This table stores normalized product information from all marketplace sources.
    Localized content (title, description) is stored in MarketplaceProductTranslation.

    Price fields use integer cents for precision (€19.99 = 1999 cents).
    Weight uses integer grams (1.5kg = 1500 grams).
    """

    __tablename__ = "marketplace_products"

    id = Column(Integer, primary_key=True, index=True)

    # === UNIVERSAL IDENTIFIERS ===
    marketplace_product_id = Column(String, unique=True, index=True, nullable=False)
    gtin = Column(String, index=True)  # EAN/UPC - primary cross-marketplace matching
    mpn = Column(String, index=True)  # Manufacturer Part Number
    sku = Column(String, index=True)  # Internal SKU if assigned

    # === SOURCE TRACKING ===
    marketplace = Column(
        String, index=True, nullable=True, default="letzshop"
    )  # 'letzshop', 'amazon', 'ebay', 'codeswholesale'
    source_url = Column(String)  # Original product URL
    store_name = Column(String, index=True)  # Seller/store in marketplace

    # === PRODUCT TYPE ===
    product_type_enum = Column(
        String(20), nullable=False, default=ProductType.PHYSICAL.value
    )
    is_digital = Column(Boolean, default=False, index=True)

    # === DIGITAL PRODUCT FIELDS ===
    digital_delivery_method = Column(String(20))  # DigitalDeliveryMethod values
    platform = Column(String(50), index=True)  # 'steam', 'playstation', 'xbox', etc.
    region_restrictions = Column(JSON)  # ["EU", "US"] or null for global
    license_type = Column(String(50))  # 'single_use', 'subscription', 'lifetime'

    # === NON-LOCALIZED FIELDS ===
    brand = Column(String, index=True)
    google_product_category = Column(String, index=True)
    category_path = Column(String)  # Normalized category hierarchy
    condition = Column(String)

    # === PRICING (stored as integer cents) ===
    price = Column(String)  # Raw price string "19.99 EUR" (kept for reference)
    price_cents = Column(Integer)  # Parsed numeric price in cents
    sale_price = Column(String)  # Raw sale price string
    sale_price_cents = Column(Integer)  # Parsed numeric sale price in cents
    currency = Column(String(3), default="EUR")

    # === TAX / VAT ===
    # Luxembourg VAT rates: 0 (exempt), 3 (super-reduced), 8 (reduced), 14 (intermediate), 17 (standard)
    # Prices are stored as gross (VAT-inclusive). Default to standard rate.
    tax_rate_percent = Column(Integer, default=17, nullable=False)

    # === MEDIA ===
    image_link = Column(String)
    additional_image_link = Column(String)  # Legacy single string
    additional_images = Column(JSON)  # Array of image URLs

    # === PRODUCT ATTRIBUTES (Flexible) ===
    attributes = Column(JSON)  # {color, size, material, etc.}

    # === PHYSICAL PRODUCT FIELDS ===
    weight_grams = Column(Integer)  # Weight in grams (1.5kg = 1500)
    weight_unit = Column(String(10), default="kg")  # Display unit
    dimensions = Column(JSON)  # {length, width, height, unit}

    # === GOOGLE SHOPPING FIELDS (Preserved for Letzshop) ===
    link = Column(String)
    availability = Column(String, index=True)
    adult = Column(String)
    multipack = Column(Integer)
    is_bundle = Column(String)
    age_group = Column(String)
    color = Column(String)
    gender = Column(String)
    material = Column(String)
    pattern = Column(String)
    size = Column(String)
    size_type = Column(String)
    size_system = Column(String)
    item_group_id = Column(String)
    product_type_raw = Column(String)  # Original feed value (renamed from product_type)
    custom_label_0 = Column(String)
    custom_label_1 = Column(String)
    custom_label_2 = Column(String)
    custom_label_3 = Column(String)
    custom_label_4 = Column(String)
    unit_pricing_measure = Column(String)
    unit_pricing_base_measure = Column(String)
    identifier_exists = Column(String)
    shipping = Column(String)

    # === STATUS ===
    is_active = Column(Boolean, default=True, index=True)

    # === RELATIONSHIPS ===
    translations = relationship(
        "MarketplaceProductTranslation",
        back_populates="marketplace_product",
        cascade="all, delete-orphan",
    )
    store_products = relationship("Product", back_populates="marketplace_product")

    # === INDEXES ===
    __table_args__ = (
        Index("idx_marketplace_store", "marketplace", "store_name"),
        Index("idx_marketplace_brand", "marketplace", "brand"),
        Index("idx_mp_gtin_marketplace", "gtin", "marketplace"),
        Index("idx_mp_product_type", "product_type_enum", "is_digital"),
    )

    def __repr__(self):
        return (
            f"<MarketplaceProduct(id={self.id}, "
            f"marketplace_product_id='{self.marketplace_product_id}', "
            f"marketplace='{self.marketplace}', "
            f"store='{self.store_name}')>"
        )

    # === PRICE PROPERTIES (Euro convenience accessors) ===

    @property
    def price_numeric(self) -> float | None:
        """Get price in euros (for API/display). Legacy name for compatibility."""
        if self.price_cents is not None:
            return cents_to_euros(self.price_cents)
        return None

    @price_numeric.setter
    def price_numeric(self, value: float | None):
        """Set price from euros. Legacy name for compatibility."""
        self.price_cents = euros_to_cents(value) if value is not None else None

    @property
    def sale_price_numeric(self) -> float | None:
        """Get sale price in euros (for API/display). Legacy name for compatibility."""
        if self.sale_price_cents is not None:
            return cents_to_euros(self.sale_price_cents)
        return None

    @sale_price_numeric.setter
    def sale_price_numeric(self, value: float | None):
        """Set sale price from euros. Legacy name for compatibility."""
        self.sale_price_cents = euros_to_cents(value) if value is not None else None

    @property
    def weight(self) -> float | None:
        """Get weight in kg (for API/display)."""
        if self.weight_grams is not None:
            return self.weight_grams / 1000.0
        return None

    @weight.setter
    def weight(self, value: float | None):
        """Set weight from kg."""
        self.weight_grams = int(value * 1000) if value is not None else None

    # === HELPER PROPERTIES ===

    @property
    def product_type(self) -> ProductType:
        """Get product type as enum."""
        return ProductType(self.product_type_enum)

    @product_type.setter
    def product_type(self, value: ProductType | str):
        """Set product type from enum or string."""
        if isinstance(value, ProductType):
            self.product_type_enum = value.value
        else:
            self.product_type_enum = value

    @property
    def delivery_method(self) -> DigitalDeliveryMethod | None:
        """Get digital delivery method as enum."""
        if self.digital_delivery_method:
            return DigitalDeliveryMethod(self.digital_delivery_method)
        return None

    @delivery_method.setter
    def delivery_method(self, value: DigitalDeliveryMethod | str | None):
        """Set delivery method from enum or string."""
        if value is None:
            self.digital_delivery_method = None
        elif isinstance(value, DigitalDeliveryMethod):
            self.digital_delivery_method = value.value
        else:
            self.digital_delivery_method = value

    def get_translation(self, language: str) -> "MarketplaceProductTranslation | None":
        """Get translation for a specific language."""
        for t in self.translations:
            if t.language == language:
                return t
        return None

    def get_title(self, language: str = "en") -> str | None:
        """Get title for a specific language with fallback to 'en'."""
        translation = self.get_translation(language)
        if translation:
            return translation.title

        # Fallback to English
        if language != "en":
            en_translation = self.get_translation("en")
            if en_translation:
                return en_translation.title

        return None

    def get_description(self, language: str = "en") -> str | None:
        """Get description for a specific language with fallback to 'en'."""
        translation = self.get_translation(language)
        if translation:
            return translation.description

        # Fallback to English
        if language != "en":
            en_translation = self.get_translation("en")
            if en_translation:
                return en_translation.description

        return None

    @property
    def effective_price(self) -> float | None:
        """Get the effective numeric price in euros."""
        return self.price_numeric

    @property
    def effective_sale_price(self) -> float | None:
        """Get the effective numeric sale price in euros."""
        return self.sale_price_numeric

    @property
    def all_images(self) -> list[str]:
        """Get all product images as a list."""
        images = []
        if self.image_link:
            images.append(self.image_link)
        if self.additional_images:
            images.extend(self.additional_images)
        elif self.additional_image_link:
            # Legacy single string format
            images.append(self.additional_image_link)
        return images


# Import MarketplaceProductTranslation for type hints
from app.modules.marketplace.models.marketplace_product_translation import (
    MarketplaceProductTranslation,
)
