<?php

namespace App\Http\Controllers\api\v1;

use Exception;
use Illuminate\Support\Str;
use App\Models\api\v1\Order;
use Illuminate\Http\Request;
use App\Models\api\v1\LineItem;
use App\Enums\OrderStatusesEnum;
use Illuminate\Http\JsonResponse;
use App\Models\api\v1\OrderStatus;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Models\api\v1\Stock;
use Illuminate\Support\Facades\Validator;

class OrderController extends Controller
{

    public function userOrders()
    {
        return $this->ReturnResponse(
            true, 
            "User Order list", 
            Order::where([['created_by',request()->user()->id], ['is_deleted', 0], ['is_active', 1]])
                ->with('lineItems.stock.item')->get()->toArray()
        );
    }


    /**
     * Cette fonction permet d'avoir la liste des status des commandes
     * Vous pouvez avoir les status suivant l'état que vous voulez voir
     * 
     * @return mixed
     */
    public function getstatuses(Request $request)
    {
        $statuses           = OrderStatus::orderBy('step_number')->get()->toArray();
        $step = $request->get('after_step');
        if(isset($step))
        {
            
            $statuses = OrderStatus::where('step_number', intval($step) +1)->orderBy('step_number')->get()->toArray() ;
            
        }
        return $this->ReturnResponse(true, "Liste des status de commandes", $statuses);
    }

    /**
     * Cette fonction permet de mettre a jour le status d'une commande
     * 
     * @return mixed
     */
    public function changeStatus(Request $request, string $order_uuid, string $status): JsonResponse
    {
        $order = Order::Where([['uuid', $order_uuid], ['is_deleted', 0], ['is_active', 1]])->first();
        if (!$order)
        {
            return $this->ReturnResponse(false, "Order not found", [],404);
        }

        $currentStatus      = OrderStatus::where('id',$order->order_status_id)->first();
        $assignStatus       = OrderStatus::where('name',strtoupper($status))->first();
        if(!$assignStatus)
        {
            return $this->ReturnResponse(false, "Le status de commande inconnu", [],404);
        }

        // @TODO: Add check for status back ASAP
//        if ($assignStatus->step_number == $currentStatus->step_number || $assignStatus->step_number == $currentStatus->step_number + 1)
//        {
            $order->order_status_id = $assignStatus->id;
            $order->updated_at      = now();
            $order->updated_by      = $request->user()->id;
            $order->save();
            return $this->ReturnResponse(
                true,
                "Le statut de la commande est passé de ". $currentStatus->name . " à ". $assignStatus->name,
                [$order]
            );
//        }
        
//        return $this->ReturnResponse(
//            false,
//            "Impossible de mettre à jour le statut de la commande",
//            [],
//            422
//        );
    }


    public function show(Request $request, string $uuid) : JsonResponse
    {
        $order = Order::Where([['uuid', $uuid], ['is_deleted', 0], ['is_active', 1]])
                        ->with('lineItems.stock.item')->first();
        if (!$order)
        {
            return $this->ReturnResponse(false, "Order not found", [],404);
        }

        return $this->ReturnResponse(
            true,
            "Order Details",
            [$order]
        );
    }

    public function show_space(Request $request, string $space_uuid, string $uuid) : JsonResponse
    {
        return $this->show($request, $uuid);
    }

    public function create(Request $request) : JsonResponse
    {

        $validator = Validator::make(
            $request->all(),
            [
                'space_id'                 => 'required|exists:spaces,id',
                'line_items'               => 'required|array',
                'line_items.*.stock_id'    => 'required|exists:stocks,id',
                'line_items.*.quantity'    => 'required|min:1',
                "table_number"             => "string",
            ]
        );

        //si erreur
        if($validator->fails())
        {
            return $this->ReturnResponse(false, $validator->errors(), [], 400);
        }

        $order = Order::where([
            ['created_by',$request->user()->id],
            ['order_status_id', OrderStatus::where('name','CART')->first()->id]
            ])->first(); 
        
        $amount_due = 0;
        if(!$order)
        {    
            $order = Order::create([
                "order_status_id"       => 1,
                "uuid"                  => Str::uuid(),
                "amount_due"            => $amount_due,
                "table_number"          => $request->table_number,
                "remaining_amount"      => $amount_due,
                "created_by"            => $request->user()->id,
                "updated_by"            => $request->user()->id,
                "is_active"             => 1
            ]);
        }


        $stock_id_list   = [];
        $list_line_items = [];
        foreach($request->line_items as $key => $sline)
        {
            $stock_id_list[$request->line_items[$key]["stock_id"]] = $sline["quantity"]; 
        }
        try
        {
            DB::beginTransaction();
            $stocks = Stock::where('space_id', $request->space_id)->whereIn('id',array_keys($stock_id_list))->get();
            if(count($stocks) != count($stock_id_list))
            {
                return $this->ReturnResponse(false, "Certains articles n'appartiennent pas à cet espace", [],404);
            }
            $amount_due = 0;
            
            foreach($stocks as $key => $stock)
            {
                $line = [
                            "stock_id"      => $stock->id,
                            "order_id"      => $order->id,
                            "quantity"      => $stock_id_list[$stock->id] ,
                            "created_by"    => $request->user()->id,
                            "updated_by"    => $request->user()->id,
                        ];
                $amount_due += $stock->price_after_sale *  $stock_id_list[$stock->id];
                $list_line_items[] = $line;
            }

            LineItem::insert($list_line_items); // inserrton par lot de 10 dans la boucle 
            //$order->lineItems()->insert($list_line_items); // inserrton par lot de 10 dans la boucle 
            $order->update([
                "amount_due"        => $amount_due,
                "remaining_amount"  => $amount_due,
            ]);             
            /*"*/
            DB::commit();
            return $this->ReturnResponse(true, "La commande a été enregistrée", [$order->with('lineItems')]);
        
        }
        catch (Exception $e)
        {
            DB::rollBack();
            // Log Error
            $message =  "Impossibme de mettre a jour la commande :  " . $e->getMessage() . " - line: " . $e->getLine();
            //Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }

        

    }

    public function update(Request $request, $uuid) : JsonResponse
    {
        $order = Order::where([
                ['uuid',$uuid],
                ['order_status_id', OrderStatus::where('name','CART')->first()->id]
        ])->first(); 
        if(!$order)
        {
            return $this->ReturnResponse(false, "Order not found", [],404);
        }
        
        $validator = Validator::make(
            $request->all(),
            [
                'table_number'             => 'string',
                'rebate'                   => 'numeric|min:0',
            ]
        );

        //si erreur
        if($validator->fails())
        {
            return $this->ReturnResponse(false, $validator->errors(), [], 400);
        }

        try
        {
            DB::beginTransaction();
            $order->update([
                'table_number'          => $request->table_number
            ]);
            if (!is_null($request->rebate))
            {
                $order->update(
                    [
                        'rebate'                => $request->rebate,
                        'remaining_amount'      => $order->amount_due - intval($request->rebate)
                    ]
                );
            }
            DB::commit();
            return $this->ReturnResponse(true, "Order Updated", []);
        }
        catch (Exception $e)
        {
            DB::rollBack();
            // Log Error
            $message =  "Impossibme de mettre a jour la commande :  " . $e->getMessage() . " - line: " . $e->getLine();
            //Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    
    }

    public function updateSpace(Request $request, string $space_uuid, string $uuid) : JsonResponse
    {
        return $this->update($request, $uuid);
    }


    public function updateOrderLineItem(Request $request, $uuid) : JsonResponse
    {
        $order = Order::where([
            ['uuid',$uuid],
            ['order_status_id', OrderStatus::where('name','CART')->first()->id]
            ])->first(); 
        
        if(!$order)
        {
            return $this->ReturnResponse(false, "Order not found", [],404);
        }

        $validator = Validator::make(
            $request->all(),
            [
                'space_id'                 => 'required|exists:spaces,id',
                'line_items'               => 'required|array',
                'line_items.*.stock_id'    => 'required|exists:stocks,id',
                'line_items.*.quantity'    => 'required|min:1',
            ]
        );
        //si erreur
        if($validator->fails())
        {
            return $this->ReturnResponse(false, $validator->errors(), [], 400);
        }
        
        
        $stock_id_list   = [];
        $list_line_items = [];

        foreach($request->line_items as $key => $sline)
        {
            $stock_id_list[$request->line_items[$key]["stock_id"]] = $sline["quantity"]; // si deux element identique faire la somme
        }

        try
        {
            DB::beginTransaction();

            $stocks = Stock::where('space_id', $request->space_id)->whereIn('id',array_keys($stock_id_list))->get();

            if(count($stocks) != count($stock_id_list))
            {
                return $this->ReturnResponse(false, "Certains articles n'appartiennent pas à cet espace", [],404);
            }

            $order->lineItems()->delete();

            $amount_due = 0;

            
            foreach($stocks as $key => $stock)
            {
                $line = [
                            "stock_id"      => $stock->id,
                            "order_id"      => $order->id,
                            "quantity"      => $stock_id_list[$stock->id] ,
                            "created_by"    => $request->user()->id,
                            "updated_by"    => $request->user()->id,
                        ];

                $amount_due += $stock->price_after_sale * $stock_id_list[$stock->id];
                $list_line_items[] = $line;
            }

            LineItem::insert($list_line_items);

            $order->update([
                "amount_due"        => $amount_due,
                "remaining_amount"  => $amount_due - $order->rebate,
            ]);

            DB::commit();
            return $this->ReturnResponse(true, "La commande a été mise à jour", [$order->with('lineItems')]);
        }
        catch (Exception $e)
        {
            DB::rollBack();
            // Log Error
            $message =  "Impossibme de mettre a jour la commande :  " . $e->getMessage() . " - line: " . $e->getLine();
            //Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    }


    public function updateOrderLineItemSpace(Request $request,  string $space_uuid, string $uuid) : JsonResponse
    {
        return $this->updateOrderLineItem($request, $uuid);
    }



    public function pay(Request $request, string $uuid) : JsonResponse
    {
        $data = [
            "id"=> 1,
            "uuid"=> Str::uuid(),
            "amount_paid"=> 500,
        ];
        return $this->ReturnResponse(true, "Order Payed Successfully", $data);
    }

    public function deleteOrder(Request $request, string $uuid) : JsonResponse
    {
        return $this->ReturnResponse(true, "Order Deleted Successfully");
    }
}
