<?php

namespace App\Http\Controllers\Customer;

use App\Classes\customer\clientLiveSpeed;
use App\Classes\MikrotikService\SyncWithMk;
use App\Http\Controllers\BillGenerateController;
use Carbon\Carbon;
use App\Models\Token;
use App\Models\Client;
use App\Models\Packages;
use App\Models\Billpayment;
use App\Models\BillGenerate;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Models\CustomerAccount;
use App\Models\CompanyInformation;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Jobs\BillGenerateJob;
use App\Jobs\BillGenerateUpdateJob;
use App\Models\Clientsinfo;
use App\Models\Pop;
use App\Models\ReselleBalanceLogReport;
use App\Models\Reseller;
use App\Models\SubPackage;
use App\Models\SubResellerBalanceLogReport;
use App\Services\RadiusClientSync;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
use phpDocumentor\Reflection\Location;

class CustomerFrontController extends Controller
{


    public function customer_login()
    {


        if ($this->checkCustomerAuth()) {
            return redirect('customerDashboard');
        }

        return view('Customer.customer-login', [
            'page_titel' => 'Customer Login'
        ]);
    }

    public function checkCustomerAuth()
    {

        $token = Cookie::get('customer_token');
        $username = Cookie::get('customer_username');

        if ($token && $username) {
            $customer_info = Client::with('clientsinfo', 'pop')->whereUserid($username)->where('login_token', $token)->first();

            if ($customer_info) {
                $info = array(
                    'id' => $customer_info->id,
                    'login_status' => 'success'
                );

                session(['customer_info' => json_encode($info)]);

                return true;
            }
        }
    }

    public function logout(Request $request)
    {
        Cookie::queue(Cookie::forget('customer_token'));
        Cookie::queue(Cookie::forget('customer_username'));
        $customer_info =  $request->session()->get('customer_info');
        if (!empty($customer_info)) {
            $request->session()->forget('customer_info');


            return redirect()->route('customer_login');
        }
    }

    public function customer_login_check(Request $request)
    {
        $customer = Client::whereUserid($request->username)->first();

        if (checksettings('customer-login-by-cid-mobileNumber') == 'disable' && checkSettings('login_customer_code_and_password') == 'disable') {
            if ($customer == null) {
                return redirect()->back()->with('error_message', 'Sorry User does not exist');
            }

            if ($customer->client_approval == "pending") {
                return redirect()->back()->with('error_message', 'Sorry User not exist');
            }
        }

        if (checkSettings('customer-login-by-cid-mobileNumber') == 'enable') {
            $c_info = Clientsinfo::where('client_id', $request->id)->where('contact_no', $request->mobileNumber)->first();
            if ($c_info == null) {
                return redirect()->back()->with('error_message', 'Sorry User not exist');
            }
            $customer_info = Client::with('clientsinfo', 'pop')->where('id', $c_info->client_id)->first();
        } elseif (checkSettings('login_customer_code_and_password') == 'enable') {

            $c_info = Client::where('customer_code', $request->code)->where('password', $request->password)->first();

            if ($c_info == null) {
                return redirect()->back()->with('error_message', 'Sorry User not exist');
            }
            $customer_info = Client::with('clientsinfo', 'pop')->where('id', $c_info->id)->first();
        } else {
            $customer_info = Client::with('clientsinfo', 'pop')->whereUserid($request->username)->wherePassword($request->password)->first();
        }
        // dd($customer_info);

        if (!empty($customer_info)) {

            $token = bcrypt(now()->timestamp) . bcrypt(uniqid());

            if ($customer_info->pop->bill_generate != 'yes' && checkSettings('ResellerClientOnlineRecharge') == 'disable') {
                return redirect()->route('customer_login')->with('error_message', 'Sorry User Does not exist');
            }

            $info = array(
                'id' => $customer_info->id,
                'login_status' => 'success'
            );

            $request->session()->put('customer_info', json_encode($info));

            $customer_info->login_token = $token;
            $customer_info->save();
            $this->setCookie($token, $customer_info->userid);
        } else {

            return redirect()->back()->with('error_message', 'Sorry User not exist');
        }

        return redirect()->route('customerDashboard');
    }


    public function setCookie($token, $username)
    {
        Cookie::queue('customer_token', $token, 60 * 60 * 24 * 30);
        Cookie::queue('customer_username', $username, 60 * 60 * 24 * 30);
    }

    public function bkashError(Request $request)
    {
        if ($request->session()->has('customer_info')) {

            // $logininfo =  json_decode($request->session()->get('customer_info'));

            $details['userinfo'] = CustomerFrontController::getinfo($request);



            return view('Customer.bkashCanceled', [
                'page_title' => 'Payment Canceled',
                'details'    => $details,
                'type' => session()->get('bkashErrorMessage')
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }


    public function bkashPaymentCanceled(Request $request)
    {
        if ($request->session()->has('customer_info')) {

            // $logininfo =  json_decode($request->session()->get('customer_info'));

            $details['userinfo'] = CustomerFrontController::getinfo($request);



            return view('Customer.bkashCanceled', [
                'page_title' => 'Payment Canceled',
                'details'    => $details,
                'type' => 'Payment Canceled'
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }
    public function bkashPaymentbkashFailure(Request $request)
    {
        if ($request->session()->has('customer_info')) {

            // $logininfo =  json_decode($request->session()->get('customer_info'));

            $details['userinfo'] = CustomerFrontController::getinfo($request);



            return view('Customer.bkashCanceled', [
                'page_title' => 'Payment Canceled',
                'details'    => $details,
                'type' => 'Payment Failed'
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }

    public function insufficientBalance(Request $request)
    {
        if ($request->session()->has('customer_info')) {

            // $logininfo =  json_decode($request->session()->get('customer_info'));

            $details['userinfo'] = CustomerFrontController::getinfo($request);



            return view('Customer.bkashCanceled', [
                'page_title' => 'Insufficient Balance',
                'details'    => $details,
                'type' => 'Insufficient Balance'
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }

    public function customerDashboard(Request $request)
    {

        if ($request->session()->has('customer_info')) {

            // $logininfo =  json_decode($request->session()->get('customer_info'));

            $customer_info =  CustomerFrontController::getinfo($request);
            if ($customer_info != null) {
                $id = $customer_info->id;
                $details['userinfo'] =  $customer_info;
                $details['paymentinfo'] = Billpayment::whereClient_id($id)->get();
                $details['billinginfo'] = BillGenerate::whereClient_id($id)->get();
                $details['package'] = Packages::where('id', $customer_info->package_id)->first();
                $details['account'] = CustomerAccount::where('client_id', $id)->first();
                // $details['expire_date'] = CustomerAccount::where('client_id', $id)->first();

                $username = $details['userinfo']->userid;
                $pendingTokenCount = Token::where('createByClient', $username)
                    ->where('status', 'Active')
                    ->get();

                $tokenListCount = Token::where('createByClient', $username)->get();

                $speed = (new clientLiveSpeed)->clientLiveSpeedShow($id);

                $re_active_btn_condition = $customer_info->clients_status == "deactive" && Carbon::parse($customer_info->expire_date)->addMonth(1)->format('Y-m-d') < today()->format('Y-m-d') && globalPermission('customerPortalReactive');

                $currentPackageRate = $details['package']->package_rate;

                if ($customer_info->pop->subreseller == "yes") {
                    $allPackages = $customer_info->pop->sub_package_list;
                    $split_packages = explode(',', $allPackages);

                    if (globalPermission('client_can_change_only_higher_package')) {
                        $packages = SubPackage::whereIn('id', $split_packages)
                            ->where('id', '!=', $customer_info->sub_package_id)
                            ->where('rate', '>', $currentPackageRate)
                            ->get();
                    } else {

                        $packages = SubPackage::whereIn('id', $split_packages)
                            ->where('id', '!=', $customer_info->sub_package_id)
                            ->get();
                    }
                } else {
                    $reseller = Reseller::find($customer_info->pop->reseller_id);
                    $allPackages = $reseller->package_list;
                    $split_packages = explode(',', $allPackages);

                    if (globalPermission('client_can_change_only_higher_package')) {
                        $packages = Packages::whereIn('id', $split_packages)
                            ->where('id', '!=', $customer_info->package_id)
                            ->where('package_rate', '>', $currentPackageRate)
                            ->get();
                    } else {
                        $packages = Packages::whereIn('id', $split_packages)
                            ->where('id', '!=', $customer_info->package_id)
                            ->get();
                    }
                }

                $days_left_to_expire = Carbon::now()
                    ->startOfDay()
                    ->diffInDays(Carbon::parse($customer_info->expire_date)->startOfDay(), false);

                if (checkSettings('reduce-one-day-in-package-change') == 'enable') {
                    $days_left_to_expire = $days_left_to_expire + 0;
                } else {
                    $days_left_to_expire = $days_left_to_expire + 1;
                }

                $changePackagePermission = globalPermission('package_change_from_customer_portal');
                $companyInfo = CompanyInformation::latest()->first();

                return view('Customer.customer-dashboard', [
                    'page_title' => 'Dashboard',
                    'details'    => $details,
                    'pendingTokenCount' => $pendingTokenCount,
                    'tokenListCount' => $tokenListCount,

                    'error' => $speed['error'],
                    'bandwidthUsage' => $speed['bandwidthUsage'],
                    "lastLogoutTime" => $speed['lastLogoutTime'],
                    'list' => $speed['data'],
                    'pop' => $speed['pop'],
                    'user_id' => $speed['user_id'],
                    're_active_btn_condition' => $re_active_btn_condition,
                    'packages' => $packages,
                    'days_left_to_expire' => $days_left_to_expire,
                    'changePackagePermission' => $changePackagePermission,
                    'companyInfo' => $companyInfo
                ]);
            }
        } else {
            return redirect()->route('customer_login');
        }
    }


    public function customer_account(Request $request)
    {


        $customer_info =  CustomerFrontController::getinfo($request);
        if ($customer_info != null) {
            $id = $customer_info->id;
            $details['userinfo'] =  $customer_info;
            $details['paymentinfo'] = Billpayment::whereClient_id($id)->get();
            $details['billinginfo'] = BillGenerate::whereClient_id($id)->get();
            $details['package'] = Packages::where('id', $customer_info->package_id)->first();
            $details['account'] = CustomerAccount::where('client_id', $id)->first();


            return view('Customer.customer_account', [
                'page_title' => 'Account',
                'details' => $details
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }


    public function payment_history(Request $request)
    {

        $customer_info =  CustomerFrontController::getinfo($request);
        if ($customer_info != null) {

            $id = $customer_info->id;
            $details['userinfo'] =  $customer_info;
            $details['paymentinfo'] = Billpayment::where('paid_amount', '>', 0)->whereClient_id($id)->orderBy('id', 'desc')->paginate(15);

            // dd($details);

            return view('Customer.payment_history', [
                'page_title' => 'Payment History',
                'details' => $details
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }

    public function singleInvoice($id)
    {
        $payments = Billpayment::find($id);
        // dd($payments);


        $cid = Client::with('pop', 'packages')->where('id', $payments->client_id)->first();
        // dd($cid);
        $customer_info = Clientsinfo::where('client_id', $payments->client_id)->first();
        $company_info = siteinfo();

        $bill = BillGenerate::find($id);


        $total_paid = $payments->paid_amount;
        $total_discount = $payments->discount_amount;
        // $previous_due = $bill->due_amount > 0 ? abs($bill->bill_amount - $bill->due_amount) : 0;
        // $total_amount = $bill->bill_amount + $previous_due;
        // $balance_due = $total_amount - ($total_paid + $total_discount);
        // dd($total_discount);

        $data = [
            'company_info' => $company_info,
            'cid' => $cid,
            'customer_info' => $customer_info,
            'bill' => $bill,
            'payments' => $payments,
            // 'previous_due' => $previous_due,
            // 'balance_due' => $balance_due,
            'total_paid' => $total_paid,
            'id' => $id,
            'total_discount' => $total_discount
        ];

        return view('Customer.singleInvoice', $data);
    }


    public function payment(Request $request)
    {



        $customer_info =  CustomerFrontController::getinfo($request);


        if ($customer_info != null) {

            if (globalPermission('blockPaymentDeActiveNoDue')) {

                $client = Client::with('customerAccount')->find($customer_info->id);
                $dueAmount = getDueAmount($client);

                if ($client->clients_status  == "deactive" &&  $dueAmount <= 0) {

                    Toastr::error('Payment is blocked for deactivated customers. Please contact support.', 'Error');
                    return redirect()->route('customerDashboard');
                }
            }

            $id                     = $customer_info->id;
            $details['userinfo']    =  $customer_info;
            $details['paymentinfo'] = Billpayment::whereClient_id($id)->get();
            $details['billinginfo'] = BillGenerate::whereClient_id($id)->get();
            $details['package']     = Packages::where('id', $customer_info->package_id)->first();
            $details['account']     = CustomerAccount::firstOrCreate(['client_id' => $id]);



            $bill_amount = 0;

            if ($details['account']->dueAmount > 0) {
                $bill_amount = $details['account']->dueAmount;
            } else {
                $bill_amount = $details['package']->package_rate + $details['account']->dueAmount - $details['userinfo']->parmanent_discount;
            }


            if ($request->status) {
                if ($request->status == 'FAILED') {
                    Toastr::success('Payment Done!!', 'success');
                }
            }

            $payment_btns = collect(json_decode(siteinfo()->payment_button));


            return view('Customer.customer_payment', [
                'page_title' => 'Pay Now',
                'details' => $details,
                'buttons' => $payment_btns,
                'bill_amount' => $bill_amount
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }

    static function getinfo($request)
    {
        $logininfo =  json_decode($request->session()->get('customer_info'));
        if ($logininfo == null) {
            return null;
        } else {
            return  Client::with('clientsinfo', 'pop')->whereId($logininfo->id)->first();
        }
    }

    static function getClientInfo($request)
    {
        // if (Auth::check()) {
        if ($request->session()->has('customer_info')) {
            $logininfo =  json_decode($request->session()->get('customer_info'));
            if ($logininfo == null) {
                return null;
            } else {
                return [
                    'login_check' => 'true',
                    'clientlist' => Client::with('clientsinfo', 'pop')->whereId($logininfo->id)->first()
                ];
            }
        } else {
            return [
                'login_check' => 'false',
                'clientlist' => Client::with('clientsinfo', 'pop')->whereId($request->customerid)->first()
            ];
        }
    }

    public function payment_process(Request $request)
    {
        # code...
    }

    public function contact(Request $request)
    {
        $details['userinfo'] = CustomerFrontController::getinfo($request);

        $company = DB::table('company_information')->get();

        if (!$details['userinfo']) {
            return redirect()->route('customer_login');
        }
        return view('Customer.contact', [
            'page_title' => 'Contact',
            'company'   => $company,
            'details'    => $details,
            'type' => 'contact'
        ]);
    }

    public function customerPackages(Request $request)
    {
        $customer_info =  CustomerFrontController::getinfo($request);

        if ($customer_info != null) {
            $id = $customer_info->id;
            $details['userinfo'] =  $customer_info;
            $details['paymentinfo'] = Billpayment::whereClient_id($id)->get();
            $details['billinginfo'] = BillGenerate::whereClient_id($id)->get();
            $details['package'] = Packages::where('id', $customer_info->package_id)->first();
            $details['account'] = CustomerAccount::where('client_id', $id)->first();



            return view('Customer.customer-package', [
                'page_title' => 'packages',
                'details' => $details
            ]);
        } else {
            return redirect()->route('customer_login');
        }
    }

    public function customerChangePackage(Request $request)
    {
        $client = CustomerFrontController::getinfo($request);
        if (!$client) {
            return response()->json(['status' => 'error', 'message' => 'Unauthorized'], Response::HTTP_UNAUTHORIZED);
        }

        $single_client = Client::with('customerAccount')->find($client->id);

        $balance = 0;
        if ($single_client->customerAccount->dueAmount >= 0) {
            $balance = 0;
        } else {
            $balance = abs($single_client->customerAccount->dueAmount);
        }

        $cost = 0;
        $subPackageStatus = false;

        if ($client->pop->subreseller == "yes") {
            $subPackage = SubPackage::with('package')->find($request->new_package);
            $packageCost = $subPackage->package->package_rate;
            $subPackageStatus = true;
            $oldSubPackage = SubPackage::find($single_client->sub_package_id)->name;
            $oldPackage = Packages::find($single_client->package_id)->package_name;

            $oldPackageRate = $oldPackage->package_rate;
        } else {
            $package = Packages::find($request->new_package);
            $packageCost = $package->package_rate;
            $oldPackage = Packages::find($single_client->package_id)->package_name;

            $oldPackageRate = Packages::find($single_client->package_id)->package_rate;
        }

        $days_left_to_expire = Carbon::now()
            ->startOfDay()
            ->diffInDays(Carbon::parse($single_client->expire_date)->startOfDay(), false);

        if (checkSettings('reduce-one-day-in-package-change') == 'enable') {
            $days_left_to_expire = $days_left_to_expire + 0;
        } else {
            $days_left_to_expire = $days_left_to_expire + 1;
        }

        if ($days_left_to_expire <= 0) {
            $cost = 0;
        } else {

            if ($oldPackageRate >= $packageCost) {
                $cost = 0;
            } else {
                $cost = ($packageCost / 30) * $days_left_to_expire;
            }
        }



        $cost = number_format($cost);

        if ($balance < $cost) {
            return response()->json(['status' => 'error', 'message' => 'Insufficient balance to change package.'], Response::HTTP_BAD_REQUEST);
        }



        try {
            DB::beginTransaction();

            if ($subPackageStatus) {
                $single_client->package_id = $subPackage->package_id;
                $single_client->sub_package_id = $subPackage->id;
            } else {
                $single_client->package_id = $package->id;
            }
            $single_client->save();



            $note = 'Package changed cost from client portal.';

            $billGenerate =  BillGenerateController::entryBillGenerate($single_client->id, number_format($cost), $note, "package_change", $single_client->expire_date);

            // reseller balance log create with zero price
            if ($subPackageStatus) {

                $resellerAction = "Package Changed. From Package: " . $oldPackage .
                    " To : " . $subPackage->package->package_name .
                    " . Expire: " . $client->expire_date .
                    " For " . $days_left_to_expire .
                    " days cost BDT " . $cost .
                    ". Cusomer has advanced balance so not deducted.";


                $subResellerAction = "Package Changed from client portal. From Package: " . $oldSubPackage .
                    " To : " . $subPackage->name .
                    " . Expire: " . $client->expire_date .
                    " For " . $days_left_to_expire .
                    " days cost BDT " . $cost .
                    ". Cusomer has advanced balance so no deduct.";
            } else {
                $resellerAction = "Package Changed. From Package: " . $oldPackage .
                    " To : " . $package->package_name .
                    " . Expire: " . $client->expire_date .
                    " For " . $days_left_to_expire .
                    " days cost BDT " . $cost .
                    ". Cusomer has advanced balance so not deducted.";
            }


            $pop = Pop::with('reseller')->find($client->pop_id);

            $resellerBalanceLogRepoer = ReselleBalanceLogReport::create([
                'reseller_id' => $client->pop->reseller_id,
                'client_id'   => $client->id,
                'action'      => $resellerAction,
                'amount'      => 0,
                'remarks'     => 'Created BY Client ' . $client->userid,
                'uniqueId'    => createUUID(),
                'pop_id'       => $client->pop_id,
                'commission_amount' => 0,
                'reseller_commission_percentage' => $pop->reseller->commission_percentage,
                'pop_commission_percentage' => $pop->commission_percentage,
            ]);

            // if sub reseller then add log with zero price
            if ($subPackageStatus) {


                SubResellerBalanceLogReport::create(
                    [
                        'reseller_id'       => $client->pop->reseller_id,
                        'sub_reseller_id'   => $client->pop_id,
                        'client_id'         => $client->id,
                        'action'            => $subResellerAction,
                        'amount'            => 0,
                        'remarks'           => 'Created BY Client ' . $client->userid,
                        'reseller_cost' => 0,
                        'commission_amount' => 0,
                        'reseller_balance_log_id' => $resellerBalanceLogRepoer->id,
                    ]
                );
            }

            // customer balance deduct from account
            CustomerAccount::updateCustomrAccount($client->id, $cost, 0, 0, $cost);

            try {
                if (!globalPermission('payment-bill-by-bill')) {
                    BillGenerateUpdateJob::dispatch($client->id);
                }
            } catch (\Exception $e) {
            }

            if(checkAPI()){
                try {
                     $mk = new SyncWithMk();
                     $mk->syncSingleClient($client->id);
                } catch (\Exception $e) {
                }
            }else{
                (new RadiusClientSync)->syncSingleRadiusClient($client->id);
            }

            DB::commit();

            return response()->json(['status' => 'success', 'message' => 'Package changed successfully.'], Response::HTTP_OK);
        } catch (\Exception $e) {

            DB::rollBack();
            return response()->json(['status' => 'error', 'message' => 'An error occurred while changing the package.'], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
}
