<?php

namespace App\Http\Controllers\Api\App\Auth;

use Exception;
use Illuminate\Support\Str;
use App\Services\OtpService;
use App\Services\SMSService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Tymon\JWTAuth\Facades\JWTAuth;
use App\Http\Controllers\Controller;
use App\Traits\CheckUserStatusTrait;
use App\Models\{Country, Device, User};
use App\Http\Requests\Api\App\Auth\LoginRequest;
use App\Http\Resources\Api\App\User\UserResource;
use App\Http\Requests\Api\App\Auth\EditPhoneRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use App\Http\Requests\Api\App\Auth\ResetPasswordRequest;
use App\Http\Requests\Api\App\Auth\{CheckCodeRequest, LogoutRequest, RegisterRequest, SendCodeRequest};

class AuthController extends Controller
{
    use CheckUserStatusTrait;

    public function login(LoginRequest $request)
    {
        // dd(request()->header('Accept-Language'));
        if (!$token = auth('api')->attempt($this->getCredentials($request) + ['user_type' => 'client'])) {
            return response()->json([
                'status'  => 'fail',
                'data'    => null,
                'message' => trans('These credentials do not match our records')
            ], 422);
        }

        $user = auth('api')->user();

        $this->checkUser($user, new UserResource($user));

        $user->update(['locale' => request()->header('Accept-Language')]);

        $user->devices()->firstOrCreate($request->only(['device_token', 'type']));

        $user->profile()->update(['last_login_at' => now()]);
        $user->refresh();
        data_set($user, 'token', $token);
        return (new UserResource($user))->additional(['status' => 'success', 'message' => trans('Login Successfully')]);
    }

    public function register(RegisterRequest $request)
    {
        $country = Country::where('phone_code', $request->phone_code)->firstOrFail();
        DB::beginTransaction();
        try {
            $code             = '1111'; // OtpService::generateCode();
            $locale           = in_array($request->header('Accept-Language'), config('translatable.locales')) ? $request->header('Accept-Language') : 'en';
            $user_data = [
                'locale'     => $locale,
                'reset_code' => $code,
            ];
            $user = User::create($request->validated() + $user_data);
            $user->profile()->create(['country_id' => $country->id]);
            $user->wallet()->firstOrCreate();
            // SMSService::sendVerificationCode($user->phone_code . $user->phone, $code);
            DB::commit();
            return response()->json(['status' => 'success', 'data' => UserResource::make($user->load('wallet')), 'message' => trans('Registration has been completed successfully')]);
        } catch (Exception $e) {
            DB::rollback();
            info($e->getMessage());
            return response()->json(['status' => 'fail', 'data' => null, 'message' => trans('Something went wrong, please try again')], 422);
        }
    }

    public function editPhone(EditPhoneRequest $request)
    {
        $code             = '1111'; // OtpService::generateCode();
        $user = User::where(['user_type' => 'client', 'phone_verified_at' => null , 'phone_code' => $request->old_phone_code, 'phone' => $request->old_phone])
            ->firstOr(function () {
                throw new HttpResponseException(response()->json(['status' => 'fail', 'data' => null, 'message' => trans('User not found')], 422));
            });
            $user->update(['phone' => $request->phone, 'phone_code' => $request->phone_code, 'reset_code' => $code]);

        // SMSService::sendVerificationCode($user->phone_code . $user->phone, $code);

        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('The code send Successful')]);
    }

    public function sendCode(SendCodeRequest $request)
    {
        $code             = '1111'; // OtpService::generateCode();

        $user = User::where(['phone' => $request->phone, 'phone_code' => $request->phone_code , 'user_type' => 'client'])->first();
        if (!$user) {
            return response()->json(['status' => 'fail', 'data' => null, 'message' => trans('User not found')], 422);
        }
        $user->update(['reset_code' => $code, 'phone_verified_at' => null]);
        // SMSService::sendVerificationCode($user->phone_code . $user->phone, $code);

        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('The code send Successful')]);
    }

    public function checkCode(CheckCodeRequest $request)
    {
        User::where(['phone' => $request->phone, 'phone_code' => $request->phone_code, 'reset_code' => $request->code])->firstOr(function () {
            throw new HttpResponseException(response()->json(['status' => 'fail', 'data' => null, 'message' => trans('The code is not correct')], 422));
        });

        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('The code is correct')]);
    }

    public function verify(CheckCodeRequest $request)
    {
        $user = User::where(['phone' => $request->phone, 'phone_code' => $request->phone_code, 'reset_code' => $request->code, 'user_type' => 'client'])->whereNull('phone_verified_at')->firstOr(function () {
            throw new HttpResponseException(response()->json(['status' => 'fail', 'data' => null, 'message' => trans('The code is not correct')], 422));
        });
        if ($user->is_ban) {
            auth('api')->logout();
            return response()->json([
                'status'  => 'fail',
                'data'    => new UserResource($user),
                'message' => trans('The account has been banned by the administrator', ['ban_reason' => $user->ban_reason]),
            ], 403);
        }
        if (in_array($user->user_type, ['admin', 'super_admin'])) {
            auth('api')->logout();
            return response()->json(['status' => 'fail', 'data' => null, 'message' => trans('You cannot register')], 422);
        }

        DB::beginTransaction();
        try {
            if ($user->reset_code == $request->code) {
                $user->update(['reset_code' => null, 'phone_verified_at' => now()]);
                $user->devices()->firstOrCreate($request->only(['device_token', 'type']));
                $token = JWTAuth::fromUser($user);
                data_set($user, 'token', $token);
                DB::commit();
                return response()->json(['status' => 'success', 'data' => UserResource::make($user->load('wallet')), 'message' => '']);
            } else {
                return response()->json(['status' => 'fail', 'message' => trans('The code is not correct'), 'data' => null], 422);
            }
        } catch (Exception $e) {
            DB::rollback();
            info($e);
            return response()->json(['status' => 'fail', 'data' => null, 'message' => trans('Something went wrong, please try again')], 422);
        }
    }

    public function logout(LogoutRequest $request)
    {
        if (auth('api')->check()) {
            $user   = auth('api')->user();
            if (isset($request->device_token) && isset($request->type)) {
                Device::where(['user_id' => auth('api')->id(), 'device_token' => $request->device_token, 'type' => $request->type])->delete();
            }
            $user->profile()->update(['last_login_at' => null]);
            auth('api')->logout();
            return response()->json(['status' => 'success', 'data' => null, 'message' => trans('You have successfully logged out')]);
        }
    }

    public function updateFcm()
    {
        Device::updateOrCreate(['user_id' => auth('api')->id(), 'type' => request()->type], ['device_token' => request()->device_token]);
        return response()->json(['status' => 'success', 'data' => null, 'message' => trans('Updated successfully')]);
    }

    protected function getCredentials(Request $request)
    {
        //dd($request);
        $username = $request['phone'];
        $credentials = [];
        switch ($username) {
            case filter_var($username, FILTER_VALIDATE_EMAIL):
                $username = 'email';
                break;
            case is_numeric($username):
                $username = 'phone';
                break;
            default:
                $username = 'email';
                break;
        }
        $credentials[$username] = $request['phone'];
        $credentials['phone_code'] = $request['phone_code'];
        if ($request['password']) {
            $credentials['password'] = $request['password'];
        }
        return $credentials;
    }

    public function resetPassword(ResetPasswordRequest $request)
    {
        $user = User::where(['phone' => $request->phone, 'phone_code' => $request->phone_code ,'deleted_at' => null, 'user_type' => 'client'])
            ->firstOr(function () {
                throw new HttpResponseException(response()->json(['status' => 'fail', 'data' => null, 'message' => trans('User not found')], 422));
            });

        // $this->checkUser($user, new ProfileResource($user));

        if ($user->reset_code == $request->code) {
            $user->update(['password' => $request->password, 'reset_code' => null, 'phone_verified_at' => now()]);
            return response()->json(['status' => 'success', 'data' => null, 'message' => trans('Password changed successfully')]);
        }

        return response()->json(['status' => 'fail', 'data' => null, 'message' => trans('incorrect code')], 422);
    }
}
