# services/recipes/app/services/recipe_service.py
"""
Service layer for recipe management operations
"""

import logging
from typing import List, Optional, Dict, Any
from uuid import UUID
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession

from ..repositories.recipe_repository import RecipeRepository
from ..schemas.recipes import RecipeCreate, RecipeUpdate

logger = logging.getLogger(__name__)


class RecipeService:
    """Async service for recipe management operations"""

    def __init__(self, session: AsyncSession):
        self.session = session
        self.recipe_repo = RecipeRepository(session)

    async def get_recipe_with_ingredients(self, recipe_id: UUID) -> Optional[Dict[str, Any]]:
        """Get recipe by ID with ingredients"""
        try:
            return await self.recipe_repo.get_recipe_with_ingredients(recipe_id)
        except Exception as e:
            logger.error(f"Error getting recipe {recipe_id}: {e}")
            return None

    async def search_recipes(
        self,
        tenant_id: UUID,
        search_term: Optional[str] = None,
        status: Optional[str] = None,
        category: Optional[str] = None,
        is_seasonal: Optional[bool] = None,
        is_signature: Optional[bool] = None,
        difficulty_level: Optional[int] = None,
        limit: int = 100,
        offset: int = 0
    ) -> List[Dict[str, Any]]:
        """Search recipes with filters"""
        try:
            return await self.recipe_repo.search_recipes(
                tenant_id=tenant_id,
                search_term=search_term,
                status=status,
                category=category,
                is_seasonal=is_seasonal,
                is_signature=is_signature,
                difficulty_level=difficulty_level,
                limit=limit,
                offset=offset
            )
        except Exception as e:
            logger.error(f"Error searching recipes: {e}")
            return []

    async def get_recipe_statistics(self, tenant_id: UUID) -> Dict[str, Any]:
        """Get recipe statistics for dashboard"""
        try:
            return await self.recipe_repo.get_recipe_statistics(tenant_id)
        except Exception as e:
            logger.error(f"Error getting recipe statistics: {e}")
            return {"total_recipes": 0, "active_recipes": 0, "signature_recipes": 0, "seasonal_recipes": 0}

    async def create_recipe(
        self,
        recipe_data: Dict[str, Any],
        ingredients_data: List[Dict[str, Any]],
        created_by: UUID
    ) -> Dict[str, Any]:
        """Create a new recipe with ingredients"""
        try:
            # Add metadata
            recipe_data["created_by"] = created_by
            recipe_data["created_at"] = datetime.utcnow()
            recipe_data["updated_at"] = datetime.utcnow()

            # Use the shared repository's create method
            recipe_create = RecipeCreate(**recipe_data)
            recipe = await self.recipe_repo.create(recipe_create)

            # Get the created recipe with ingredients (if the repository supports it)
            result = await self.recipe_repo.get_recipe_with_ingredients(recipe.id)

            return {
                "success": True,
                "data": result
            }

        except Exception as e:
            logger.error(f"Error creating recipe: {e}")
            await self.session.rollback()
            return {
                "success": False,
                "error": str(e)
            }

    async def update_recipe(
        self,
        recipe_id: UUID,
        recipe_data: Dict[str, Any],
        ingredients_data: Optional[List[Dict[str, Any]]] = None,
        updated_by: UUID = None
    ) -> Dict[str, Any]:
        """Update an existing recipe"""
        try:
            # Check if recipe exists
            existing_recipe = await self.recipe_repo.get_by_id(recipe_id)
            if not existing_recipe:
                return {
                    "success": False,
                    "error": "Recipe not found"
                }

            # Add metadata
            if updated_by:
                recipe_data["updated_by"] = updated_by
            recipe_data["updated_at"] = datetime.utcnow()

            # Use the shared repository's update method
            recipe_update = RecipeUpdate(**recipe_data)
            updated_recipe = await self.recipe_repo.update(recipe_id, recipe_update)

            # Get the updated recipe with ingredients
            result = await self.recipe_repo.get_recipe_with_ingredients(recipe_id)

            return {
                "success": True,
                "data": result
            }

        except Exception as e:
            logger.error(f"Error updating recipe {recipe_id}: {e}")
            await self.session.rollback()
            return {
                "success": False,
                "error": str(e)
            }

    async def delete_recipe(self, recipe_id: UUID) -> bool:
        """Delete a recipe"""
        try:
            return await self.recipe_repo.delete(recipe_id)
        except Exception as e:
            logger.error(f"Error deleting recipe {recipe_id}: {e}")
            return False

    async def check_recipe_feasibility(self, recipe_id: UUID, batch_multiplier: float = 1.0) -> Dict[str, Any]:
        """Check if recipe can be produced with current inventory"""
        try:
            recipe = await self.recipe_repo.get_recipe_with_ingredients(recipe_id)
            if not recipe:
                return {
                    "success": False,
                    "error": "Recipe not found"
                }

            # Simplified feasibility check - can be enhanced later with inventory service integration
            return {
                "success": True,
                "data": {
                    "recipe_id": str(recipe_id),
                    "recipe_name": recipe["name"],
                    "batch_multiplier": batch_multiplier,
                    "feasible": True,
                    "missing_ingredients": [],
                    "insufficient_ingredients": []
                }
            }

        except Exception as e:
            logger.error(f"Error checking recipe feasibility {recipe_id}: {e}")
            return {
                "success": False,
                "error": str(e)
            }

    async def duplicate_recipe(
        self,
        recipe_id: UUID,
        new_name: str,
        created_by: UUID
    ) -> Dict[str, Any]:
        """Create a duplicate of an existing recipe"""
        try:
            # Get original recipe
            original_recipe = await self.recipe_repo.get_recipe_with_ingredients(recipe_id)
            if not original_recipe:
                return {
                    "success": False,
                    "error": "Recipe not found"
                }

            # Create new recipe data
            new_recipe_data = original_recipe.copy()
            new_recipe_data["name"] = new_name

            # Remove fields that should be auto-generated
            new_recipe_data.pop("id", None)
            new_recipe_data.pop("created_at", None)
            new_recipe_data.pop("updated_at", None)

            # Handle ingredients
            ingredients = new_recipe_data.pop("ingredients", [])

            # Create the duplicate
            result = await self.create_recipe(new_recipe_data, ingredients, created_by)

            return result

        except Exception as e:
            logger.error(f"Error duplicating recipe {recipe_id}: {e}")
            await self.session.rollback()
            return {
                "success": False,
                "error": str(e)
            }

    async def activate_recipe(self, recipe_id: UUID, activated_by: UUID) -> Dict[str, Any]:
        """Activate a recipe for production"""
        try:
            # Check if recipe exists
            recipe = await self.recipe_repo.get_recipe_with_ingredients(recipe_id)
            if not recipe:
                return {
                    "success": False,
                    "error": "Recipe not found"
                }

            if not recipe.get("ingredients"):
                return {
                    "success": False,
                    "error": "Recipe must have at least one ingredient"
                }

            # Update recipe status
            update_data = {
                "status": "active",
                "updated_by": activated_by,
                "updated_at": datetime.utcnow()
            }

            recipe_update = RecipeUpdate(**update_data)
            await self.recipe_repo.update(recipe_id, recipe_update)

            # Get the updated recipe
            result = await self.recipe_repo.get_recipe_with_ingredients(recipe_id)

            return {
                "success": True,
                "data": result
            }

        except Exception as e:
            logger.error(f"Error activating recipe {recipe_id}: {e}")
            return {
                "success": False,
                "error": str(e)
            }