# services/inventory/app/api/ingredients.py
"""
API endpoints for ingredient management
"""

from typing import List, Optional
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, Path, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.services.inventory_service import InventoryService
from app.schemas.inventory import (
    IngredientCreate,
    IngredientUpdate,
    IngredientResponse,
    StockResponse,
    InventoryFilter,
    PaginatedResponse
)
from shared.auth.decorators import get_current_user_dep

router = APIRouter(tags=["ingredients"])

# Helper function to extract user ID from user object
def get_current_user_id(current_user: dict = Depends(get_current_user_dep)) -> UUID:
    """Extract user ID from current user context"""
    user_id = current_user.get('user_id')
    if not user_id:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="User ID not found in context"
        )
    return UUID(user_id)


@router.post("/tenants/{tenant_id}/ingredients", response_model=IngredientResponse)
async def create_ingredient(
    ingredient_data: IngredientCreate,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Create a new ingredient"""
    try:
        # Extract user ID - handle service tokens that don't have UUID user_ids
        raw_user_id = current_user.get('user_id')
        if current_user.get('type') == 'service':
            # For service tokens, user_id might not be a UUID, so set to None
            user_id = None
        else:
            try:
                user_id = UUID(raw_user_id)
            except (ValueError, TypeError):
                user_id = None
        
        service = InventoryService()
        ingredient = await service.create_ingredient(ingredient_data, tenant_id, user_id)
        return ingredient
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create ingredient"
        )


@router.get("/tenants/{tenant_id}/ingredients/count")
async def count_ingredients(
    tenant_id: UUID = Path(...),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
) -> dict:
    """Get count of ingredients for a tenant"""

    try:
        service = InventoryService()
        count = await service.count_ingredients_by_tenant(tenant_id)

        return {
            "tenant_id": str(tenant_id),
            "ingredient_count": count
        }

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to count ingredients: {str(e)}"
        )


@router.get("/tenants/{tenant_id}/ingredients/{ingredient_id}", response_model=IngredientResponse)
async def get_ingredient(
    ingredient_id: UUID,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    db: AsyncSession = Depends(get_db)
):
    """Get ingredient by ID"""
    try:
        service = InventoryService()
        ingredient = await service.get_ingredient(ingredient_id, tenant_id)
        
        if not ingredient:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Ingredient not found"
            )
        
        return ingredient
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get ingredient"
        )


@router.put("/tenants/{tenant_id}/ingredients/{ingredient_id}", response_model=IngredientResponse)
async def update_ingredient(
    ingredient_id: UUID,
    ingredient_data: IngredientUpdate,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    db: AsyncSession = Depends(get_db)
):
    """Update ingredient"""
    try:            
        service = InventoryService()
        ingredient = await service.update_ingredient(ingredient_id, ingredient_data, tenant_id)
        
        if not ingredient:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Ingredient not found"
            )
        
        return ingredient
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to update ingredient"
        )


@router.get("/tenants/{tenant_id}/ingredients", response_model=List[IngredientResponse])
async def list_ingredients(
    tenant_id: UUID = Path(..., description="Tenant ID"),
    skip: int = Query(0, ge=0, description="Number of records to skip"),
    limit: int = Query(100, ge=1, le=1000, description="Number of records to return"),
    category: Optional[str] = Query(None, description="Filter by category"),
    product_type: Optional[str] = Query(None, description="Filter by product type (ingredient or finished_product)"),
    is_active: Optional[bool] = Query(None, description="Filter by active status"),
    is_low_stock: Optional[bool] = Query(None, description="Filter by low stock status"),
    needs_reorder: Optional[bool] = Query(None, description="Filter by reorder needed"),
    search: Optional[str] = Query(None, description="Search in name, SKU, or barcode"),
    db: AsyncSession = Depends(get_db)
):
    """List ingredients with filtering"""
    try:
            
        service = InventoryService()
        
        # Build filters
        filters = {}
        if category:
            filters['category'] = category
        if product_type:
            filters['product_type'] = product_type
        if is_active is not None:
            filters['is_active'] = is_active
        if is_low_stock is not None:
            filters['is_low_stock'] = is_low_stock
        if needs_reorder is not None:
            filters['needs_reorder'] = needs_reorder
        if search:
            filters['search'] = search
        
        ingredients = await service.get_ingredients(tenant_id, skip, limit, filters)
        return ingredients
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to list ingredients"
        )


@router.delete("/tenants/{tenant_id}/ingredients/{ingredient_id}", status_code=status.HTTP_204_NO_CONTENT)
async def soft_delete_ingredient(
    ingredient_id: UUID,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    db: AsyncSession = Depends(get_db)
):
    """Soft delete ingredient (mark as inactive)"""
    try:
        service = InventoryService()
        result = await service.soft_delete_ingredient(ingredient_id, tenant_id)
        return None
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to soft delete ingredient"
        )


@router.delete("/tenants/{tenant_id}/ingredients/{ingredient_id}/hard")
async def hard_delete_ingredient(
    ingredient_id: UUID,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    db: AsyncSession = Depends(get_db)
):
    """Hard delete ingredient and all associated data (stock, movements, etc.)"""
    try:
        service = InventoryService()
        deletion_summary = await service.hard_delete_ingredient(ingredient_id, tenant_id)
        return deletion_summary
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to hard delete ingredient"
        )


@router.get("/tenants/{tenant_id}/ingredients/{ingredient_id}/stock", response_model=List[StockResponse])
async def get_ingredient_stock(
    ingredient_id: UUID,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    include_unavailable: bool = Query(False, description="Include unavailable stock"),
    db: AsyncSession = Depends(get_db)
):
    """Get stock entries for an ingredient"""
    try:
            
        service = InventoryService()
        stock_entries = await service.get_stock_by_ingredient(
            ingredient_id, tenant_id, include_unavailable
        )
        return stock_entries
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get ingredient stock"
        )