<?php

namespace App\Http\Controllers\Api\App\Recipe;

use Arr;
use Illuminate\Http\Request;
use App\Services\DietPlanService;
use App\Http\Controllers\Controller;
use App\Models\{Meal, Product, User};
use App\Http\Requests\Api\Dashboard\Admin\Recipe\RecipeRequest;
use App\Http\Resources\Api\Dashboard\Admin\Product\{ProductResource, SimpleProductResource};

class RecipeController extends Controller
{
    /**
     * DietPlanService instance.
     *
     * @var DietPlanService
     */
    private $dietPlanService;

    public function __construct(DietPlanService $dietPlanService)
    {
        $this->dietPlanService = $dietPlanService;
    }
    
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $products = Product::where(['type' => 'recipe'])->where(function ($q){
            $q->where('status', 'approved')->orWhere('user_id', auth('api')->id());
        })->when($request->keyword, function ($q) use ($request) {
            $q->whereTranslationLike('title', '%' . $request->keyword . '%')
                ->orWhereTranslationLike('serving_desc', '%' . $request->keyword . '%')
                ->orWhereTranslationLike('desc', '%' . $request->keyword . '%');
        })->latest()->paginate($request->per_page ?? 25);
        return SimpleProductResource::collection($products)->additional(['status' => 'success', 'message' => '']);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function store(RecipeRequest $request)
    {
        $data = $request->validated() + ['added_by' => 'client', 'user_id' => auth('api')->id(), 'type' => 'recipe', 'status' => 'pending'];

        // Extract related data and remove from main data array
        $relations = [
            'ingredients' => 'productIngredients',
            'carbs'      => 'productCarbs',
            'fats'       => 'productFats',
            'others'     => 'productOthers',
            'micros'     => 'productMicros',
            'directions' => 'productDirections',
        ];

        $mainData = Arr::except($data, array_keys($relations));
        $product = Product::create($mainData);

        foreach ($relations as $key => $relation) {
            if ($request->filled($key)) {
                $method = $relation;
                $value = $request->input($key);
                // Use createMany for arrays, create for single objects
                if (is_array($value) && Arr::isList($value)) {
                    $product->$method()->createMany($value);
                } else {
                    $product->$method()->create($value);
                }
            }
        }
        if($request->meal_id && $request->number_of_servings && $request->date && $request->yields){
            $number_of_servings = $request->yields;
            if($request->serving_size != 'gram') {
                $number_of_servings = $request->yields * $product->calories_per;
            }
            $meal = Meal::where('user_id', auth('api')->id())->findOrFail($request->meal_id);
            $diet_plan = $this->dietPlanService->createDietPlan($product, auth('api')->id(), $number_of_servings, $meal, $request->date, $request->serving_size, $request->yields);
        }
        return ProductResource::make($product)->additional(['status' => 'success', 'message' => trans('Created successfully')]);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $product = Product::where('type', 'recipe')->findOrFail($id);
        return ProductResource::make($product)->additional(['status' => 'success', 'message' => '']);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(RecipeRequest $request, $id)
    {
        $product = Product::where(['type' => 'recipe', 'user_id' => auth('api')->id()])->where('status', '!=', 'approved')->findOrFail($id);
        $product->update(Arr::except($request->validated(), ['ingredients', 'carbs', 'fats', 'others', 'micros']));
        // Update or create related data
        $relations = [
            'ingredients' => 'productIngredients',
            'carbs'      => 'productCarbs',
            'fats'       => 'productFats',
            'others'     => 'productOthers',
            'micros'     => 'productMicros',
        ];

        foreach ($relations as $key => $relation) {
            if ($request->filled($key)) {
                $method = $relation;
                $value = $request->input($key);

                // Delete old related records
                $product->$method()->delete();

                // Re-create related records
                if (is_array($value) && Arr::isList($value)) {
                    $product->$method()->createMany($value);
                } else {
                    $product->$method()->create($value);
                }
            }
        }

        if($request->meal_id && $request->number_of_servings && $request->date && $request->yields){
            $number_of_servings = $request->yields;
            if($request->serving_size != 'gram') {
                $number_of_servings = $request->yields * $product->calories_per;
            }
            $meal = Meal::where('user_id', auth('api')->id())->findOrFail($request->meal_id);
            $diet_plan = $this->dietPlanService->createDietPlan($product, auth('api')->id(), $number_of_servings, $meal, $request->date, $request->serving_size, $request->yields);
        }

        return ProductResource::make($product)->additional(['status' => 'success', 'message' => trans('Updated successfully')]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $product = Product::where(['type' => 'recipe', 'user_id' => auth('api')->id()])->where('status', '!=', 'approved')->findOrFail($id);
        if ($product->delete()) {
            return response()->json(['status' => 'success', 'data' => null, 'message' => trans('Deleted successfully')]);
        }
        return response()->json(['status' => 'fail', 'data' => null, 'message' => trans('Something went wrong, please try again')], 422);
    }

    public function toggleSave($id)
    {
        $user = User::find(auth('api')->id());
        $user->savedRecipes()->where('recipe_id', $id)->exists() ? $user->savedRecipes()->detach($id) : $user->savedRecipes()->attach($id);
        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('Updated successfully')]);
    }

    public function savedRecipes()
    {
        $user = User::find(auth('api')->id());
        $recipes = $user->savedRecipes()->where('status', 'approved')->latest()->paginate(25);
        return SimpleProductResource::collection($recipes)->additional(['status' => 'success', 'message' => '']);
    }

    public function toggleLike($id)
    {
        $user = User::find(auth('api')->id());
        $user->likedRecipes()->where('recipe_id', $id)->exists() ? $user->likedRecipes()->detach($id) : $user->likedRecipes()->attach($id);
        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('Updated successfully')]);
    }

    public function toggleShare($id)
    {
        $user = User::find(auth('api')->id());
        $user->sharedRecipes()->where('recipe_id', $id)->exists() ? $user->sharedRecipes()->detach($id) : $user->sharedRecipes()->attach($id);
        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('Updated successfully')]);
    }
}
