# app/services/letzshop_export_service.py
"""
Service for exporting products to Letzshop CSV format.

Generates Google Shopping compatible CSV files for Letzshop marketplace.
"""

from __future__ import annotations

import csv
import io
import logging
from datetime import datetime
from typing import TYPE_CHECKING

from sqlalchemy.orm import Session, joinedload

from app.modules.marketplace.models import LetzshopSyncLog, MarketplaceProduct

if TYPE_CHECKING:
    from app.modules.catalog.models import Product

logger = logging.getLogger(__name__)

# Letzshop CSV columns in order
LETZSHOP_CSV_COLUMNS = [
    "id",
    "title",
    "description",
    "link",
    "image_link",
    "additional_image_link",
    "availability",
    "price",
    "sale_price",
    "brand",
    "gtin",
    "mpn",
    "google_product_category",
    "product_type",
    "condition",
    "adult",
    "multipack",
    "is_bundle",
    "age_group",
    "color",
    "gender",
    "material",
    "pattern",
    "size",
    "size_type",
    "size_system",
    "item_group_id",
    "custom_label_0",
    "custom_label_1",
    "custom_label_2",
    "custom_label_3",
    "custom_label_4",
    "identifier_exists",
    "unit_pricing_measure",
    "unit_pricing_base_measure",
    "shipping",
    "atalanda:tax_rate",
    "atalanda:quantity",
    "atalanda:boost_sort",
    "atalanda:delivery_method",
]


class LetzshopExportService:
    """Service for exporting products to Letzshop CSV format."""

    def __init__(self, default_tax_rate: float = 17.0):
        """
        Initialize the export service.

        Args:
            default_tax_rate: Default VAT rate for Luxembourg (17%)
        """
        self.default_tax_rate = default_tax_rate

    def export_store_products(
        self,
        db: Session,
        store_id: int,
        language: str = "en",
        include_inactive: bool = False,
    ) -> str:
        """
        Export all products for a store in Letzshop CSV format.

        Args:
            db: Database session
            store_id: Store ID to export products for
            language: Language for title/description (en, fr, de)
            include_inactive: Whether to include inactive products

        Returns:
            CSV string content
        """
        # Query products for this store with their marketplace product data
        from app.modules.catalog.models import Product as ProductModel

        query = (
            db.query(ProductModel)
            .filter(ProductModel.store_id == store_id)
            .options(
                joinedload(ProductModel.marketplace_product).joinedload(
                    MarketplaceProduct.translations
                )
            )
        )

        if not include_inactive:
            query = query.filter(ProductModel.is_active == True)

        products = query.all()

        logger.info(
            f"Exporting {len(products)} products for store {store_id} in {language}"
        )

        return self._generate_csv(products, language)

    def export_marketplace_products(
        self,
        db: Session,
        marketplace: str = "Letzshop",
        language: str = "en",
        limit: int | None = None,
    ) -> str:
        """
        Export marketplace products directly (admin use).

        Args:
            db: Database session
            marketplace: Filter by marketplace source
            language: Language for title/description
            limit: Optional limit on number of products

        Returns:
            CSV string content
        """
        query = (
            db.query(MarketplaceProduct)
            .filter(MarketplaceProduct.is_active == True)
            .options(joinedload(MarketplaceProduct.translations))
        )

        if marketplace:
            query = query.filter(
                MarketplaceProduct.marketplace.ilike(f"%{marketplace}%")
            )

        if limit:
            query = query.limit(limit)

        products = query.all()

        logger.info(
            f"Exporting {len(products)} marketplace products for {marketplace} in {language}"
        )

        return self._generate_csv_from_marketplace_products(products, language)

    def _generate_csv(self, products: list[Product], language: str) -> str:
        """Generate CSV from store Product objects."""
        output = io.StringIO()
        writer = csv.DictWriter(
            output,
            fieldnames=LETZSHOP_CSV_COLUMNS,
            delimiter="\t",
            quoting=csv.QUOTE_MINIMAL,
        )
        writer.writeheader()

        for product in products:
            if product.marketplace_product:
                row = self._product_to_row(product, language)
                writer.writerow(row)

        return output.getvalue()

    def _generate_csv_from_marketplace_products(
        self, products: list[MarketplaceProduct], language: str
    ) -> str:
        """Generate CSV from MarketplaceProduct objects directly."""
        output = io.StringIO()
        writer = csv.DictWriter(
            output,
            fieldnames=LETZSHOP_CSV_COLUMNS,
            delimiter="\t",
            quoting=csv.QUOTE_MINIMAL,
        )
        writer.writeheader()

        for mp in products:
            row = self._marketplace_product_to_row(mp, language)
            writer.writerow(row)

        return output.getvalue()

    def _product_to_row(self, product: Product, language: str) -> dict:
        """Convert a Product (with MarketplaceProduct) to a CSV row."""
        mp = product.marketplace_product
        return self._marketplace_product_to_row(
            mp, language, store_sku=product.store_sku
        )

    def _marketplace_product_to_row(
        self,
        mp: MarketplaceProduct,
        language: str,
        store_sku: str | None = None,
    ) -> dict:
        """Convert a MarketplaceProduct to a CSV row dict."""
        # Get localized title and description
        title = mp.get_title(language) or ""
        description = mp.get_description(language) or ""

        # Format price with currency
        price = ""
        if mp.price_numeric:
            price = f"{mp.price_numeric:.2f} {mp.currency or 'EUR'}"
        elif mp.price:
            price = mp.price

        # Format sale price
        sale_price = ""
        if mp.sale_price_numeric:
            sale_price = f"{mp.sale_price_numeric:.2f} {mp.currency or 'EUR'}"
        elif mp.sale_price:
            sale_price = mp.sale_price

        # Additional images - join with comma if multiple
        additional_images = ""
        if mp.additional_images:
            additional_images = ",".join(mp.additional_images)
        elif mp.additional_image_link:
            additional_images = mp.additional_image_link

        # Determine identifier_exists
        identifier_exists = mp.identifier_exists
        if not identifier_exists:
            identifier_exists = "yes" if (mp.gtin or mp.mpn) else "no"

        return {
            "id": store_sku or mp.marketplace_product_id,
            "title": title,
            "description": description,
            "link": mp.link or mp.source_url or "",
            "image_link": mp.image_link or "",
            "additional_image_link": additional_images,
            "availability": mp.availability or "in stock",
            "price": price,
            "sale_price": sale_price,
            "brand": mp.brand or "",
            "gtin": mp.gtin or "",
            "mpn": mp.mpn or "",
            "google_product_category": mp.google_product_category or "",
            "product_type": mp.product_type_raw or "",
            "condition": mp.condition or "new",
            "adult": mp.adult or "no",
            "multipack": str(mp.multipack) if mp.multipack else "",
            "is_bundle": mp.is_bundle or "no",
            "age_group": mp.age_group or "",
            "color": mp.color or "",
            "gender": mp.gender or "",
            "material": mp.material or "",
            "pattern": mp.pattern or "",
            "size": mp.size or "",
            "size_type": mp.size_type or "",
            "size_system": mp.size_system or "",
            "item_group_id": mp.item_group_id or "",
            "custom_label_0": mp.custom_label_0 or "",
            "custom_label_1": mp.custom_label_1 or "",
            "custom_label_2": mp.custom_label_2 or "",
            "custom_label_3": mp.custom_label_3 or "",
            "custom_label_4": mp.custom_label_4 or "",
            "identifier_exists": identifier_exists,
            "unit_pricing_measure": mp.unit_pricing_measure or "",
            "unit_pricing_base_measure": mp.unit_pricing_base_measure or "",
            "shipping": mp.shipping or "",
            "atalanda:tax_rate": str(self.default_tax_rate),
            "atalanda:quantity": "",  # Would need inventory data
            "atalanda:boost_sort": "",
            "atalanda:delivery_method": "",
        }

    def log_export(
        self,
        db: Session,
        store_id: int,
        started_at: datetime,
        completed_at: datetime,
        files_processed: int,
        files_succeeded: int,
        files_failed: int,
        products_exported: int,
        triggered_by: str,
        error_details: dict | None = None,
    ) -> LetzshopSyncLog:
        """
        Log an export operation to the sync log.

        Args:
            db: Database session
            store_id: Store ID
            started_at: When the export started
            completed_at: When the export completed
            files_processed: Number of language files to export (e.g., 3)
            files_succeeded: Number of files successfully exported
            files_failed: Number of files that failed
            products_exported: Total products in the export
            triggered_by: Who triggered the export (e.g., "admin:123")
            error_details: Optional error details if any failures

        Returns:
            Created LetzshopSyncLog entry
        """
        sync_log = LetzshopSyncLog(
            store_id=store_id,
            operation_type="product_export",
            direction="outbound",
            status="completed" if files_failed == 0 else "partial",
            records_processed=files_processed,
            records_succeeded=files_succeeded,
            records_failed=files_failed,
            started_at=started_at,
            completed_at=completed_at,
            duration_seconds=int((completed_at - started_at).total_seconds()),
            triggered_by=triggered_by,
            error_details={
                "products_exported": products_exported,
                **(error_details or {}),
            } if products_exported or error_details else None,
        )
        db.add(sync_log)
        db.flush()
        return sync_log


# Singleton instance
letzshop_export_service = LetzshopExportService()
