# services/inventory/app/api/batch.py
"""
Inventory Batch API - Batch operations for enterprise dashboards

Phase 2 optimization: Eliminate N+1 query patterns by fetching inventory data
for multiple tenants in a single request.
"""

from fastapi import APIRouter, Depends, HTTPException, Body
from typing import List, Dict, Any
from uuid import UUID
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession
import structlog
import asyncio

from app.core.database import get_db
from app.services.dashboard_service import DashboardService
from app.services.inventory_service import InventoryService
from shared.auth.decorators import get_current_user_dep

router = APIRouter(tags=["inventory-batch"])
logger = structlog.get_logger()


class InventorySummaryBatchRequest(BaseModel):
    """Request model for batch inventory summary"""
    tenant_ids: List[str] = Field(..., description="List of tenant IDs", max_length=100)


class InventorySummary(BaseModel):
    """Inventory summary for a single tenant"""
    tenant_id: str
    total_value: float
    out_of_stock_count: int
    low_stock_count: int
    adequate_stock_count: int
    total_ingredients: int


@router.post("/batch/inventory-summary", response_model=Dict[str, InventorySummary])
async def get_inventory_summary_batch(
    request: InventorySummaryBatchRequest = Body(...),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Get inventory summary for multiple tenants in a single request.

    Optimized for enterprise dashboards to eliminate N+1 query patterns.
    Fetches inventory data for all tenants in parallel.

    Args:
        request: Batch request with tenant IDs

    Returns:
        Dictionary mapping tenant_id -> inventory summary

    Example:
        POST /api/v1/inventory/batch/inventory-summary
        {
            "tenant_ids": ["tenant-1", "tenant-2", "tenant-3"]
        }

        Response:
        {
            "tenant-1": {"tenant_id": "tenant-1", "total_value": 15000, ...},
            "tenant-2": {"tenant_id": "tenant-2", "total_value": 12000, ...},
            "tenant-3": {"tenant_id": "tenant-3", "total_value": 18000, ...}
        }
    """
    try:
        if len(request.tenant_ids) > 100:
            raise HTTPException(
                status_code=400,
                detail="Maximum 100 tenant IDs allowed per batch request"
            )

        if not request.tenant_ids:
            return {}

        logger.info(
            "Batch fetching inventory summaries",
            tenant_count=len(request.tenant_ids)
        )

        async def fetch_tenant_inventory(tenant_id: str) -> tuple[str, InventorySummary]:
            """Fetch inventory summary for a single tenant"""
            try:
                tenant_uuid = UUID(tenant_id)
                dashboard_service = DashboardService(
                    inventory_service=InventoryService(),
                    food_safety_service=None
                )

                overview = await dashboard_service.get_inventory_overview(db, tenant_uuid)

                return tenant_id, InventorySummary(
                    tenant_id=tenant_id,
                    total_value=float(overview.get('total_value', 0)),
                    out_of_stock_count=int(overview.get('out_of_stock_count', 0)),
                    low_stock_count=int(overview.get('low_stock_count', 0)),
                    adequate_stock_count=int(overview.get('adequate_stock_count', 0)),
                    total_ingredients=int(overview.get('total_ingredients', 0))
                )
            except Exception as e:
                logger.warning(
                    "Failed to fetch inventory for tenant in batch",
                    tenant_id=tenant_id,
                    error=str(e)
                )
                return tenant_id, InventorySummary(
                    tenant_id=tenant_id,
                    total_value=0.0,
                    out_of_stock_count=0,
                    low_stock_count=0,
                    adequate_stock_count=0,
                    total_ingredients=0
                )

        # Fetch all tenant inventory data in parallel
        tasks = [fetch_tenant_inventory(tid) for tid in request.tenant_ids]
        results = await asyncio.gather(*tasks, return_exceptions=True)

        # Build result dictionary
        result_dict = {}
        for result in results:
            if isinstance(result, Exception):
                logger.error("Exception in batch inventory fetch", error=str(result))
                continue
            tenant_id, summary = result
            result_dict[tenant_id] = summary

        logger.info(
            "Batch inventory summaries retrieved",
            requested_count=len(request.tenant_ids),
            successful_count=len(result_dict)
        )

        return result_dict

    except HTTPException:
        raise
    except Exception as e:
        logger.error("Error in batch inventory summary", error=str(e), exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to fetch batch inventory summaries: {str(e)}"
        )
