<?php

namespace App\Http\Controllers\Api;

use App\Enums\SMSEnums;
use App\Enums\UsersTypesEnums;
use App\Http\Controllers\Controller;
use App\Http\Requests\ActiveSmsCodeRequest;
use App\Http\Requests\ChangePhoneNumberRequest;
use App\Http\Requests\checkPhoneIsExistsRequest;
use App\Http\Requests\resendVerificationCodeRequest;
use App\Http\Requests\Users\UpdateUserProfileRequest;
use App\Http\Requests\Users\UserStoreRequest;
use App\Http\Requests\VerifyEmailByCodeRequest;
use App\Http\Resources\UserResource;
use App\Http\Services\SMSService;
use App\Mail\UserRegistered;
use App\Models\SMSLog;
use App\Models\User;
use App\Repository\Users\UsersRepo;
use Carbon\Carbon;
use Hashids\Hashids;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;

class UsersController extends Controller
{
    private $usersRepo;

    public function __construct(UsersRepo $usersRepo)
    {
        $this->usersRepo = $usersRepo;
    }

    public function index()
    {
        return response()->json([
            'user' => new UserResource(\request()->user())
        ]);
    }

    public function store(UserStoreRequest $request)
    {
        $request->offsetSet('country_id', $request->input('country_id'));
        $user = $this->usersRepo->create($request->input());

        Mail::to('Blockatboutique@gmail.com')->send(new UserRegistered($request));
        return response()->json([
            'user' => new UserResource($user),
            'token' => $user->createToken($request->input('device_name', Carbon::now()->toDateTimeString()))->plainTextToken
        ]);
    }

    public function updateUserProfile(UpdateUserProfileRequest $request)
    {
        $user = $this->usersRepo->update($request);
        return response()->json([
            'user' => new UserResource($user)
        ]);
    }

    public function activeUserBySmsCode(ActiveSmsCodeRequest $request)
    {
        $message = $this->usersRepo->activeUserBySmsCode($request);
        return response()->json([
            'user' => new UserResource($request->user()),
            'message' => $message[0]
        ], $message[1]);
    }

    public function VendorAcceptContract()
    {
        $user = auth()->user();
        if ($user && $user->shop_accept_contract) {
            return response()->json(['message'=>trans('global.vendor_already_accepted_contract'),'status'=>false]);

        } elseif ($user) {
            $user->update(['shop_accept_contract' => 1]);
            return response()->json(['message' => trans('global.shop_accept_contract'),'status'=>true]);
        } else {
            return ValidationError(trans('global.unauthenticated'));
        }
    }

    public function sendResetPasswordCode(Request $request)
    {
        $user = User::query()
            ->where('country_id', $request->input('country_id'))
            ->where('phone', $request->input('phone'))
            ->first();
        if (!$user) {
            return response()->json([
                'message' => trans('global.invalid_phone_number'),
            ], 422);
        }
        $user->sms()->where('type', SMSEnums::ResetPassword)->update(['code' => null]);

        (new SMSService($user))->sendResetCode($user);
        cache()->put('passed'.$user->id, bcrypt($request->input('new_password')));

        return $user
            ? response()->json(['message' => trans('global.otp_send_success')])
            : response()->json(['message' => trans('global.user_not_found')], 422);
    }

    public function resetPassword(Request $request)
    {
        $user = User::query()
            ->where('country_id', $request->input('country_id'))
            ->where('phone', $request->input('phone'))
            ->first();
        if (!$user) {
            return response()->json([
                'message' => trans('global.invalid_phone_number'),
            ], 422);
        }
        $hasSameCode = $user->sms()->where('type', SMSEnums::ResetPassword)->where('code', $request->input('code'))->exists();
        $pass = cache()->get('passed'.$user->id);
        if (($user && $hasSameCode) || (env('SMS_ALLOW') == false && $request->input('code') == 1234)) {
            $user->update(['password' => $pass]);
            $user->sms()->where('type', SMSEnums::ResetPassword)->update(['code' => null]);
            cache()->forget('passed'.$user->id);
        } else {
            return response()->json([
                'message' => trans('global.invalid_code_number'),
            ], 422);
        }
        return response()->json([
            'message' => trans('global.reset_password_success')
        ]);
    }

    public function verifyEmailByCode(VerifyEmailByCodeRequest $request)
    {
        $message = $this->usersRepo->activeEmailByCode($request);
        return response()->json([
            'user' => new UserResource($request->user()),
            'message' => $message[0]
        ], $message[1]);
    }

    public function checkPhoneIsExists(checkPhoneIsExistsRequest $request)
    {
        $user = User::query()
            ->where('country_id', $request->input('country_id'))
            ->where('phone', $request->input('phone'))
            ->first();

        return response()->json([
            'exists' => (boolean) $user,
            'message' => $user ? trans('global.user_exist') : trans('global.phone_not_found')
        ], 200);
    }

    public function ChangePhoneNumber(ChangePhoneNumberRequest $request)
    {
        $message = $this->usersRepo->ChangePhoneBySmsCode($request);
        return response()->json([
            'user' => new UserResource($request->user()),
            'message' => $message[0]
        ], $message[1]);
    }

    public function resendVerificationCode(resendVerificationCodeRequest $request)
    {
        if ($request->user()) {
            (new SMSService($request->user()))->sendActivationCode($request->user());
            return response()->json([
                'message' => 'Verification code has been sent to your phone number'
            ]);
        }
    }

    public function switchUserType()
    {
        $user = auth()->user();

        if (!$user) return response()->json(['message' => 'User not found!'], 404);

        if ($user->user_type == UsersTypesEnums::User) {
            $user->update([
                'user_type' => UsersTypesEnums::Vendor,
            ]);
        } else {
            $user->update([
                'user_type' => UsersTypesEnums::User,
            ]);
        }
        $user->update([
            'user_vendor' => true,
        ]);
        if ($user->shop_name != NULL && $user->shop_name_en != NULL && $user->whatsapp != NULL) {
            $has_completed_shop_info = 1;
        } else {
            $has_completed_shop_info = 0;
        }
        return response()->json([
                'user' => new UserResource($user),
                'message' => 'Switched to ' . ($user->user_type == UsersTypesEnums::User ? 'Normal user' : 'Vendor'),
            ] + ($user->user_type == UsersTypesEnums::Vendor ? ['has_completed_shop_info' => $has_completed_shop_info] : []));
    }
    public function destroy(Request $request)
    {
        try {
                /** @var \App\Models\User */
                $user = auth()->user();

                $user->tokens()->delete();
                $user->update([
                    'phone' => $user->phone . '-' . now()->format('Y-m-d H:i A'),
                    'shop_name' => $user->shop_name . '-DELETED',
                    'shop_name_en' => $user->shop_name_en . '-DELETED',
                ]);
                $user->delete();
                return response()->json(['message' => trans('global.user_deleted'),'status' => true]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => trans('global.something_wrong'),
            ], $e->getMessage());
        }
    }

    public function checkAuth()
    {
        if (!auth()->check()) {
            return response()->json([
                'status' => false,
                'message' => trans('global.unauthenticated'),
            ]);
        }
        return response()->json([
            'status' => true,
            'message' => trans('global.available'),
        ]);
    }
}
