# services/inventory/app/api/transformations.py
"""
API endpoints for product transformations
Following standardized URL structure with role-based access control
"""

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

from app.core.database import get_db
from app.services.transformation_service import TransformationService
from app.schemas.inventory import (
    ProductTransformationCreate,
    ProductTransformationResponse
)
from app.models.inventory import ProductionStage
from shared.auth.decorators import get_current_user_dep
from shared.auth.access_control import require_user_role, admin_role_required
from shared.routing import RouteBuilder

logger = structlog.get_logger()

# Create route builder for consistent URL structure
route_builder = RouteBuilder('inventory')

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


# 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:
        # Handle service tokens that don't have UUID user_ids
        if current_user.get('type') == 'service':
            return None
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="User ID not found in context"
        )
    try:
        return UUID(user_id)
    except (ValueError, TypeError):
        return None


@router.post(
    route_builder.build_base_route("transformations"),
    response_model=ProductTransformationResponse,
    status_code=status.HTTP_201_CREATED
)
@require_user_role(['admin', 'owner', 'member'])
async def create_transformation(
    transformation_data: ProductTransformationCreate,
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Create a new product transformation (e.g., par-baked to fully baked)"""
    try:
        # Extract user ID - handle service tokens
        user_id = get_current_user_id(current_user)

        service = TransformationService()
        transformation = await service.create_transformation(transformation_data, tenant_id, user_id)
        return transformation
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error("Failed to create transformation", error=str(e), tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create transformation"
        )


@router.get(
    route_builder.build_base_route("transformations"),
    response_model=List[ProductTransformationResponse]
)
async def get_transformations(
    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"),
    ingredient_id: Optional[UUID] = Query(None, description="Filter by ingredient (source or target)"),
    source_stage: Optional[ProductionStage] = Query(None, description="Filter by source production stage"),
    target_stage: Optional[ProductionStage] = Query(None, description="Filter by target production stage"),
    days_back: Optional[int] = Query(None, ge=1, le=365, description="Filter by days back from today"),
    db: AsyncSession = Depends(get_db)
):
    """Get product transformations with filtering"""
    try:
        service = TransformationService()
        transformations = await service.get_transformations(
            tenant_id, skip, limit, ingredient_id, source_stage, target_stage, days_back
        )
        return transformations
    except Exception as e:
        logger.error("Failed to get transformations", error=str(e), tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get transformations"
        )


@router.get(
    route_builder.build_resource_detail_route("transformations", "transformation_id"),
    response_model=ProductTransformationResponse
)
async def get_transformation(
    transformation_id: UUID = Path(..., description="Transformation ID"),
    tenant_id: UUID = Path(..., description="Tenant ID"),
    db: AsyncSession = Depends(get_db)
):
    """Get specific transformation by ID"""
    try:
        service = TransformationService()
        transformation = await service.get_transformation(transformation_id, tenant_id)

        if not transformation:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Transformation not found"
            )

        return transformation
    except HTTPException:
        raise
    except Exception as e:
        logger.error("Failed to get transformation", error=str(e), transformation_id=transformation_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get transformation"
        )


@router.get(
    route_builder.build_base_route("transformations/summary"),
    response_model=dict
)
async def get_transformation_summary(
    tenant_id: UUID = Path(..., description="Tenant ID"),
    days_back: int = Query(30, ge=1, le=365, description="Days back for summary"),
    db: AsyncSession = Depends(get_db)
):
    """Get transformation summary for dashboard"""
    try:
        service = TransformationService()
        summary = await service.get_transformation_summary(tenant_id, days_back)
        return summary
    except Exception as e:
        logger.error("Failed to get transformation summary", error=str(e), tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get transformation summary"
        )


@router.post(
    route_builder.build_operations_route("transformations/par-bake-to-fresh"),
    response_model=dict
)
@require_user_role(['admin', 'owner', 'member'])
async def create_par_bake_transformation(
    source_ingredient_id: UUID = Query(..., description="Par-baked ingredient ID"),
    target_ingredient_id: UUID = Query(..., description="Fresh baked ingredient ID"),
    quantity: float = Query(..., gt=0, description="Quantity to transform"),
    target_batch_number: Optional[str] = Query(None, description="Target batch number"),
    expiration_hours: int = Query(24, ge=1, le=72, description="Hours until expiration after baking"),
    notes: Optional[str] = Query(None, description="Process notes"),
    tenant_id: UUID = Path(..., description="Tenant ID"),
    current_user: dict = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Convenience endpoint for par-baked to fresh transformation"""
    try:
        # Extract user ID - handle service tokens
        user_id = get_current_user_id(current_user)

        # Create transformation data for par-baked to fully baked
        transformation_data = ProductTransformationCreate(
            source_ingredient_id=str(source_ingredient_id),
            target_ingredient_id=str(target_ingredient_id),
            source_stage=ProductionStage.PAR_BAKED,
            target_stage=ProductionStage.FULLY_BAKED,
            source_quantity=quantity,
            target_quantity=quantity,  # Assume 1:1 ratio for par-baked goods
            expiration_calculation_method="days_from_transformation",
            expiration_days_offset=max(1, expiration_hours // 24),  # Convert hours to days, minimum 1 day
            process_notes=notes,
            target_batch_number=target_batch_number
        )

        service = TransformationService()
        transformation = await service.create_transformation(transformation_data, tenant_id, user_id)

        return {
            "transformation_id": transformation.id,
            "transformation_reference": transformation.transformation_reference,
            "source_quantity": transformation.source_quantity,
            "target_quantity": transformation.target_quantity,
            "expiration_date": transformation.transformation_date,
            "message": f"Successfully transformed {quantity} units from par-baked to fresh baked"
        }

    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error("Failed to create par-bake transformation", error=str(e), tenant_id=tenant_id)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to create par-bake transformation"
        )