<?php

namespace App\Http\Controllers;

use App\BvLog;
use App\Deposit;
use App\GeneralSetting;
use App\Lib\GoogleAuthenticator;
use App\Plan;
use App\Rules\FileTypeValidate;
use App\Trx;
use App\User;
use App\UserExtra;
use App\UserLogin;
use App\Withdrawal;
use App\WithdrawMethod;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use  Auth;
use  Session;
use Illuminate\Support\Str;

class UserController extends Controller
{
    public function home()
    {
        $user = Auth::user();
        $data['page_title'] = "Dashboard";
        $data['total_deposit'] = Deposit::whereUserId($user->id)->whereStatus(1)->sum('amount');
        $data['total_withdraw'] = Withdrawal::whereUserId($user->id)->whereStatus(1)->sum('amount');
        $data['complete_withdraw'] = Withdrawal::whereUserId($user->id)->whereStatus(1)->count();
        $data['pending_withdraw'] = Withdrawal::whereUserId($user->id)->whereStatus(0)->count();;
        $data['reject_withdraw'] = Withdrawal::whereUserId($user->id)->whereStatus(2)->count();;


        return view(activeTemplate() . 'user.dashboard', $data);
    }

    public function profile()
    {
        $page_title = 'Profile';
        return view(activeTemplate() . 'user.profile', compact('page_title'));
    }

    public function profileUpdate(Request $request)
    {
        $request->validate([
            'firstname' => 'required|max:160',
            'lastname' => 'required|max:160',
            'address' => 'nullable|max:160',
            'city' => 'nullable|max:160',
            'state' => 'nullable|max:160',
            'zip' => 'nullable|max:160',
            'country' => 'nullable|max:160',
            'image' => ['nullable', 'image', new FileTypeValidate(['jpeg', 'jpg', 'png'])],
        ]);

        $filename = auth()->user()->image;
        if ($request->hasFile('image')) {
            try {
                $path = config('constants.user.profile.path');
                $size = config('constants.user.profile.size');
                $filename = upload_image($request->image, $path, $size, $filename);
            } catch (\Exception $exp) {
                $notify[] = ['success', 'Image could not be uploaded'];
                return back()->withNotify($notify);
            }
        }

        auth()->user()->update([
            'firstname' => $request->firstname,
            'lastname' => $request->lastname,
            'image' => $filename,
            'address' => [
                'address' => $request->address,
                'city' => $request->city,
                'state' => $request->state,
                'zip' => $request->zip,
                'country' => $request->country,
            ]
        ]);
        $notify[] = ['success', 'Your profile has been updated'];
        return back()->withNotify($notify);
    }

    public function passwordChange()
    {
        $page_title = 'Password Change';
        return view(activeTemplate() . 'user.password', compact('page_title'));
    }

    public function passwordUpdate(Request $request)
    {
        $request->validate([
            'old_password' => 'required',
            'password' => 'required|confirmed|max:160|min:6'
        ]);

        if (!Hash::check($request->old_password, auth()->user()->password)) {
            $notify[] = ['error', 'Your old password doesnt match'];
            return back()->withNotify($notify);
        }
        auth()->user()->update([
            'password' => bcrypt($request->password)
        ]);
        $notify[] = ['success', 'Your password has been updated'];
        return back()->withNotify($notify);
    }

    public function show2faForm()
    {
        $gnl = GeneralSetting::first();
        $ga = new GoogleAuthenticator();
        $user = auth()->user();
        $secret = $ga->createSecret();
        $qrCodeUrl = $ga->getQRCodeGoogleUrl($user->username . '@' . $gnl->sitename, $secret);
        $prevcode = $user->tsc;
        $prevqr = $ga->getQRCodeGoogleUrl($user->username . '@' . $gnl->sitename, $prevcode);
        $page_title = 'Google 2FA Auth';

        return view(activeTemplate() . 'user.go2fa', compact('page_title', 'secret', 'qrCodeUrl', 'prevcode', 'prevqr'));
    }

    public function create2fa(Request $request)
    {
        $user = auth()->user();
        $this->validate($request, [
            'key' => 'required',
            'code' => 'required',
        ]);

        $ga = new GoogleAuthenticator();
        $secret = $request->key;
        $oneCode = $ga->getCode($secret);

        if ($oneCode === $request->code) {
            $user->tsc = $request->key;
            $user->ts = 1;
            $user->tv = 1;
            $user->save();

            send_email($user, '2FA_ENABLE', [
                'code' => $user->ver_code
            ]);
            send_sms($user, '2FA_ENABLE', [
                'code' => $user->ver_code
            ]);

            $notify[] = ['success', 'Google Authenticator Enabled Successfully'];
            return back()->withNotify($notify);
        } else {
            $notify[] = ['danger', 'Wrong Verification Code'];
            return back()->withNotify($notify);
        }
    }


    public function disable2fa(Request $request)
    {
        $this->validate($request, [
            'code' => 'required',
        ]);

        $user = auth()->user();
        $ga = new GoogleAuthenticator();

        $secret = $user->tsc;
        $oneCode = $ga->getCode($secret);
        $userCode = $request->code;

        if ($oneCode == $userCode) {

            $user->tsc = null;
            $user->ts = 0;
            $user->tv = 1;
            $user->save();

            send_email($user, '2FA_DISABLE');
            send_sms($user, '2FA_DISABLE');

            $notify[] = ['success', 'Two Factor Authenticator Disable Successfully'];
            return back()->withNotify($notify);
        } else {
            $notify[] = ['error', 'Wrong Verification Code'];
            return back()->with($notify);
        }
    }

    public function depositHistory()
    {
        $page_title = 'Deposit History';
        $empty_message = 'No history found.';
        $logs = auth()->user()->deposits()->with(['gateway'])->latest()->paginate(config('constants.table.default'));
        return view(activeTemplate() . 'payment.deposit_history', compact('page_title', 'empty_message', 'logs'));
    }

    public function withdrawHistory()
    {
        $page_title = 'Withdraw History';
        $empty_message = 'No history found.';
        $logs = auth()->user()->withdrawals()->with(['method'])->latest()->paginate(config('constants.table.default'));
        return view(activeTemplate() . 'user.withdraw_history', compact('page_title', 'empty_message', 'logs'));
    }

    public function withdraw()
    {
        $page_title = 'Withdraw';
        $methods = WithdrawMethod::where('status', 1)->get();
        $logs = auth()->user()->withdrawals()->with(['method'])->latest()->paginate(config('constants.table.default'));
        $empty_message = 'No history found.';
        return view(activeTemplate() . 'user.withdraw', compact('page_title', 'methods', 'logs', 'empty_message'));
    }


    public function withdrawInsert(Request $request)
    {


        $request->validate([
            'id' => 'required|integer',
            'amount' => 'required|numeric|gt:0',
        ]);
        $withdraw = WithdrawMethod::findOrFail($request->id);

        $multiInput = [];
        if ($withdraw->user_data != null) {
            foreach ($withdraw->user_data as $k => $val) {
                $multiInput[str_replace(' ', '_', $val)] = null;
            }
        }

        if ($request->amount < $withdraw->min_limit || $request->amount > $withdraw->max_limit) {
            $notify[] = ['error', 'Please follow the limit'];
            return back()->withNotify($notify);
        }

        if ($request->amount > auth()->user()->balance) {
            $notify[] = ['error', 'You do not have sufficient balance'];
            return back()->withNotify($notify);
        }

        $exchangeRate = $withdraw->rate > 1 ? 1 / $withdraw->rate : $withdraw->rate;
        $charge = $withdraw->fixed_charge + (($request->amount * $withdraw->percent_charge) / 100);
        $withoutCharge = $request->amount - $charge;
        $final_amo = formatter_money($withoutCharge * $exchangeRate);

        $data = new Withdrawal();
        $data->method_id = $request->id;
        $data->user_id = auth()->id();
        $data->amount = formatter_money($request->amount);
        $data->charge = formatter_money($charge);
        $data->rate = $withdraw->rate;
        $data->currency = $withdraw->currency;
        $data->delay = $withdraw->delay;
        $data->final_amo = $final_amo;
        $data->status = 0;
        $data->trx = getTrx();
        $data->save();
        Session::put('Track', $data->trx);
        return redirect()->route('user.withdraw.preview');

    }


    public function withdrawPreview()
    {
        $track = Session::get('Track');
        $data = Withdrawal::where('user_id', auth()->id())->where('trx', $track)->where('status', 0)->first();
        if (!$data) {
            return redirect()->route('user.withdraw');
        }
        $page_title = "Withdraw Preview";

        return view(activeTemplate() . 'user.withdraw_preview', compact('data', 'page_title'));
    }




    public function withdrawStore(Request $request)
    {

        $track = Session::get('Track');
        $withdraw = Withdrawal::where('user_id', auth()->id())->where('trx', $track)->orderBy('id', 'DESC')->first();
        $withdraw_method = WithdrawMethod::where('status', 1)->findOrFail($withdraw->method_id);

        if (!empty($withdraw_method->user_data)) {
            foreach ($withdraw_method->user_data as $data) {
                $validation_rule['ud.' . \Str::slug($data)] = 'required';
            }
            $request->validate($validation_rule, ['ud.*' => 'Please provide all information.']);
        }

        $balance = auth()->user()->balance - $withdraw->amount;
        auth()->user()->update([
            'balance' => formatter_money($balance),
        ]);

        $withdraw->detail = $request->ud;
        $withdraw->status = 9;
        $withdraw->save();

        $trx = new Trx();
        $trx->user_id = auth()->id();
        $trx->amount = $withdraw->amount;
        $trx->charge = formatter_money($withdraw->final_amo);
        $trx->main_amo = formatter_money($withdraw->final_amo);
        $trx->balance = formatter_money(auth()->user()->balance);
        $trx->type = 'withdraw';
        $trx->trx = $withdraw->trx;
        $trx->title = 'withdraw Via ' . $withdraw->method->name;
        $trx->save();


        $general = GeneralSetting::first();

        send_email(auth()->user(), 'WITHDRAW_PENDING', [
            'trx' => $withdraw->trx,
            'amount' => $general->cur_sym . ' ' . formatter_money($withdraw->amount),
            'method' => $withdraw->method->name,
            'charge' => $general->cur_sym . ' ' . $withdraw->charge,
        ]);

        send_sms(auth()->user(), 'WITHDRAW_PENDING', [
            'trx' => $withdraw->trx,
            'amount' => $general->cur_sym . ' ' . formatter_money($withdraw->amount),
            'method' => $withdraw->method->name,
            'charge' => $general->cur_sym . ' ' . $withdraw->charge,
        ]);

        $notify[] = ['success', 'You withdraw request has been taken.'];

        return redirect()->route('user.home')->withNotify($notify);
    }


    public function transactions()
    {
        $page_title = 'Transactions';
        $logs = auth()->user()->transactions()->latest()->paginate(config('constants.table.default'));
        $empty_message = 'No transaction history';
        return view(activeTemplate() . 'user.transactions', compact('page_title', 'logs', 'empty_message'));
    }


    function loginHistory()
    {
        $data['page_title'] = "Login History";
        $data['history'] = UserLogin::where('user_id', Auth::id())->latest()->paginate(15);
        return view(activeTemplate() . '.user.login_history', $data);
    }


    function indexTransfer()
    {
        $page_title = 'Balance Transfer';
        return view(activeTemplate() . '.user.balance_transfer', compact('page_title'));
    }

    function balanceTransfer(Request $request)
    {
        $this->validate($request, [
            'username' => 'required',
            'amount' => 'required|numeric|min:0',
        ]);
        $gnl = GeneralSetting::first();
        $user = User::find(Auth::id());
        $trans_user = User::where('username', $request->username)->orwhere('email', $request->username)->first();
        if ($trans_user == '') {
            $notify[] = ['error', 'Username Not Found'];
            return back()->withNotify($notify);
        }
        if ($trans_user->username == $user->username) {

            $notify[] = ['error', 'Balance Transfer Not Possible In Your Own Account'];
            return back()->withNotify($notify);

        }
        $charge = $gnl->bal_trans_fixed_charge + ($request->amount * $gnl->bal_trans_per_charge) / 100;
        $amount = $request->amount + $charge;
        if ($user->balance >= $amount) {

            $new_balance = $user->balance - $amount;
            $user->balance = $new_balance;
            $user->save();


            $trx = getTrx();


            Trx::create([
                'trx' => $trx,
                'user_id' => $user->id,
                'type' => 'balance_transfer',
                'title' => 'Balance Transferred To ' . $trans_user->username,
                'amount' => $request->amount,
                'main_amo' => $amount,
                'balance' => $user->balance,
                'charge' => $charge
            ]);


            send_email($user, 'BAL_SEND', [

                'amount' => formatter_money($request->amount) . '' . $gnl->cur_text,
                'name' => $trans_user->username,
                'charge' =>  formatter_money($charge) . ' ' . $gnl->cur_text,
                'balance_now' =>  formatter_money($new_balance) . ' ' . $gnl->cur_text,

            ]);

            send_sms($user, 'BAL_SEND', [
                'amount' => formatter_money($request->amount) . '' . $gnl->cur_text,
                'name' => $trans_user->username,
                'charge' =>  formatter_money($charge) . ' ' . $gnl->cur_text,
                'balance_now' =>  formatter_money($new_balance) . ' ' . $gnl->cur_text,
            ]);


            $trans_new_bal = $trans_user->balance + $request->amount;
            $trans_user->balance = $trans_new_bal;
            $trans_user->save();

            Trx::create([
                'trx' => $trx,
                'user_id' => $trans_user->id,
                'type' => 'balance_receive',
                'title' => 'Balance receive From ' . $user->username,
                'amount' => $request->amount,
                'main_amo' => $request->amount,
                'balance' => $trans_new_bal,
                'charge' => 0
            ]);


            send_email($trans_user, 'bal_receive', [

                'amount' => formatter_money($request->amount) . '' . $gnl->cur_text,
                'name' => $user->username,
                'charge' => 0 . ' ' . $gnl->cur_text,
                'balance_now' =>  formatter_money($trans_new_bal) . ' ' . $gnl->cur_text,

            ]);

            send_sms($trans_user, 'bal_receive', [
                'amount' => formatter_money($request->amount) . '' . $gnl->cur_text,
                'name' => $user->username,
                'charge' => 0 . ' ' . $gnl->cur_text,
                'balance_now' =>  formatter_money($trans_user) . ' ' . $gnl->cur_text,
            ]);


            $notify[] = ['success', 'Balance Transferred Successfully.'];
            return back()->withNotify($notify);
        } else {
            $notify[] = ['error', 'Insufficient Balance.'];
            return back()->withNotify($notify);

        }
    }


    function searchUser(Request $request)
    {
        $trans_user = User::where('id', '!=', Auth::id())->where('username', $request->username)
            ->orwhere('email', $request->username)->count();
        if ($trans_user == 1) {
            return response()->json(['success' => true, 'message' => 'Correct User']);
        } else {
            return response()->json(['success' => false, 'message' => 'User Not Found']);
        }

    }


    function planIndex()
    {
        $data['page_title'] = "Plans";
        $data['plans'] = Plan::whereStatus(1)->get();
        return view(activeTemplate() . '.user.plan', $data);
    }

    function planStore(Request $request)
    {


        $this->validate($request, ['plan_id' => 'required|integer']);
        $plan = Plan::find($request->plan_id);
        $gnl = GeneralSetting::first();
        if ($plan) {
            $user = User::find(Auth::id());

            if ($user->balance >= $plan->amount) {

                $oldPlan = $user->plan_id;

                $user->update(['plan_id' => $plan->id, 'balance' => $user->balance - $plan->amount,]);

                $user->transactions()->create([
                    'trx' => getTrx(),
                    'user_id' => $user->id,
                    'amount' => $plan->amount,
                    'main_amo' => $plan->amount,
                    'balance' => $user->balance,
                    'title' => 'Purchased ' . $plan->name,
                    'charge' => 0,
                    'type' => 'purchased_plan',
                ]);


                send_email($user, 'pan_purchased', [
                    'name' => $plan->name,
                    'price' => formatter_money($plan->amount) . ' ' . $gnl->cur_text,
                    'balance_now' => formatter_money($user->balance) . ' ' . $gnl->cur_text,

                ]);

                send_sms($user, 'pan_purchased', [
                    'name' => $plan->name,
                    'price' => formatter_money($plan->amount) . ' ' . $gnl->cur_text,
                    'balance_now' => formatter_money($user->balance) . ' ' . $gnl->cur_text,
                ]);


                if ($oldPlan == 0) {
                    updatePaidCount($user->id);
                }

                $details = Auth::user()->username . ' Subscribed to ' . $plan->name . ' plan.';

                updateBV($user->id, $plan->bv, $details);

                if ($plan->com_to_tree > 0) {

                    treeComission($user->id, $plan->com_to_tree, $details);
                }

                referralComission($user->id, $details);


                $notify[] = ['success', 'Purchased ' . $plan->name . ' Successfully'];
                return redirect()->route('user.home')->withNotify($notify);


            }
            $notify[] = ['error', 'Insufficient Balance'];
            return back()->withNotify($notify);

        }
        $notify[] = ['error', 'Something Went Wrong'];
        return back()->withNotify($notify);
    }

    public function referralCom()
    {
        $data['page_title'] = "Referral Commission";

        $data['logs'] = Trx::where('user_id', auth()->id())->where('type', 'referral_commision')->latest()->paginate(config('constants.table.default'));

        $data['empty_message'] = 'No data found';
        return view(activeTemplate() . '.user.referralCom', $data);
    }

    public function binaryCom()
    {
        $data['page_title'] = "Binary Commission";

        $data['logs'] = Trx::where('user_id', auth()->id())->where('type', 'binary_comission')->latest()->paginate(config('constants.table.default'));

        $data['empty_message'] = 'No data found';

        return view(activeTemplate() . '.user.binaryCom', $data);
    }

    public function binarySummery()
    {
        $data['page_title'] = "Binary Summery";


        $data['logs'] = UserExtra::findOrfail(auth()->id());

        return view(activeTemplate() . '.user.binary_summery', $data);
    }

    public function bvlog()
    {
        $data['page_title'] = "BV LOG";

        $data['logs'] = BvLog::where('user_id', auth()->id())->orderBy('id', 'desc')->paginate(config('constants.table.default'));

        $data['empty_message'] = 'No data found';

        return view(activeTemplate() . '.user.bv_log', $data);
    }

    public function myRefLog()
    {
        $data['page_title'] = "My Referral";
        $data['empty_message'] = 'No data found';

        $data['logs'] = User::where('ref_id', auth()->id())->latest()->paginate(config('constants.table.default'));

        return view(activeTemplate() . '.user.my_ref', $data);
    }

    public function myTree()
    {


        $data['tree'] = showTreePage(Auth::id());
        $data['page_title'] = "My Tree";
        return view(activeTemplate() . 'user.my_tree', $data);
    }


    public function otherTree($username){

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

    if($user && treeAuth($user->id,Auth::id())){
        $data['tree'] = showTreePage($user->id);
        $data['page_title'] = "Tree of ".$user->fullname;
        return view(activeTemplate() . 'user.my_tree', $data);
    }

                $notify[] = ['error', 'Tree Not Found or You do not have Permission to view that!!'];
                return redirect()->route('user.my.tree')->withNotify($notify);



    }

}
