# app/modules/core/routes/api/admin_dashboard.py
"""
Admin dashboard and statistics endpoints.

This module uses the StatsAggregator service from core to collect metrics from all
enabled modules. Each module provides its own metrics via the MetricsProvider protocol.

Dashboard widgets are collected via the WidgetAggregator service, which discovers
DashboardWidgetProvider implementations from all enabled modules.

For backward compatibility, this also falls back to the analytics stats_service
for comprehensive statistics that haven't been migrated to the provider pattern yet.
"""

import logging
from typing import Any

from fastapi import APIRouter, Depends, Request
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.modules.contracts.widgets import BreakdownWidget, ListWidget
from app.modules.core.schemas.dashboard import (
    AdminDashboardResponse,
    ImportStatsResponse,
    MarketplaceStatsResponse,
    OrderStatsBasicResponse,
    PlatformStatsResponse,
    ProductStatsResponse,
    StatsResponse,
    UserStatsResponse,
    VendorStatsResponse,
)
from app.modules.core.services.stats_aggregator import stats_aggregator
from app.modules.core.services.widget_aggregator import widget_aggregator
from models.schema.auth import UserContext

admin_dashboard_router = APIRouter(prefix="/dashboard")
logger = logging.getLogger(__name__)


def _get_platform_id(request: Request, current_admin: UserContext) -> int:
    """
    Get platform_id from available sources in priority order.

    Priority:
    1. JWT token (token_platform_id) - set when admin selects a platform
    2. Request state (set by PlatformContextMiddleware) - for page routes
    3. First accessible platform (for platform admins)
    4. Fallback to 1 (for super admins with global access)

    Returns:
        Platform ID to use for queries
    """
    # 1. From JWT token (most authoritative for API routes)
    if current_admin.token_platform_id:
        return current_admin.token_platform_id

    # 2. From request state (set by PlatformContextMiddleware)
    platform = getattr(request.state, "platform", None)
    if platform:
        return platform.id

    # 3. For platform admins, use their first accessible platform
    if current_admin.accessible_platform_ids:
        return current_admin.accessible_platform_ids[0]

    # 4. Fallback for super admins (global access)
    return 1


def _extract_metric_value(
    metrics: dict[str, list], category: str, key: str, default: int | float = 0
) -> int | float:
    """Extract a specific metric value from categorized metrics."""
    if category not in metrics:
        return default
    for metric in metrics[category]:
        if metric.key == key:
            return metric.value
    return default


def _widget_list_item_to_dict(item) -> dict[str, Any]:
    """Convert a WidgetListItem to a dictionary for API response."""
    return {
        "id": item.id,
        "title": item.title,
        "subtitle": item.subtitle,
        "status": item.status,
        "timestamp": item.timestamp,
        "url": item.url,
        **item.metadata,
    }


def _extract_widget_items(
    widgets: dict[str, list], category: str, key: str
) -> list[dict[str, Any]]:
    """Extract items from a list widget for backward compatibility."""
    if category not in widgets:
        return []
    for widget in widgets[category]:
        if widget.key == key and isinstance(widget.data, ListWidget):
            return [_widget_list_item_to_dict(item) for item in widget.data.items]
    return []


@admin_dashboard_router.get("", response_model=AdminDashboardResponse)
def get_admin_dashboard(
    request: Request,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get admin dashboard with platform statistics (Admin only)."""
    platform_id = _get_platform_id(request, current_admin)

    # Get aggregated metrics from all enabled modules
    metrics = stats_aggregator.get_admin_dashboard_stats(db=db, platform_id=platform_id)

    # Get aggregated widgets from all enabled modules
    widgets = widget_aggregator.get_admin_dashboard_widgets(db=db, platform_id=platform_id)

    # Extract user stats from tenancy module
    total_users = _extract_metric_value(metrics, "tenancy", "tenancy.total_users", 0)
    active_users = _extract_metric_value(metrics, "tenancy", "tenancy.active_users", 0)
    inactive_users = _extract_metric_value(metrics, "tenancy", "tenancy.inactive_users", 0)
    admin_users = _extract_metric_value(metrics, "tenancy", "tenancy.admin_users", 0)
    activation_rate = _extract_metric_value(
        metrics, "tenancy", "tenancy.user_activation_rate", 0
    )

    # Extract vendor stats from tenancy module
    total_vendors = _extract_metric_value(metrics, "tenancy", "tenancy.total_vendors", 0)
    verified_vendors = _extract_metric_value(
        metrics, "tenancy", "tenancy.verified_vendors", 0
    )
    pending_vendors = _extract_metric_value(
        metrics, "tenancy", "tenancy.pending_vendors", 0
    )
    inactive_vendors = _extract_metric_value(
        metrics, "tenancy", "tenancy.inactive_vendors", 0
    )

    # Extract recent_vendors from tenancy widget (backward compatibility)
    recent_vendors = _extract_widget_items(widgets, "tenancy", "tenancy.recent_vendors")

    # Extract recent_imports from marketplace widget (backward compatibility)
    recent_imports = _extract_widget_items(widgets, "marketplace", "marketplace.recent_imports")

    return AdminDashboardResponse(
        platform={
            "name": "Multi-Tenant Ecommerce Platform",
            "version": "1.0.0",
        },
        users=UserStatsResponse(
            total_users=int(total_users),
            active_users=int(active_users),
            inactive_users=int(inactive_users),
            admin_users=int(admin_users),
            activation_rate=float(activation_rate),
        ),
        vendors=VendorStatsResponse(
            total=int(total_vendors),
            verified=int(verified_vendors),
            pending=int(pending_vendors),
            inactive=int(inactive_vendors),
        ),
        recent_vendors=recent_vendors,
        recent_imports=recent_imports,
    )


@admin_dashboard_router.get("/stats", response_model=StatsResponse)
def get_comprehensive_stats(
    request: Request,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get comprehensive platform statistics (Admin only)."""
    platform_id = _get_platform_id(request, current_admin)

    # Get aggregated metrics
    metrics = stats_aggregator.get_admin_dashboard_stats(db=db, platform_id=platform_id)

    # Extract product stats from catalog module
    total_products = _extract_metric_value(metrics, "catalog", "catalog.total_products", 0)

    # Extract marketplace stats
    unique_marketplaces = _extract_metric_value(
        metrics, "marketplace", "marketplace.unique_marketplaces", 0
    )
    unique_brands = _extract_metric_value(
        metrics, "marketplace", "marketplace.unique_brands", 0
    )

    # Extract vendor stats
    unique_vendors = _extract_metric_value(metrics, "tenancy", "tenancy.total_vendors", 0)

    # Extract inventory stats
    inventory_entries = _extract_metric_value(metrics, "inventory", "inventory.entries", 0)
    inventory_quantity = _extract_metric_value(
        metrics, "inventory", "inventory.total_quantity", 0
    )

    return StatsResponse(
        total_products=int(total_products),
        unique_brands=int(unique_brands),
        unique_categories=0,  # TODO: Add category tracking
        unique_marketplaces=int(unique_marketplaces),
        unique_vendors=int(unique_vendors),
        total_inventory_entries=int(inventory_entries),
        total_inventory_quantity=int(inventory_quantity),
    )


@admin_dashboard_router.get(
    "/stats/marketplace", response_model=list[MarketplaceStatsResponse]
)
def get_marketplace_stats(
    request: Request,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get statistics broken down by marketplace (Admin only).

    Uses the widget_aggregator to get marketplace breakdown data from the
    marketplace module's WidgetProvider, avoiding cross-module violations.
    """
    platform_id = _get_platform_id(request, current_admin)

    # Get widgets from marketplace module via aggregator
    widgets = widget_aggregator.get_admin_dashboard_widgets(db=db, platform_id=platform_id)

    # Extract marketplace breakdown widget
    marketplace_widgets = widgets.get("marketplace", [])
    for widget in marketplace_widgets:
        if widget.key == "marketplace.breakdown" and isinstance(widget.data, BreakdownWidget):
            # Transform breakdown items to MarketplaceStatsResponse
            return [
                MarketplaceStatsResponse(
                    marketplace=item.label,
                    total_products=int(item.value),
                    unique_vendors=int(item.secondary_value or 0),
                    unique_brands=0,  # Not included in breakdown widget
                )
                for item in widget.data.items
            ]

    # No breakdown widget found
    return []


@admin_dashboard_router.get("/stats/platform", response_model=PlatformStatsResponse)
def get_platform_statistics(
    request: Request,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get comprehensive platform statistics (Admin only)."""
    platform_id = _get_platform_id(request, current_admin)

    # Get aggregated metrics from all enabled modules
    metrics = stats_aggregator.get_admin_dashboard_stats(db=db, platform_id=platform_id)

    # User stats from tenancy
    total_users = _extract_metric_value(metrics, "tenancy", "tenancy.total_users", 0)
    active_users = _extract_metric_value(metrics, "tenancy", "tenancy.active_users", 0)
    inactive_users = _extract_metric_value(metrics, "tenancy", "tenancy.inactive_users", 0)
    admin_users = _extract_metric_value(metrics, "tenancy", "tenancy.admin_users", 0)
    activation_rate = _extract_metric_value(
        metrics, "tenancy", "tenancy.user_activation_rate", 0
    )

    # Vendor stats from tenancy
    total_vendors = _extract_metric_value(metrics, "tenancy", "tenancy.total_vendors", 0)
    verified_vendors = _extract_metric_value(
        metrics, "tenancy", "tenancy.verified_vendors", 0
    )
    pending_vendors = _extract_metric_value(
        metrics, "tenancy", "tenancy.pending_vendors", 0
    )
    inactive_vendors = _extract_metric_value(
        metrics, "tenancy", "tenancy.inactive_vendors", 0
    )

    # Product stats from catalog
    total_products = _extract_metric_value(metrics, "catalog", "catalog.total_products", 0)
    active_products = _extract_metric_value(
        metrics, "catalog", "catalog.active_products", 0
    )

    # Order stats from orders
    total_orders = _extract_metric_value(metrics, "orders", "orders.total", 0)

    # Import stats from marketplace
    total_imports = _extract_metric_value(
        metrics, "marketplace", "marketplace.total_imports", 0
    )
    pending_imports = _extract_metric_value(
        metrics, "marketplace", "marketplace.pending_imports", 0
    )
    processing_imports = _extract_metric_value(
        metrics, "marketplace", "marketplace.processing_imports", 0
    )
    completed_imports = _extract_metric_value(
        metrics, "marketplace", "marketplace.successful_imports", 0
    )
    failed_imports = _extract_metric_value(
        metrics, "marketplace", "marketplace.failed_imports", 0
    )
    import_success_rate = _extract_metric_value(
        metrics, "marketplace", "marketplace.success_rate", 0
    )

    return PlatformStatsResponse(
        users=UserStatsResponse(
            total_users=int(total_users),
            active_users=int(active_users),
            inactive_users=int(inactive_users),
            admin_users=int(admin_users),
            activation_rate=float(activation_rate),
        ),
        vendors=VendorStatsResponse(
            total=int(total_vendors),
            verified=int(verified_vendors),
            pending=int(pending_vendors),
            inactive=int(inactive_vendors),
        ),
        products=ProductStatsResponse(
            total_products=int(total_products),
            active_products=int(active_products),
            out_of_stock=0,  # TODO: Implement
        ),
        orders=OrderStatsBasicResponse(
            total_orders=int(total_orders),
            pending_orders=0,  # TODO: Implement status tracking
            completed_orders=0,  # TODO: Implement status tracking
        ),
        imports=ImportStatsResponse(
            total=int(total_imports),
            pending=int(pending_imports),
            processing=int(processing_imports),
            completed=int(completed_imports),
            failed=int(failed_imports),
            success_rate=float(import_success_rate),
        ),
    )
