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

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

from fastapi import APIRouter, Depends, HTTPException, Body, Path
from typing import List, Dict, Any
from datetime import date
from uuid import UUID
from pydantic import BaseModel, Field
import structlog
import asyncio

from app.services.sales_service import SalesService
from shared.auth.decorators import get_current_user_dep
from shared.routing import RouteBuilder
from shared.auth.access_control import require_user_role

route_builder = RouteBuilder('sales')
router = APIRouter(tags=["sales-batch"])
logger = structlog.get_logger()


def get_sales_service():
    """Dependency injection for SalesService"""
    return SalesService()


class SalesSummaryBatchRequest(BaseModel):
    """Request model for batch sales summary"""
    tenant_ids: List[str] = Field(..., description="List of tenant IDs", max_length=100)
    start_date: date = Field(..., description="Start date for sales period")
    end_date: date = Field(..., description="End date for sales period")


class SalesSummary(BaseModel):
    """Sales summary for a single tenant"""
    tenant_id: str
    total_revenue: float
    total_orders: int
    average_order_value: float
    period_start: str
    period_end: str


@router.post("/api/v1/batch/sales-summary", response_model=Dict[str, SalesSummary])
async def get_sales_summary_batch(
    request: SalesSummaryBatchRequest = Body(...),
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    sales_service: SalesService = Depends(get_sales_service)
):
    """
    Get sales summary for multiple tenants in a single request.

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

    Args:
        request: Batch request with tenant IDs and date range

    Returns:
        Dictionary mapping tenant_id -> sales summary

    Example:
        POST /api/v1/sales/batch/sales-summary
        {
            "tenant_ids": ["tenant-1", "tenant-2", "tenant-3"],
            "start_date": "2025-01-01",
            "end_date": "2025-01-31"
        }

        Response:
        {
            "tenant-1": {"tenant_id": "tenant-1", "total_revenue": 50000, ...},
            "tenant-2": {"tenant_id": "tenant-2", "total_revenue": 45000", ...},
            "tenant-3": {"tenant_id": "tenant-3", "total_revenue": 52000, ...}
        }
    """
    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 sales summaries",
            tenant_count=len(request.tenant_ids),
            start_date=str(request.start_date),
            end_date=str(request.end_date)
        )

        async def fetch_tenant_sales(tenant_id: str) -> tuple[str, SalesSummary]:
            """Fetch sales summary for a single tenant"""
            try:
                tenant_uuid = UUID(tenant_id)
                summary = await sales_service.get_sales_analytics(
                    tenant_uuid,
                    request.start_date,
                    request.end_date
                )

                return tenant_id, SalesSummary(
                    tenant_id=tenant_id,
                    total_revenue=float(summary.get('total_revenue', 0)),
                    total_orders=int(summary.get('total_orders', 0)),
                    average_order_value=float(summary.get('average_order_value', 0)),
                    period_start=str(request.start_date),
                    period_end=str(request.end_date)
                )
            except Exception as e:
                logger.warning(
                    "Failed to fetch sales for tenant in batch",
                    tenant_id=tenant_id,
                    error=str(e)
                )
                return tenant_id, SalesSummary(
                    tenant_id=tenant_id,
                    total_revenue=0.0,
                    total_orders=0,
                    average_order_value=0.0,
                    period_start=str(request.start_date),
                    period_end=str(request.end_date)
                )

        # Fetch all tenant sales in parallel
        tasks = [fetch_tenant_sales(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 sales fetch", error=str(result))
                continue
            tenant_id, summary = result
            result_dict[tenant_id] = summary

        logger.info(
            "Batch sales 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 sales summary", error=str(e), exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to fetch batch sales summaries: {str(e)}"
        )
