<?php

namespace App\Http\Controllers;

use App\Models\Restaurante;
use App\Models\Producto;
use App\Models\Ingrediente;
use App\Models\Receta;
use App\Services\PaginatorService;
use App\Services\UuidService;
use App\Exceptions\GenericException;
use App\Exceptions\AlreadyExistsException;
use App\Exceptions\ModelNotFoundException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Ramsey\Uuid\Uuid;

class RecetasController extends Controller {

    /**
     * Obtiene los ingredientes de la receta de un producto
     */
    public function all(Request $request, $restaurante_id, $producto_id) {
        app(UuidService::class)->validOrFail($restaurante_id);
        app(UuidService::class)->validOrFail($producto_id);

        $restaurante = Restaurante::findOrFail($restaurante_id);
        $producto = Producto::findOrFail($producto_id);

        if($producto->restaurante != $restaurante) {
            throw new ModelNotFoundException("producto", $producto_id);
        }

        $recetas = Receta::where('producto_id', $producto->id)->with('ingrediente');

        $paginate = app(PaginatorService::class)->paginate(
            perPage: $request->input('per_page', 15),
            page: $request->input('page', 1),
            total: $recetas->count(),
            route: 'productos.receta.all',
            data: ['restaurante_id' => $restaurante_id, 'producto_id' => $producto_id]
        );

        $data = $recetas->get()
                        ->skip($paginate['from'] - 1)
                        ->take($paginate['per_page'])
                        ->all();

        return response()->json([
            'pagination' => $paginate,
            'data' => $data
        ]);
    }

    /**
     * Obtiene los datos de un ingrediente de una receta
     */
    public function get(Request $request, $restaurante_id, $producto_id, $ingrediente_id) {
        app(UuidService::class)->validOrFail($restaurante_id);
        app(UuidService::class)->validOrFail($ingrediente_id);
        app(UuidService::class)->validOrFail($producto_id);

        $restaurante = Restaurante::findOrFail($restaurante_id);
        $ingrediente = Ingrediente::findOrFail($ingrediente_id);
        $producto = Producto::findOrFail($producto_id);

        if($ingrediente->restaurante != $restaurante) {
            throw new ModelNotFoundException("ingrediente", $ingrediente_id);
        }

        if($producto->restaurante != $restaurante) {
            throw new ModelNotFoundException("producto", $producto_id);
        }

        $receta = Receta::where('producto_id', $producto->id)
                        ->where('ingrediente_id', $ingrediente->id)
                        ->with('ingrediente')
                        ->first();
        if(!$receta) {
            throw new ModelNotFoundException("receta", [$ingrediente_id, $producto_id]);
        }

        return response()->json($receta);
    }

    /**
     * Agrega un ingrediente a la receta del producto
     */
    public function create(Request $request, $restaurante_id, $producto_id, $ingrediente_id) {
        $this->validate($request, [
            'unidades' => 'required|numeric'
        ]);

        app(UuidService::class)->validOrFail($restaurante_id);
        app(UuidService::class)->validOrFail($ingrediente_id);
        app(UuidService::class)->validOrFail($producto_id);

        $restaurante = Restaurante::findOrFail($restaurante_id);
        $ingrediente = Ingrediente::findOrFail($ingrediente_id);
        $producto = Producto::findOrFail($producto_id);

        if($ingrediente->restaurante != $restaurante) {
            throw new ModelNotFoundException("ingrediente", $ingrediente_id);
        }

        if($producto->restaurante != $restaurante) {
            throw new ModelNotFoundException("producto", $producto_id);
        }

        $receta = Receta::where('producto_id', $producto->id)
                        ->where('ingrediente_id', $ingrediente->id)
                        ->first();

        if($receta) throw new AlreadyExistsException("receta");

        $receta = Receta::create([
            'id' => Uuid::uuid4(),
            'unidades' => $request->input('unidades'),
            'producto_id' => $producto->id,
            'ingrediente_id' => $ingrediente->id,
        ]);

        return response()->json($receta);
    }

    /**
     * Modifica el ingrediente de una receta
     */
    public function update(Request $request, $restaurante_id, $producto_id, $ingrediente_id) {
        $this->validate($request, [
            'unidades' => 'required|numeric'
        ]);

        app(UuidService::class)->validOrFail($restaurante_id);
        app(UuidService::class)->validOrFail($ingrediente_id);
        app(UuidService::class)->validOrFail($producto_id);

        $restaurante = Restaurante::findOrFail($restaurante_id);
        $ingrediente = Ingrediente::findOrFail($ingrediente_id);
        $producto = Producto::findOrFail($producto_id);

        if($ingrediente->restaurante != $restaurante) {
            throw new ModelNotFoundException("ingrediente", $ingrediente_id);
        }

        if($producto->restaurante != $restaurante) {
            throw new ModelNotFoundException("producto", $producto_id);
        }

        $receta = Receta::where('producto_id', $producto->id)
                        ->where('ingrediente_id', $ingrediente->id)
                        ->first();

        $receta->unidades = $request->input('unidades');
        $receta->save();

        return response()->json($receta);
    }

    /**
     * Elimina un ingrediente de la receta del producto
     */
    public function delete(Request $request, $restaurante_id, $producto_id, $ingrediente_id) {
        app(UuidService::class)->validOrFail($restaurante_id);
        app(UuidService::class)->validOrFail($producto_id);
        app(UuidService::class)->validOrFail($ingrediente_id);

        $restaurante = Restaurante::findOrFail($restaurante_id);
        $producto = Producto::findOrFail($producto_id);
        $ingrediente = Ingrediente::findOrFail($ingrediente_id);

        if($producto->restaurante != $restaurante) {
            throw new ModelNotFoundException("producto", $producto_id);
        }

        if($ingrediente->restaurante != $restaurante) {
            throw new ModelNotFoundException("ingrediente", $ingrediente_id);
        }

        $receta = Receta::where('producto_id', $producto->id)
                        ->where('ingrediente_id', $ingrediente->id)
                        ->first();
        
        $receta->delete();
        return response()->json([], 204);
    }
}
