<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\UserVerification;
use App\PasswordResets;
use JWTAuth;
use Auth;
use App\Role;
use App\Company;

use Aloha\Twilio\Twilio;
use Tymon\JWTAuth\Exceptions\JWTException;
use Validator, DB, Hash, Mail, Illuminate\Support\Facades\Password;
use Illuminate\Auth\Passwords\TokenRepositoryInterface;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;

class AuthController extends Controller
{
    protected $hasher;
    public function __construct(HasherContract $hasher)
    {
        $this->hasher = $hasher;
    }
    /**
     * API Send verification code
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function sendVerification(Request $request){
        $credentials = $request->only('phone');
        $rules = [
            'phone' => 'required|digits_between:10,11|unique:users'
        ];
        $validator = Validator::make($credentials, $rules);

        if($validator->fails()){
            return response()->json(['success'=> false, 'message'=> 'The minimum length should be 10.' ], 400);
        }

        // create user if not exist
        $user = User::firstOrNew([
                        'phone' => $request->phone
        ]);
        $user->save();

        // create token if not exist, update if exist
        $token = mt_rand(0000,9999);

        // for testing
        if($request->phone == '0123456789'){
            $token = "1234";
        }

        $user_verification = $user->phoneVerification()->firstOrNew([
            'user_id' => $user->id,
        ]);
        $user_verification->token = $token;
        $user_verification->save();

        // TODO:  send token to phone
        //$message = "RM0.00 IZYIM: Verification code : ". $token;
        //$twilio = new Twilio(env('TWILIO_ACC'), env('TWILIO_TOKEN'), env('TWILIO_NUMBER'));
        //$twilio->message($request->phone, $message);
        return response()->json(['success'=> true, 'message'=> 'A verification code has been send to your mobile number.' ], 200);

    }

    /**
     * API Verify User
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function verifyPhone(Request $request)
    {
        $credentials = $request->only('phone', 'token');

        // check if user already verified
        $check_user = User::where('phone', $request->phone)->first();
        if(!is_null($check_user)){
            if($check_user->is_verified == 1){
                return response()->json([
                    'success'=> true,
                    'message'=> 'Account already verified.'
                ], 200);
            }
        }
        else{
            return response()->json([
                'success'=> false,
                'message'=> 'Please contact support.'
            ], 400);
        }

        // check and verify valid token
        $check_token = $check_user->phoneVerification()->where('token', $request->token)->first();
        if(!is_null($check_token)){
            $check_user->is_verified = 1;
            $check_user->save();
            $check_token->delete();

            if (!$userToken=JWTAuth::fromUser($check_user)) {
                return response()->json(['error' => 'invalid_credentials'], 401);
            }

            // TODO : Create company for user


            $expiration = JWTAuth::setToken($userToken)->getPayload()->get('exp');
            // all good so return the token
            return response()->json(['success' => true, 'token' => $userToken,
            'token_type' => 'bearer',
            'expires_in' => $expiration - time()]);
        }
        return response()->json(['success'=> false, 'error'=> "Verification code is invalid."], 400);
    }

    /**
     * API Register
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function updateUser(Request $request)
    {
        $credentials = $request->only('role', 'name', 'password', 'password_confirmation');

        $rules = [
            'name' => 'required|max:255',
            'role' => 'required',
            'password' => 'required|confirmed|min:6'
        ];

        $validator = Validator::make($credentials, $rules);
        if($validator->fails()) {
            return response()->json(['success'=> false, 'error'=> $validator->messages()], 400);
        }

        $name = $request->name;
        $password = $request->password;
        $role = $request->role;

        // find role
        $role = Role::where('name','=',$role)->first();

        $user = Auth::user();

        // attach role to user
        $user->attachRole($role);
        $user->update(['name' => $name, 'password' => Hash::make($password)]);

        // TODO : create company for user
        $company = new Company;
        $company->user_id = $user->id;
        $company->save();


        return response()->json(['success'=> true, 'message'=> 'Profile updated.'], 200);
    }


    /**
     * API Login, on success return JWT Auth token
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        $credentials = $request->only('phone', 'password');

        $rules = [
            'phone' => 'required|digits:11',
            'password' => 'required',
        ];
        $validator = Validator::make($credentials, $rules);
        if($validator->fails()) {
            return response()->json(['success'=> false, 'error'=> $validator->messages()]);
        }

        $credentials['is_verified'] = 1;

        try {
            // attempt to verify the credentials and create a token for the user
            if (! $token = JWTAuth::attempt($credentials)) {
                return response()->json(['success' => false, 'error' => 'Phone or password incorrect'], 401);
            }
        } catch (JWTException $e) {
            // something went wrong whilst attempting to encode the token
            return response()->json(['success' => false, 'error' => 'Failed to login, please try again.'], 500);
        }
        // all good so return the token
        return response()->json(['success' => true, 'data'=> [ 'token' => $token ]]);
    }

    /**
     * Log out
     * Invalidate the token, so user cannot use it anymore
     * They have to relogin to get a new token
     *
     * @param Request $request
     */
    public function logout(Request $request) {
        $this->validate($request, ['token' => 'required']);

        try {
            JWTAuth::invalidate($request->input('token'));
            return response()->json(['success' => true, 'message'=> "You have successfully logged out."]);
        } catch (JWTException $e) {
            // something went wrong whilst attempting to encode the token
            return response()->json(['success' => false, 'error' => 'Failed to logout, please try again.'], 500);
        }
    }

     /**
     * API Recover Password
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function recover(Request $request)
    {

        $credentials = $request->only('phone');

        $rules = [
            'phone'=> 'required',
        ];

        $validator = Validator::make($credentials, $rules);
        if($validator->fails()) {
            return response()->json(['success'=> false, 'error'=> $validator->messages()]);
        }

        $user = User::where('phone', $request->phone)->first();

        if ($user){
            $token = str_random(64);
            DB::table(config('auth.passwords.users.table'))->insert([
                'phone' => $user->phone,
                'token' => $token
            ]);
            return response()->json([
                'success' => true, 'data'=> ['message'=> 'A reset link has been send to your mobile phone.']
            ]);
        }

        /*
        todo

        send SMS
        */

        return response()->json([
            'success' => false, 'data'=> ['message'=> 'Fail to recover your account.']
        ]);
    }

    /**
     * Reset the given user's password.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function reset(Request $request)
    {

        $credentials = $request->only('token', 'password', 'password_confirmation');

        $rules = [
            'token' => 'required',
            'password' => 'required|confirmed|min:6'
        ];

        $validator = Validator::make($credentials, $rules);
        if($validator->fails()) {
            return response()->json(['success'=> false, 'error'=> $validator->messages()]);
        }
        $token = $request->get('token');
        $password = $request->get('password');
        $reset = PasswordResets::where('token', $token)->first();
        if($reset) {
            $user = User::where('phone', '=', $reset->phone)->first();
            $user->password = Hash::make($password);
            $user->save();
            $reset->delete();
            return response()->json([
                'success' => false, 'data'=> ['message'=> 'Reset success']
            ]);
        }
        return response()->json([
            'success' => false, 'data'=> ['message'=> 'Invalid token or email or expired code']
        ]);
    }
}