<?php

namespace App\Services;

use App\Repositories\Eloquent\RecipeRepository;
use App\Repositories\Eloquent\ScoopYieldRepository;

class RecipeService
{
    public function __construct(
        protected RecipeRepository $recipeRepository,
        protected ScoopYieldRepository $scoopYieldRepository,
        protected LoggingService $loggingService
    ) {}

    public function getAll()
    {
        $this->loggingService->logInfo('Fetching all recipes');
        return $this->recipeRepository->all();
    }

    public function getActive()
    {
        $this->loggingService->logInfo('Fetching active recipes');
        return $this->recipeRepository->getActive();
    }

    public function getForProduct(int $productId)
    {
        $this->loggingService->logInfo('Fetching recipes for product', ['product_id' => $productId]);
        return $this->recipeRepository->getForProduct($productId);
    }

    public function find(int $id)
    {
        $this->loggingService->logInfo('Finding recipe', ['id' => $id]);
        return $this->recipeRepository->find($id);
    }

    public function findWithIngredients(int $id)
    {
        $this->loggingService->logInfo('Finding recipe with ingredients', ['id' => $id]);
        return $this->recipeRepository->getWithIngredients($id);
    }

    public function create(array $data)
    {
        $this->loggingService->logInfo('Creating recipe', ['data' => $data]);

        $ingredients = $data['ingredients'] ?? [];
        unset($data['ingredients']);

        $recipe = $this->recipeRepository->create($data);

        if (!empty($ingredients)) {
            $this->recipeRepository->syncIngredients($recipe->id, $ingredients);
        }

        return $recipe->fresh(['product', 'ingredients', 'recipeIngredients.ingredient']);
    }

    public function update(int $id, array $data)
    {
        $this->loggingService->logInfo('Updating recipe', ['id' => $id, 'data' => $data]);

        $ingredients = $data['ingredients'] ?? null;
        unset($data['ingredients']);

        $recipe = $this->recipeRepository->update($id, $data);

        if ($ingredients !== null) {
            $this->recipeRepository->syncIngredients($id, $ingredients);
        }

        return $recipe->fresh(['product', 'ingredients', 'recipeIngredients.ingredient']);
    }

    public function delete(int $id)
    {
        $this->loggingService->logInfo('Deleting recipe', ['id' => $id]);
        return $this->recipeRepository->delete($id);
    }

    // -------------------------------------------------------------------------
    // Production Items (gram-based deductions from production batches)
    // -------------------------------------------------------------------------

    /**
     * Replace all production items for a recipe.
     *
     * Each item:
     *   source_product_id  – product whose active batch to deduct from
     *   grams              – grams to deduct
     *   option_set_item_id – NULL = default/Regular; ID = size-specific
     *   notes              – optional
     */
    public function syncProductionItems(int $recipeId, array $productionItems)
    {
        $this->loggingService->logInfo('Syncing production items for recipe', [
            'recipe_id' => $recipeId,
            'count'     => count($productionItems),
        ]);

        $this->recipeRepository->syncProductionItems($recipeId, $productionItems);

        return $this->recipeRepository->getWithIngredients($recipeId);
    }

    /**
     * Add a single production item to a recipe.
     */
    public function addProductionItem(int $recipeId, array $data)
    {
        $this->loggingService->logInfo('Adding production item to recipe', [
            'recipe_id' => $recipeId,
            'data'      => $data,
        ]);

        $recipe = $this->recipeRepository->find($recipeId);
        if (!$recipe) {
            return null;
        }

        $item = $recipe->productionItems()->create([
            'source_product_id'  => $data['source_product_id'],
            'grams'              => $data['grams'],
            'option_set_item_id' => $data['option_set_item_id'] ?? null,
            'notes'              => $data['notes'] ?? null,
        ]);

        return $item->fresh(['sourceProduct', 'sizeOption']);
    }

    /**
     * Update a production item.
     */
    public function updateProductionItem(int $itemId, array $data)
    {
        $item = \App\Models\RecipeProductionItem::find($itemId);
        if (!$item) {
            return null;
        }

        $item->update(array_filter($data, fn ($v) => $v !== null));

        return $item->fresh(['sourceProduct', 'sizeOption']);
    }

    /**
     * Delete a production item.
     */
    public function deleteProductionItem(int $itemId): bool
    {
        $item = \App\Models\RecipeProductionItem::find($itemId);
        if (!$item) {
            return false;
        }

        return $item->delete();
    }

    /**
     * Get all production items for a recipe.
     */
    public function getProductionItems(int $recipeId)
    {
        $recipe = $this->recipeRepository->find($recipeId);
        if (!$recipe) {
            return collect();
        }

        return $recipe->productionItems()->with(['sourceProduct', 'sizeOption'])->get();
    }

    public function calculateCost(int $id): array
    {
        $this->loggingService->logInfo('Calculating recipe cost', ['id' => $id]);

        $recipe = $this->recipeRepository->getWithIngredients($id);

        if (!$recipe) {
            return ['error' => 'Recipe not found'];
        }

        $totalCost = 0;
        $breakdown = [];

        foreach ($recipe->recipeIngredients as $recipeIngredient) {
            $ingredientCost = $recipeIngredient->getCost();
            $totalCost += $ingredientCost;
            $breakdown[] = [
                'ingredient' => $recipeIngredient->ingredient->name,
                'quantity' => $recipeIngredient->quantity,
                'unit' => $recipeIngredient->getEffectiveUnit(),
                'cost_per_unit' => $recipeIngredient->ingredient->cost_per_unit,
                'total_cost' => $ingredientCost,
            ];
        }

        return [
            'recipe_id' => $recipe->id,
            'recipe_name' => $recipe->name,
            'yield_grams'   => $recipe->yield_grams,
            'total_cost'    => $totalCost,
            'cost_per_gram' => $recipe->yield_grams > 0 ? $totalCost / $recipe->yield_grams : 0,
            'breakdown' => $breakdown,
        ];
    }

    // Scoop Yield Methods
    public function getScoopYields()
    {
        $this->loggingService->logInfo('Fetching all scoop yields');
        return $this->scoopYieldRepository->getActive();
    }

    public function getScoopYieldsForIngredient(int $ingredientId)
    {
        $this->loggingService->logInfo('Fetching scoop yields for ingredient', ['ingredient_id' => $ingredientId]);
        return $this->scoopYieldRepository->getForIngredient($ingredientId);
    }

    public function createScoopYield(array $data)
    {
        $this->loggingService->logInfo('Creating scoop yield', ['data' => $data]);
        return $this->scoopYieldRepository->create($data);
    }

    public function updateScoopYield(int $id, array $data)
    {
        $this->loggingService->logInfo('Updating scoop yield', ['id' => $id, 'data' => $data]);
        return $this->scoopYieldRepository->update($id, $data);
    }

    public function deleteScoopYield(int $id)
    {
        $this->loggingService->logInfo('Deleting scoop yield', ['id' => $id]);
        return $this->scoopYieldRepository->delete($id);
    }

    public function calculateScoopUsage(int $ingredientId, ?int $optionSetItemId, int $scoopCount): ?array
    {
        $this->loggingService->logInfo('Calculating scoop usage', [
            'ingredient_id' => $ingredientId,
            'option_set_item_id' => $optionSetItemId,
            'scoop_count' => $scoopCount
        ]);

        $scoopYield = $this->scoopYieldRepository->findByIngredientAndSize($ingredientId, $optionSetItemId);

        if (!$scoopYield) {
            return null;
        }

        return [
            'ingredient_id' => $ingredientId,
            'scoop_count' => $scoopCount,
            'yield_per_scoop' => $scoopYield->yield_per_scoop,
            'total_usage' => $scoopYield->calculateUsage($scoopCount),
            'unit' => $scoopYield->unit,
        ];
    }
}
