# app/modules/catalog/services/store_product_service.py
"""
Store product service for managing store-specific product catalogs.

This module provides:
- Store product catalog browsing
- Product search and filtering
- Product statistics
- Product removal from catalogs
"""

import logging

from sqlalchemy import func
from sqlalchemy.orm import Session, joinedload

from app.modules.catalog.exceptions import ProductNotFoundException
from app.modules.catalog.models import Product

logger = logging.getLogger(__name__)


class StoreProductService:
    """Service for store product catalog operations."""

    def get_products(
        self,
        db: Session,
        skip: int = 0,
        limit: int = 50,
        search: str | None = None,
        store_id: int | None = None,
        is_active: bool | None = None,
        is_featured: bool | None = None,
        language: str = "en",
    ) -> tuple[list[dict], int]:
        """
        Get store products with search and filtering.

        Returns:
            Tuple of (products list as dicts, total count)
        """
        query = (
            db.query(Product)
            .options(
                joinedload(Product.store),
                joinedload(Product.marketplace_product),
                joinedload(Product.translations),
            )
        )

        if search:
            search_term = f"%{search}%"
            query = query.filter(Product.store_sku.ilike(search_term))

        if store_id:
            query = query.filter(Product.store_id == store_id)

        if is_active is not None:
            query = query.filter(Product.is_active == is_active)

        if is_featured is not None:
            query = query.filter(Product.is_featured == is_featured)

        total = query.count()

        products = (
            query.order_by(Product.updated_at.desc()).offset(skip).limit(limit).all()
        )

        result = []
        for product in products:
            result.append(self._build_product_list_item(product, language))

        return result, total

    def get_product_stats(self, db: Session, store_id: int | None = None) -> dict:
        """Get store product statistics for admin dashboard.

        Args:
            db: Database session
            store_id: Optional store ID to filter stats

        Returns:
            Dict with product counts (total, active, inactive, etc.)
        """
        # Base query filter
        base_filter = Product.store_id == store_id if store_id else True

        total = db.query(func.count(Product.id)).filter(base_filter).scalar() or 0

        active = (
            db.query(func.count(Product.id))
            .filter(base_filter)
            .filter(Product.is_active == True)  # noqa: E712
            .scalar()
            or 0
        )
        inactive = total - active

        featured = (
            db.query(func.count(Product.id))
            .filter(base_filter)
            .filter(Product.is_featured == True)  # noqa: E712
            .scalar()
            or 0
        )

        # Digital/physical counts
        digital = (
            db.query(func.count(Product.id))
            .filter(base_filter)
            .join(Product.marketplace_product)
            .filter(Product.marketplace_product.has(is_digital=True))
            .scalar()
            or 0
        )
        physical = total - digital

        # Count by store (only when not filtered by store_id)
        by_store = {}
        if not store_id:
            # Get product counts grouped by store_id
            store_id_counts = (
                db.query(
                    Product.store_id,
                    func.count(Product.id),
                )
                .group_by(Product.store_id)
                .all()
            )
            # Resolve store names via service
            from app.modules.tenancy.services.store_service import store_service
            for sid, count in store_id_counts:
                store = store_service.get_store_by_id_optional(db, sid)
                name = store.name if store else "unknown"
                by_store[name] = count

        return {
            "total": total,
            "active": active,
            "inactive": inactive,
            "featured": featured,
            "digital": digital,
            "physical": physical,
            "by_store": by_store,
        }

    def get_catalog_stores(self, db: Session) -> list[dict]:
        """Get list of stores with products in their catalogs."""
        from app.modules.tenancy.services.store_service import store_service

        # Get distinct store IDs that have products
        store_ids = (
            db.query(Product.store_id)
            .distinct()
            .all()
        )
        result = []
        for (sid,) in store_ids:
            store = store_service.get_store_by_id_optional(db, sid)
            if store:
                result.append({"id": store.id, "name": store.name, "store_code": store.store_code})
        return result

    def get_product_detail(self, db: Session, product_id: int) -> dict:
        """Get detailed store product information including override info."""
        product = (
            db.query(Product)
            .options(
                joinedload(Product.store),
                joinedload(Product.marketplace_product),
                joinedload(Product.translations),
            )
            .filter(Product.id == product_id)
            .first()
        )

        if not product:
            raise ProductNotFoundException(product_id)

        mp = product.marketplace_product
        source_comparison_info = product.get_source_comparison_info()

        # Get marketplace product translations (for "view original source")
        mp_translations = {}
        if mp:
            for t in mp.translations:
                mp_translations[t.language] = {
                    "title": t.title,
                    "description": t.description,
                    "short_description": t.short_description,
                }

        # Get store translations
        store_translations = {}
        for t in product.translations:
            store_translations[t.language] = {
                "title": t.title,
                "description": t.description,
            }

        # Convenience fields for UI (prefer store translations, fallback to English)
        title = None
        description = None
        if store_translations:
            # Try English first, then first available language
            if "en" in store_translations:
                title = store_translations["en"].get("title")
                description = store_translations["en"].get("description")
            elif store_translations:
                first_lang = next(iter(store_translations))
                title = store_translations[first_lang].get("title")
                description = store_translations[first_lang].get("description")

        return {
            "id": product.id,
            "store_id": product.store_id,
            "store_name": product.store.name if product.store else None,
            "store_code": product.store.store_code if product.store else None,
            "marketplace_product_id": product.marketplace_product_id,
            "store_sku": product.store_sku,
            # Product identifiers
            "gtin": product.gtin,
            "gtin_type": product.gtin_type or "ean13",
            # Product fields with source comparison info
            **source_comparison_info,
            # Store-specific fields
            "is_featured": product.is_featured,
            "is_active": product.is_active,
            "display_order": product.display_order,
            "min_quantity": product.min_quantity,
            "max_quantity": product.max_quantity,
            # Supplier tracking
            "supplier": product.supplier,
            "supplier_product_id": product.supplier_product_id,
            "cost": product.cost,
            "margin_percent": product.margin_percent,
            # Tax/profit info
            "tax_rate_percent": product.tax_rate_percent,
            "net_price": product.net_price,
            "vat_amount": product.vat_amount,
            "profit": product.profit,
            "profit_margin_percent": product.profit_margin_percent,
            # Digital fulfillment
            "download_url": product.download_url,
            "license_type": product.license_type,
            "fulfillment_email_template": product.fulfillment_email_template,
            # Source info from marketplace product
            "source_marketplace": mp.marketplace if mp else None,
            "source_store": mp.store_name if mp else None,
            "source_gtin": mp.gtin if mp else None,
            "source_sku": mp.sku if mp else None,
            # Translations
            "marketplace_translations": mp_translations,
            "store_translations": store_translations,
            # Convenience fields for UI display
            "title": title,
            "description": description,
            "image_url": product.primary_image_url,
            "additional_images": product.additional_images or [],
            # Timestamps
            "created_at": product.created_at.isoformat()
            if product.created_at
            else None,
            "updated_at": product.updated_at.isoformat()
            if product.updated_at
            else None,
        }

    def create_product(self, db: Session, data: dict) -> Product:
        """Create a new store product.

        Args:
            db: Database session
            data: Product data dict (includes translations dict for multiple languages)

        Returns:
            Created Product instance
        """
        from app.modules.catalog.models import ProductTranslation

        # Determine product_type from is_digital flag
        is_digital = data.get("is_digital", False)
        product_type = "digital" if is_digital else data.get("product_type", "physical")

        product = Product(
            store_id=data["store_id"],
            store_sku=data.get("store_sku"),
            brand=data.get("brand"),
            gtin=data.get("gtin"),
            gtin_type=data.get("gtin_type"),
            currency=data.get("currency", "EUR"),
            tax_rate_percent=data.get("tax_rate_percent", 17),
            availability=data.get("availability"),
            primary_image_url=data.get("primary_image_url"),
            additional_images=data.get("additional_images"),
            is_active=data.get("is_active", True),
            is_featured=data.get("is_featured", False),
            is_digital=is_digital,
            product_type=product_type,
        )

        # Handle price fields via setters (convert to cents)
        if data.get("price") is not None:
            product.price = data["price"]
        if data.get("sale_price") is not None:
            product.sale_price = data["sale_price"]

        db.add(product)
        db.flush()  # Get the product ID

        # Handle translations dict (new format with multiple languages)
        translations = data.get("translations")
        if translations:
            for lang, trans_data in translations.items():
                if trans_data and (trans_data.get("title") or trans_data.get("description")):
                    translation = ProductTranslation(
                        product_id=product.id,
                        language=lang,
                        title=trans_data.get("title"),
                        description=trans_data.get("description"),
                    )
                    db.add(translation)
        else:
            # Fallback for old format with single title/description
            title = data.get("title")
            description = data.get("description")
            if title or description:
                translation = ProductTranslation(
                    product_id=product.id,
                    language="en",
                    title=title,
                    description=description,
                )
                db.add(translation)

        db.flush()

        logger.info(f"Created store product {product.id} for store {data['store_id']}")

        return product

    def update_product(self, db: Session, product_id: int, data: dict) -> Product:
        """Update a store product.

        Args:
            db: Database session
            product_id: Product ID to update
            data: Fields to update (may include translations dict)

        Returns:
            Updated Product instance
        """
        from app.modules.catalog.models import ProductTranslation

        product = (
            db.query(Product)
            .options(joinedload(Product.translations))
            .filter(Product.id == product_id)
            .first()
        )

        if not product:
            raise ProductNotFoundException(product_id)

        # Handle translations separately
        if "translations" in data and data["translations"]:
            existing_translations = {t.language: t for t in product.translations}

            for lang, trans_data in data["translations"].items():
                if lang in existing_translations:
                    # Update existing translation
                    if "title" in trans_data:
                        existing_translations[lang].title = trans_data["title"]
                    if "description" in trans_data:
                        existing_translations[lang].description = trans_data["description"]
                else:
                    # Create new translation
                    new_trans = ProductTranslation(
                        product_id=product_id,
                        language=lang,
                        title=trans_data.get("title"),
                        description=trans_data.get("description"),
                    )
                    db.add(new_trans)

        # Handle price (convert to cents)
        if "price" in data and data["price"] is not None:
            product.price = data["price"]  # Uses property setter to convert to cents

        if "sale_price" in data:
            product.sale_price = data["sale_price"]  # Uses property setter

        if "cost" in data:
            product.cost = data["cost"]  # Uses property setter

        # Update other allowed fields
        updatable_fields = [
            "store_sku",
            "brand",
            "gtin",
            "gtin_type",
            "currency",
            "tax_rate_percent",
            "availability",
            "is_digital",
            "is_active",
            "is_featured",
            "primary_image_url",
            "additional_images",
            "supplier",
        ]

        for field in updatable_fields:
            if field in data:
                setattr(product, field, data[field])

        db.flush()

        logger.info(f"Updated store product {product_id}")

        return product

    def remove_product(self, db: Session, product_id: int) -> dict:
        """Remove a product from store catalog."""
        product = db.query(Product).filter(Product.id == product_id).first()

        if not product:
            raise ProductNotFoundException(product_id)

        store_name = product.store.name if product.store else "Unknown"
        db.delete(product)
        db.flush()

        logger.info(f"Removed product {product_id} from store {store_name} catalog")

        return {"message": f"Product removed from {store_name}'s catalog"}

    def _build_product_list_item(self, product: Product, language: str) -> dict:
        """Build a product list item dict."""
        mp = product.marketplace_product

        # Get title: prefer store translations, fallback to marketplace translations
        title = None
        # First try store's own translations
        if product.translations:
            for trans in product.translations:
                if trans.language == language and trans.title:
                    title = trans.title
                    break
            # Fallback to English if requested language not found
            if not title:
                for trans in product.translations:
                    if trans.language == "en" and trans.title:
                        title = trans.title
                        break
        # Fallback to marketplace translations
        if not title and mp:
            title = mp.get_title(language)

        return {
            "id": product.id,
            "store_id": product.store_id,
            "store_name": product.store.name if product.store else None,
            "store_code": product.store.store_code if product.store else None,
            "marketplace_product_id": product.marketplace_product_id,
            "store_sku": product.store_sku,
            "title": title,
            "brand": product.brand,
            "price": product.price,
            "currency": product.currency,
            # Effective price/currency for UI (same as price/currency for now)
            "effective_price": product.price,
            "effective_currency": product.currency,
            "is_active": product.is_active,
            "is_featured": product.is_featured,
            "is_digital": product.is_digital,
            "image_url": product.primary_image_url,
            "source_marketplace": mp.marketplace if mp else None,
            "source_store": mp.store_name if mp else None,
            "created_at": product.created_at.isoformat()
            if product.created_at
            else None,
            "updated_at": product.updated_at.isoformat()
            if product.updated_at
            else None,
        }


# Create service instance
store_product_service = StoreProductService()
