<?php
/**
* Social Login Controller
* Login with social (google + facebook)
* Handle G2FA
*
* @package TokenLite
* @author Softnio
* @version 1.0.2
*/
namespace App\Http\Controllers\Auth;

use Auth;
use Session;
use Socialite;
use App\Models\User;
use App\Models\Activity;
use App\Models\UserMeta;
use Jenssegers\Agent\Agent;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\GlobalMeta;
use App\Models\PrivateInvitation;
use App\Models\Referral;
use Illuminate\Support\Facades\Cookie;

class SocialAuthController extends Controller
{
    // Available social login
    protected $available = ['facebook', 'google'];
    /**
     * Redirect to the Service for Login
     *
     * @return \Illuminate\Http\Response
     */
    public function redirect($social)
    {
        if (! in_array($social, $this->available)) {
            session()->flash('warning', __('messages.invalid.social'));
            return redirect()->route('login');
        }
        if (
            (get_setting('site_api_fb_id', env('FB_CLIENT_ID', '')) != '' && get_setting('site_api_fb_secret', env('FB_CLIENT_SECRET', '')) != '') ||
            (get_setting('site_api_google_id', env('GOOGLE_CLIENT_ID', '')) != '' && get_setting('site_api_google_secret', env('GOOGLE_CLIENT_SECRET', '')) != '')
            ) {
            if(request()->has('invite')) {
                $invite_code = request()->invite;
                if(!empty($invite_code)) {
                    if(strlen($invite_code) >= 4 && strlen($invite_code) <= 20) {
                        Cookie::queue('private_socia_auth', $invite_code, 15);
                    }
                }
            }

            return Socialite::driver($social)->redirect();
        } else {
            return back()->with(['warning' => __('messages.invalid.social')]);
        }
    }

    /**
     * Callback for Socialite
     *
     * @return \Illuminate\Http\Response
     */
    public function callback($social)
    {
        try {
            $invite_code = Cookie::get('private_socia_auth');
            Cookie::expire('private_socia_auth');

            $user = Socialite::driver($social)->user();

            if (empty($user)) {
                session()->flash('info', __('Sorry, Something is wrong, please login via your email & password!'));
                return redirect()->route('login');
            }

            $email = $user->getEmail();
            $id = $user->getId();

            //check if user already exists
            $checkUser = User::where(['email'=> $email, 'social_id' => $id])->first();
            if ($checkUser) {
                Auth::login($checkUser, true);
                $this->save_activity();
                // return redirect()->route('home');
            }
            $checkEMail = User::where(['email'=> $email])->first();
            if ($checkEMail) {
                $has_social = ($checkEMail->social_id != null) ? true : false;
                $msg = ($has_social) ? 'You are already registered, try again with different social account!' : 'Sorry, Something is wrong, please try again!';
                session()->flash('warning', $msg);
                return redirect()->route('login');
            }

            $flag = false;
            if(get_setting('registration_option') == 'invite') {
                if(get_setting('private_invitation_active')==1 && (empty($invite_code) || strlen($invite_code) < 4 || strlen($invite_code) > 20)) {
                    $flag = true;
                } elseif(get_setting('private_invitation_active')==0) {
                    $flag = true;
                }

                if($flag == true) {
                    session()->flash('warning', __('You have not registered yet in our platform.'));
                    return redirect()->route('login');
                }
            }
            $notice = "You have not registered yet in our platform. You can sign up with your ".ucfirst($social)." account.";
            // show the confirm form
            return view('auth.social', compact('user', 'social', 'notice', 'invite_code'));
        } catch (\Exception $e) {
            session()->flash('warning', __('Sorry, Something is wrong, please login via your email & password!!'));
            return redirect()->route('login');
        }
    }

    /**
     * Finally register the user
     *
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required|string',
            'email' => 'required|email|regex:/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,9}$/ix|unique:users',
            'social_id' => 'required',
        ]);

        if (get_setting('private_invitation_active')== 1 && !empty($request->invitation_code)) {
            $invite_code = strip_tags($request->invitation_code);
            if(strlen($invite_code) < 4 || strlen($invite_code) > 20) {
                $invite_code = null;
            } else {
                $invite_code = PrivateInvitation::stage_status_chk($invite_code);
            }
            if(empty($invite_code)) {
                session()->flash('warning', __('The invitation link is invalid or already expired.'));
                return redirect()->route('login');
            }
        } elseif(get_setting('registration_option')=='invite') {
            session()->flash('warning', __('You have not registered yet in our platform.'));
            return redirect()->route('login');
        }

        $password = str_random(12);
        $createUser = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($password),
            'role' => 'user',
            'lastLogin' => date("Y-m-d H:i:s"),
        ]);

        if ($createUser) {
            UserMeta::create([
                'userId' => $createUser->id
            ]);
            $social = $request->social;
            $createUser->email_verified_at = in_array($social, $this->available) ? now() : null;
            $createUser->status = 'active';
            $createUser->registerMethod = $social;
            $createUser->social_id = $request->social_id;

            $refer_blank = true;
            if (is_active_referral_system()) {
                if (Cookie::has('ico_nio_ref_by')) {
                    $ref_id = (int) Cookie::get('ico_nio_ref_by');
                    if(disable_email_verification() == 1) {
                        $ref_user = User::where('id', $ref_id)->first();
                    } else {
                        $ref_user = User::where('id', $ref_id)->where('email_verified_at', '!=', null)->first();
                    }
                    if ($ref_user) {
                        $createUser->referral = $ref_user->id;
                        $createUser->referralInfo = json_encode([
                            'user' => $ref_user->id,
                            'name' => $ref_user->name,
                            'time' => now(),
                        ]);
                        $refer_blank = false;
                        $this->create_referral_or_not($createUser->id, $ref_user->id);
                        Cookie::queue(Cookie::forget('ico_nio_ref_by'));
                    }
                }
            }
            if ($createUser->role=='user' && $refer_blank==true) {
                $this->create_referral_or_not($createUser->id);
            }

            if(get_setting('private_invitation_active')==1 && !empty($request->invitation_code)) {
                $invitation = PrivateInvitation::where('code', $request->invitation_code)->first();
                $invitation->signup = $invitation->signup+1;
                $invitation->save();

                GlobalMeta::save_meta('private_reg_code', $invitation->code, $createUser->id);
                Cookie::queue('private_sale_'.$invitation->code, $invitation->code, 43200);
            }

            $createUser->save();

            Auth::login($createUser, true);
            $this->save_activity();

            return redirect()->route('home');
        } else {
            return redirect()->route('home');
        }
    }
    /**
     * Save user Activity
     *
     * @return activity
     */
    protected function save_activity()
    {
        if (UserMeta::getMeta(Auth::id())->save_activity == 'TRUE') {
            $agent = new Agent();

            $ret['activity'] = Activity::create([
                'user_id' => Auth::id(),
                'browser' => $agent->browser().'/'.$agent->version($agent->browser()),
                'device' => $agent->device().'/'.$agent->platform().'-'.$agent->version($agent->platform()),
                'ip' => request()->ip()
            ]);
        }
    }


    /*
     * Show the Google 2fa form
     */
    public function show_2fa_form()
    {
        if (auth()->user()->google2fa != 1) {
            return redirect()->route('home');
        }
        return view('auth.g2fa');
    }

    public function show_2fa_reset_form(Request $request)
    {
        if (!isset($request->token)) {
            return redirect()->route('login')->with(['warning' => 'Invalid or Expired 2FA reset verification code!']);
        }

        $token = $request->token;
        $meta = UserMeta::where('email_token', $token)->first();

        if (!isset($meta->user)) {
            return redirect()->route('login')->with(['warning' => 'Invalid 2FA reset verification code!']);
        }
        if (strtotime($meta->email_expire) < time()) {
            return redirect()->route('login')->with(['warning' => 'Expired 2FA reset verification code!']);
        }
        $user = $meta->user;

        return view('auth.reset2fa', compact('user', 'meta', 'token'));
    }

    public function reset_2fa(Request $request)
    {
        $request->validate([
            'token' => 'required',
            'password' => 'required|string'
        ]);
        $token = $request->token;
        $meta = UserMeta::where('email_token', $token)->first();
        if (!isset($meta->user)) {
            return redirect()->route('login')->with(['warning' => 'Invalid 2FA reset verification code!']);
        }
        $user = $meta->user;
        $check = Hash::check($request->password, $user->password);
        if ($check) {
            $user->google2fa = 0;
            $user->google2fa_secret = null;
            $user->save();
            Auth::login($user);

            if ($user->meta) {
                $user->meta->email_token = str_random(65);
                $user->meta->email_expire = now()->addMinutes(75);
                $user->meta->save();
            }
            session()->flash('info', 'Successfully reset your 2FA authentication!');
            if ($user->role == 'admin') {
                return redirect()->route('admin.home');
            }
            return redirect()->route('user.home');
        }
        return back()->with(['error' => 'Invalid password!']);
    }

    /**
     * Create user in referral table.
     *
     * @param  $user, $refer
     * @version 1.0
     * @since 1.6.0
     * @return void
     */
    protected function create_referral_or_not($user, $refer=0)
    {
        Referral::create([ 'user_id' => $user, 'user_bonus' => 0, 'refer_by' => $refer, 'refer_bonus' => 0 ]);
    }
}
