# app/modules/analytics/services/stats_service.py
"""
Statistics service for generating system analytics and metrics.

This is the canonical location for the stats service.

This module provides:
- System-wide statistics (admin)
- Store-specific statistics
- Marketplace analytics
- Performance metrics
"""

import logging
from datetime import datetime, timedelta
from typing import Any

from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session

from app.modules.tenancy.exceptions import (
    AdminOperationException,
    StoreNotFoundException,
)

logger = logging.getLogger(__name__)


class StatsService:
    """Service for statistics operations."""

    # ========================================================================
    # STORE-SPECIFIC STATISTICS
    # ========================================================================

    def get_store_stats(self, db: Session, store_id: int) -> dict[str, Any]:
        """
        Get statistics for a specific store.

        Args:
            db: Database session
            store_id: Store ID

        Returns:
            Dictionary with store statistics

        Raises:
            StoreNotFoundException: If store doesn't exist
            AdminOperationException: If database query fails
        """
        from app.modules.catalog.services.product_service import product_service
        from app.modules.customers.services.customer_service import customer_service
        from app.modules.inventory.services.inventory_service import inventory_service
        from app.modules.marketplace.services.marketplace_import_job_service import (
            marketplace_import_job_service,
        )
        from app.modules.marketplace.services.marketplace_product_service import (
            marketplace_product_service,
        )
        from app.modules.orders.services.order_service import order_service
        from app.modules.tenancy.services.store_service import store_service

        # Verify store exists
        store = store_service.get_store_by_id_optional(db, store_id)
        if not store:
            raise StoreNotFoundException(str(store_id), identifier_type="id")

        try:
            # Catalog statistics
            total_catalog_products = product_service.get_store_product_count(
                db, store_id, active_only=True,
            )

            featured_products = product_service.get_store_product_count(
                db, store_id, active_only=True, featured_only=True,
            )

            # Staging statistics
            staging_products = marketplace_product_service.get_staging_product_count(
                db, store_name=store.name,
            )

            # Inventory statistics
            inv_stats = inventory_service.get_store_inventory_stats(db, store_id)
            total_inventory = inv_stats["total"]
            reserved_inventory = inv_stats["reserved"]
            inventory_locations = inv_stats["locations"]

            # Import statistics
            import_stats = marketplace_import_job_service.get_import_job_stats(
                db, store_id=store_id,
            )
            total_imports = import_stats["total"]
            successful_imports = import_stats["completed"]

            # Orders
            total_orders = order_service.get_store_order_count(db, store_id)

            # Customers
            total_customers = customer_service.get_store_customer_count(db, store_id)

            # Return flat structure compatible with StoreDashboardStatsResponse schema
            # The endpoint will restructure this into nested format
            return {
                # Product stats
                "total_products": total_catalog_products,
                "active_products": total_catalog_products,
                "featured_products": featured_products,
                # Order stats (TODO: implement when Order model has status field)
                "total_orders": total_orders,
                "pending_orders": 0,  # TODO: filter by status
                "completed_orders": 0,  # TODO: filter by status
                # Customer stats
                "total_customers": total_customers,
                "active_customers": 0,  # TODO: implement active customer logic
                # Revenue stats (TODO: implement when Order model has amount field)
                "total_revenue": 0,
                "revenue_this_month": 0,
                # Import stats
                "total_imports": total_imports,
                "successful_imports": successful_imports,
                "import_success_rate": (
                    (successful_imports / total_imports * 100)
                    if total_imports > 0
                    else 0
                ),
                # Staging stats
                "imported_products": staging_products,
                # Inventory stats
                "total_inventory_quantity": int(total_inventory),
                "reserved_inventory_quantity": int(reserved_inventory),
                "available_inventory_quantity": int(
                    total_inventory - reserved_inventory
                ),
                "inventory_locations_count": inventory_locations,
            }

        except StoreNotFoundException:
            raise
        except SQLAlchemyError as e:
            logger.error(
                f"Failed to retrieve store statistics for store {store_id}: {str(e)}"
            )
            raise AdminOperationException(
                operation="get_store_stats",
                reason=f"Database query failed: {str(e)}",
                target_type="store",
                target_id=str(store_id),
            )

    def get_store_analytics(
        self, db: Session, store_id: int, period: str = "30d"
    ) -> dict[str, Any]:
        """
        Get a specific store analytics for a time period.

        Args:
            db: Database session
            store_id: Store ID
            period: Time period (7d, 30d, 90d, 1y)

        Returns:
            Analytics data

        Raises:
            StoreNotFoundException: If store doesn't exist
            AdminOperationException: If database query fails
        """
        from app.modules.catalog.services.product_service import product_service
        from app.modules.inventory.services.inventory_service import inventory_service
        from app.modules.marketplace.services.marketplace_import_job_service import (
            marketplace_import_job_service,
        )
        from app.modules.tenancy.services.store_service import store_service

        # Verify store exists
        store = store_service.get_store_by_id_optional(db, store_id)
        if not store:
            raise StoreNotFoundException(str(store_id), identifier_type="id")

        try:
            # Parse period
            days = self._parse_period(period)
            start_date = datetime.utcnow() - timedelta(days=days)

            # Import activity
            import_stats = marketplace_import_job_service.get_import_job_stats(
                db, store_id=store_id,
            )
            recent_imports = import_stats["total"]

            # Products added to catalog
            products_added = product_service.get_store_product_count(db, store_id)

            # Inventory changes
            inv_stats = inventory_service.get_store_inventory_stats(db, store_id)
            inventory_entries = inv_stats.get("locations", 0)

            return {
                "period": period,
                "start_date": start_date.isoformat(),
                "imports": {
                    "count": recent_imports,
                },
                "catalog": {
                    "products_added": products_added,
                },
                "inventory": {
                    "total_locations": inventory_entries,
                },
            }

        except StoreNotFoundException:
            raise
        except SQLAlchemyError as e:
            logger.error(
                f"Failed to retrieve store analytics for store {store_id}: {str(e)}"
            )
            raise AdminOperationException(
                operation="get_store_analytics",
                reason=f"Database query failed: {str(e)}",
                target_type="store",
                target_id=str(store_id),
            )

    def get_store_statistics(self, db: Session) -> dict:
        """Get store statistics for admin dashboard.

        Returns dict compatible with StoreStatsResponse schema.
        Keys: total, verified, pending, inactive (mapped from internal names)
        """
        from app.modules.tenancy.services.store_service import store_service

        try:
            total_stores = store_service.get_total_store_count(db)
            active_stores = store_service.get_total_store_count(db, active_only=True)
            inactive_stores = total_stores - active_stores
            # Use store_service for verified/pending counts
            verified_stores = store_service.get_store_count_by_status(db, verified=True)
            pending_stores = store_service.get_store_count_by_status(db, active=True, verified=False)

            return {
                "total": total_stores,
                "verified": verified_stores,
                "pending": pending_stores,
                "inactive": inactive_stores,
                "verification_rate": (
                    (verified_stores / total_stores * 100) if total_stores > 0 else 0
                ),
            }
        except SQLAlchemyError as e:
            logger.error(f"Failed to get store statistics: {str(e)}")
            raise AdminOperationException(
                operation="get_store_statistics", reason="Database query failed"
            )

    # ========================================================================
    # SYSTEM-WIDE STATISTICS (ADMIN)
    # ========================================================================

    def get_comprehensive_stats(self, db: Session) -> dict[str, Any]:
        """
        Get comprehensive system statistics for admin dashboard.

        Args:
            db: Database session

        Returns:
            Dictionary with comprehensive statistics

        Raises:
            AdminOperationException: If database query fails
        """
        try:
            from app.modules.catalog.services.product_service import product_service
            from app.modules.marketplace.services.marketplace_product_service import (
                marketplace_product_service,
            )
            from app.modules.tenancy.services.store_service import store_service

            # Stores
            total_stores = store_service.get_total_store_count(db, active_only=True)

            # Products
            total_catalog_products = product_service.get_total_product_count(db)
            unique_brands = marketplace_product_service.get_distinct_brand_count(db)
            unique_categories = marketplace_product_service.get_distinct_category_count(db)

            # Marketplaces
            unique_marketplaces = marketplace_product_service.get_distinct_marketplace_count(db)

            # Inventory
            inventory_stats = self._get_inventory_statistics(db)

            return {
                "total_products": total_catalog_products,
                "unique_brands": unique_brands,
                "unique_categories": unique_categories,
                "unique_marketplaces": unique_marketplaces,
                "unique_stores": total_stores,
                "total_inventory_entries": inventory_stats.get("total_entries", 0),
                "total_inventory_quantity": inventory_stats.get("total_quantity", 0),
            }

        except SQLAlchemyError as e:
            logger.error(f"Failed to retrieve comprehensive statistics: {str(e)}")
            raise AdminOperationException(
                operation="get_comprehensive_stats",
                reason=f"Database query failed: {str(e)}",
            )

    def get_marketplace_breakdown_stats(self, db: Session) -> list[dict[str, Any]]:
        """
        Get statistics broken down by marketplace.

        Args:
            db: Database session

        Returns:
            List of marketplace statistics

        Raises:
            AdminOperationException: If database query fails
        """
        try:
            from app.modules.marketplace.services.marketplace_product_service import (
                marketplace_product_service,
            )

            return marketplace_product_service.get_marketplace_breakdown(db)

        except SQLAlchemyError as e:
            logger.error(
                f"Failed to retrieve marketplace breakdown statistics: {str(e)}"
            )
            raise AdminOperationException(
                operation="get_marketplace_breakdown_stats",
                reason=f"Database query failed: {str(e)}",
            )

    def get_user_statistics(self, db: Session) -> dict[str, Any]:
        """
        Get user statistics for admin dashboard.

        Args:
            db: Database session

        Returns:
            Dictionary with user statistics

        Raises:
            AdminOperationException: If database query fails
        """
        try:
            from app.modules.tenancy.services.admin_service import admin_service

            user_stats = admin_service.get_user_statistics(db)
            return user_stats
        except SQLAlchemyError as e:
            logger.error(f"Failed to get user statistics: {str(e)}")
            raise AdminOperationException(
                operation="get_user_statistics", reason="Database query failed"
            )

    def get_import_statistics(self, db: Session) -> dict[str, Any]:
        """
        Get import job statistics.

        Args:
            db: Database session

        Returns:
            Dictionary with import statistics

        Raises:
            AdminOperationException: If database query fails
        """
        try:
            from app.modules.marketplace.services.marketplace_import_job_service import (
                marketplace_import_job_service,
            )

            stats = marketplace_import_job_service.get_import_job_stats(db)
            total = stats["total"]
            completed = stats["completed"]
            return {
                "total": total,
                "pending": stats["pending"],
                "processing": stats.get("processing", 0),
                "completed": completed,
                "failed": stats["failed"],
                "success_rate": (completed / total * 100) if total > 0 else 0,
            }
        except SQLAlchemyError as e:
            logger.error(f"Failed to get import statistics: {str(e)}")
            return {
                "total": 0,
                "pending": 0,
                "processing": 0,
                "completed": 0,
                "failed": 0,
                "success_rate": 0,
            }

    def get_order_statistics(self, db: Session) -> dict[str, Any]:
        """
        Get order statistics.

        Args:
            db: Database session

        Returns:
            Dictionary with order statistics

        Note:
            TODO: Implement when Order model is fully available
        """
        return {"total_orders": 0, "pending_orders": 0, "completed_orders": 0}

    def get_product_statistics(self, db: Session) -> dict[str, Any]:
        """
        Get product statistics.

        Args:
            db: Database session

        Returns:
            Dictionary with product statistics

        Note:
            TODO: Implement when Product model is fully available
        """
        return {"total_products": 0, "active_products": 0, "out_of_stock": 0}

    # ========================================================================
    # PRIVATE HELPER METHODS
    # ========================================================================

    def _parse_period(self, period: str) -> int:
        """
        Parse period string to days.

        Args:
            period: Period string (7d, 30d, 90d, 1y)

        Returns:
            Number of days
        """
        period_map = {
            "7d": 7,
            "30d": 30,
            "90d": 90,
            "1y": 365,
        }
        return period_map.get(period, 30)

    def _get_inventory_statistics(self, db: Session) -> dict[str, int]:
        """Get inventory-related statistics via inventory service."""
        from app.modules.inventory.services.inventory_service import inventory_service

        total_entries = inventory_service.get_total_inventory_count(db)
        total_quantity = inventory_service.get_total_inventory_quantity(db)
        total_reserved = inventory_service.get_total_reserved_quantity(db)

        return {
            "total_entries": total_entries,
            "total_quantity": int(total_quantity),
            "total_reserved": int(total_reserved),
            "total_available": int(total_quantity - total_reserved),
        }


# Create service instance
stats_service = StatsService()

__all__ = ["stats_service", "StatsService"]
