<?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 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 SimpleSoftwareIO\QrCode\Facades\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 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]])->get();

        return $this->ReturnResponse(true, "Space's stocks", ["space"=>$space , "stocks"=>$stocks], 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);


    }

    /**
     * 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);
        }

    }

}
