<?php

namespace App\Http\Controllers\api\v1;

use Log;
use Auth;
use Session;
use Exception;
use Carbon\Carbon;
use App\Models\User;
use GuzzleHttp\Client;
use App\Constant\OTPStatus;
use App\Models\api\v1\Item;
use App\Models\api\v1\Role;
use Illuminate\Support\Str;
use App\Models\api\v1\Space;
use App\Models\api\v1\Stock;
use App\Services\OtpService;
use Illuminate\Http\Request;
use App\Models\api\v1\ApiKey;
use App\Models\api\v1\Country;
use App\Models\api\v1\MfaCode;
use App\Models\api\v1\UserRole;
use App\Services\ApiKeyService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Models\api\v1\Order;
use App\Models\api\v1\OrderStatus;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use App\Models\api\v1\UsersRolesSpace;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Validator;
use GuzzleHttp\Psr7\Request as Psr7Request;
use App\Models\api\v1\QrCode;


class SpaceController extends Controller
{
    /**
     * Detail espace
     */
    public function show(Request $request, $space_uuid): JsonResponse
    {
        try {
            //si validé alors connexion
            $current_space = Space::Active()->where('uuid', $space_uuid)->with('country')->first();

            if ($current_space) {
                return $this->ReturnResponse(true, "Space Details", [$current_space], 200);
            }
            return $this->ReturnResponse(true, "Space not found", [], 200);
        } catch (Exception $e) {
            $message = "Space - details - " . $e->getMessage() . " - line: " . $e->getLine() . " - file: " . $e->getFile();
            //Logging de l erreur
            Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    }

    public function createStock(Request $request, string $space_uuid)
    {
        $current_space = Space::Active()->where('uuid', $space_uuid)->with('country')->first();

        if (!$current_space) {
            return $this->ReturnResponse(false, "Space not found", [], 404);
        }
        $validator = Validator::make(
            $request->all(),
            [
                'item_id'               => 'required|exists:items,id',
                //'space_id'              => 'required|exists:spaces,id',
                'price'                 => 'required|numeric|min:0',
                'off_by_percentage'     => 'numeric|min:0|max:100',
                'off_by_number'         => 'numeric|min:0',
                "quantity"              => "required|numeric|min:0",
            ]
        );

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

        try {
            //si validé alors connexion
            $stock = null;
            $check = Stock::where([['item_id', $request->item_id], ['space_id', $current_space->id], ['is_deleted', 0]])->first();


            if (!$check) {
                $stock = Stock::create([
                    'item_id'               => $request->item_id,
                    'space_id'              => $current_space->id,
                    'price'                 => $request->price,
                    'off_by_percentage'     => $request->off_by_percentage,
                    'off_by_number'         => $request->off_by_number,
                    "quantity"              => $request->quantity ?? 0,
                    "created_by"            => auth()->user()->id,
                    "is_active"             => 1,
                ]);
                return $this->ReturnResponse(true, "Stock créé avec succès", [$stock], 200);
            } else {
                $check->update([
                    'item_id'               => $request->item_id,
                    'space_id'              => $current_space->id,
                    'price'                 => $request->price,
                    'off_by_percentage'     => $request->off_by_percentage,
                    'off_by_number'         => $request->off_by_number,
                    "quantity"              => $request->quantity ?? 0,
                    "created_by"            => auth()->user()->id,
                    "is_active"             => 1,
                ]);
                $stock = Stock::where([['item_id', $request->item_id], ['space_id', $current_space->id], ['is_deleted', 0]])->first();
                return $this->ReturnResponse(true, "Le produit a été mise à jour dans cette espace", [$stock], 200);
            }

            //retour formaté depuis commonController

        } catch (Exception $e) {
            $message = "Stock - details - " . $e->getMessage() . " - line: " . $e->getLine() . " - file: " . $e->getFile();
            //Logging de l erreur
            Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    }



    public function showStock(Request $request, $space_uuid)
    {
        $space = Space::where('uuid', $space_uuid)->first();

        if (!$space) {
            return $this->ReturnResponse(false, "Space not found", [], 404);
        }

        $stocks = Stock::where([['space_id', $space->id], ['is_deleted', 0]])->with('item')->get();

        $order = new OrderController();
        $basket = $order->getBasketByUser($request);

        return $this->ReturnResponse(true, "Space's stocks", ["space" => $space, "stocks" => $stocks, "basket" => $basket], 200);
    }


    public function assignUserToSpace(Request $request, string $space_uuid): JsonResponse
    {
        $space = Space::Where([['uuid', $space_uuid], ['is_deleted', 0], ['is_active', 1]])
            ->first();
        if (!$space) {
            return $this->ReturnResponse(false, "Space not found", [], 404);
        }


        $validator = Validator::make(
            $request->all(),
            [
                'user_id' => 'required|exists:users,id',
                'role_id' => 'required|exists:roles,id'
            ]
        );
        // If errors
        if ($validator->fails()) {
            return  response(['success' => false, 'message' => $validator->errors(), 'data' => []], 400);
        }

        $role = Role::where([['id', $request->role_id], ['is_assignable', 1], ['is_deleted', 0], ['is_active', 1]])->first();
        if (!$role) {
            return $this->ReturnResponse(false, "Role is not assignable to a space", [], 404);
        }

        $user_role =  UserRole::where([['user_id', $request->user_id], ['role_id', $role->id], ['is_deleted', 0], ['is_active', 1]])
            ->orderBy('created_at', 'DESC')
            ->first();

        if (!$user_role) {
            return $this->ReturnResponse(false, "The user does not have this role", [], 401);
        }

        $user_role_space = UsersRolesSpace::where(
            [
                ['user_role_id',    $user_role->id],
                ['space_id',        $space->id],
                ['is_deleted',      0],
                ['is_active',       1]
            ]
        )->first();


        if ($user_role_space) {
            return $this->ReturnResponse(false, "The user is already assigned to this space with this role.", [], 401);
        }

        UsersRolesSpace::create([
            'user_role_id'  => $user_role->id,
            'space_id'      => $space->id
        ]);


        return $this->ReturnResponse(true, "L'utilisateur a été assigné a l'espace", [], 200);
    }


    public function getListWaiters(Request $request, string $space_uuid): JsonResponse
    {
        $space = Space::Where([['uuid', $space_uuid], ['is_deleted', 0], ['is_active', 1]])
            ->first();
        if (!$space) {
            return $this->ReturnResponse(false, "Space not found", [], 404);
        }


        $validator = Validator::make(
            $request->all(),
            [
                'user_id' => 'required|exists:users,id',
                'role_id' => 'required|exists:roles,id'
            ]
        );

        $user_role_space = UsersRolesSpace::Where([['space_id', $space->id], ['is_deleted', 0], ['is_active', 1]])->get()->pluck('user_role_id');

        $user_role = UserRole::whereIn('id', $user_role_space)->Where('is_deleted', 0)->get()->pluck('user_id');

        $user = User::whereIn('id', $user_role)->Where('is_deleted', 0)->get();

        return $this->ReturnResponse(true, "Liste des serveurs de l'espace", $user->toArray(), 200);
    }

    /**
     * Cette methode permet d'ajouter un serveur a un espace
     * @param string $space_uuid
     * @return JsonResponse
     */
    public function createWaiter(Request $request, string $space_uuid): JsonResponse
    {
        $space = Space::Where([['uuid', $space_uuid], ['is_deleted', 0], ['is_active', 1]])
            ->first();
        if (!$space) {
            return $this->ReturnResponse(false, "Space not found", [], 404);
        }

        $validator = Validator::make(
            $request->all(),
            [
                'username'      => 'required',
                'firstname'     => 'required',
                'lastname'      => 'required',
                'phone_code'    => 'required',
                'email'         => 'email',
                'gender_id'     => 'exists:genders,id',
            ]
        );

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

        try {
            $message = "Votre compte a été assigné à l'espace " . $space->name . " en tant que serveur";

            DB::beginTransaction();

            // @TODO: Ensure user is not deleted.
            $user = User::where([
                ['username', trim($request->phone_code) . trim($request->username)],
                ['is_deleted', 0]
            ])->first();

            if (!$user) {
                $password = Str::random(8);
                $user = User::create([
                    'uuid'              => Str::uuid()->toString(),
                    'lastname'          => $request->lastname,
                    'firstname'         => $request->firstname,
                    'username'          => trim($request->phone_code) . trim($request->username),
                    'phone_code'        => $request->phone_code,
                    'gender_id'         => $request->gender_id,
                    "reset_password"    => 0,
                    'country_id'        => $request->country_id ?? 1,
                    'password'          => Hash::make($password), //bcrypt($request->password)
                    //'created_by'        => 1, // @TODO Update with Session for API Key
                    'created_at'        => date("Y-m-d H:i:s"),
                    'is_active'         => 1
                ]);
                $message = "Bienvenue sur COnnecte toi au foot. Votre compte a été créé et assigné à l'espace " . $space->name . ". Votre mot de passe est : " . $password;
            }

            // @TODO: Ensure user role is not deleted.
            $user_role = UserRole::where([['user_id', $user->id], ['role_id', Role::where('name', 'Serveur')->first()->id]])->first();
            if (!$user_role) {
                $user_role = UserRole::create([
                    'user_id'   => $user->id,
                    'role_id'   => Role::where('name', 'Serveur')->first()->id
                ]);
            }

            // @TODO: Ensure user role space is not deleted.
            $space_user = UsersRolesSpace::where([['user_role_id', $user_role->id], ['space_id', $space->id]])->first();
            if ($space_user) {
                return $this->ReturnResponse(false, "Cette personne existe déjà dans cette espace", [], 406);
            }

            $space_user = UsersRolesSpace::create([
                'user_role_id' => $user_role->id,
                'space_id' => $space->id
            ]);


            if ((new OtpService())->sendSMS(
                $message,
                $user->username,
                env('SMS_CREDENTIAL_FIRST_PARAM'),
                env('SMS_CREDENTIAL_SECOND_PARAM'),
                env('SMS_FROM_FIRST_PARAM'),
                env('SMS_FROM_SECOND_PARAM')
            )) {
                $code       = rand(10000, 99999);

                // Faire un check sur l'envoi du SMS
                MfaCode::create([
                    'recepient'     => $user->username,
                    'code'          => $code,
                    'status'        => OTPStatus::PENDING,
                    'action'        => strtoupper(trim($request->action)),
                    'api_key_id'    => ApiKey::where('key', $request->header('x-api-key'))->first()->id,
                    'expire_at'     => now()->addSeconds(ApiKeyService::getApiKey($request)->otp_max_interval)
                ]);

                Log::info("Message sent to  [" . $request->username . "] - Code:  [" . $code . "]");
            } else {
                Log::alert("Otp not sent [" . $request->username . "]");
            }

            // Commit Changes
            $user = User::where([
                ['username', trim($request->phone_code) . trim($request->username)],
                ['is_deleted', 0]
            ])->first();

            DB::commit();

            // Return Response
            return $this->ReturnResponse(
                true,
                "Waiter created successfully and logged in",
                [$user],
                201
            );
        } catch (Exception $e) {
            DB::rollBack();
            // Log Error
            $message =  "Creation de compte - impossible de creer le compte " . $e->getMessage() . " - line: " . $e->getLine() . " - username:" . $request->username;
            Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    }

    public function getSpaceBySssid(Request $request, $space_ssid): JsonResponse
    {
        //return $this->ReturnResponse(true, "Space Details", [Space::first()]);
        try {
            $space = Space::Where([['ssid', $space_ssid], ['is_deleted', 0], ['is_active', 1]])->first();
            if (!$space) {
                return $this->ReturnResponse(false, "Space not found", [], 404);
            }

            return $this->ReturnResponse(true, "Space Details", [$space]);
        } catch (Exception  $e) {
            // Log Error
            $message =  "getSpaceBySssid => " . $e->getMessage() . " - line: " . $e->getLine();
            //Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    }

    public function getSpaceByQrCode(Request $request, $space_qrcode): JsonResponse
    { //return $this->ReturnResponse(true, "Space Details", [Space::first()]);
        try {
            $space = Space::Where([['num_carte', $space_qrcode], ['is_deleted', 0], ['is_active', 1]])->first();
            if (!$space) {
                return $this->ReturnResponse(false, "Space not found", [], 404);
            }
             if ($space_qrcode == "CM00000000") {
                $stocks = Stock::where([['is_deleted', 0]])->with('item')->get();
            } else {
                $stocks = Stock::where([['space_id', $space->id], ['is_deleted', 0]])->with('item')->get();
            }
            $space["catalogue"] = $stocks;
            return $this->ReturnResponse(true, "Space Details", [$space]);
        } catch (Exception  $e) {
            // Log Error
            $message =  "getSpaceByQrCode => " . $e->getMessage() . " - line: " . $e->getLine();
            //Log::channel('customlog')->error($message);
            return $this->ReturnResponse(false, $message, [], 500);
        }
    }

    public function deleteWaiterBySpace(Request $request, $space_uuid)
    {
        $space = Space::Where([['uuid', $space_uuid], ['is_deleted', 0], ['is_active', 1]])
            ->first();
        if (!$space) {
            return $this->ReturnResponse(false, "Space not found", [], 404);
        }

        $validator = Validator::make(
            $request->all(),
            [
                'user_id'     => 'required|exists:users,id',
            ]
        );

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

        $user = User::where([['id', $request->user_id], ['is_active', 1], ['is_deleted', 0]])->first();

        if (!$user) {
            return $this->ReturnResponse(false, "User not found", [], 404);
        }

        $userRole = UserRole::where([['user_id', $request->user_id], ['role_id', Role::where('name', 'Serveur')->first()->id], ['is_active', 1], ['is_deleted', 0]])->first();


        if (!$userRole) {
            return $this->ReturnResponse(false, "user does not have this right", [], 404);
        }

        $userRoleSpace = UsersRolesSpace::where([['space_id', $space->id], ['user_role_id'], ['is_active', 1], ['is_deleted', 0]])->first();

        if (!$userRoleSpace) {
            return $this->ReturnResponse(false, "user does not have this right in this space", [], 404);
        }

        $userRoleSpace->update([
            'is_active' => false,
            'is_deleted' => true,
            'deleted_at' => now(),
            'deleted_by' => request()->user()->id,
        ]);

        return $this->ReturnResponse(false, "user deleted in this space", [], 200);
    }
}
