<?php

namespace App\Http\Controllers\Clients;

use App\Classes\MikrotikService\Mikrotik;
use App\Classes\SMS\DisableCustomerSms;
use App\Classes\MikrotikService\SyncWithMk;
use App\Classes\Notification;
use Carbon\Carbon;
use App\Models\Pop;
use App\Models\Client;
use App\Models\User_log;
use App\Models\BillGenerate;
use Illuminate\Http\Request;
use App\Services\ExpireCheck;
use App\Models\CustomerAccount;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Brian2694\Toastr\Facades\Toastr;
use App\Services\GenerateMonthlyBill;
use App\Http\Controllers\BillGenerateController;
use App\Http\Controllers\Clients\IdDisconnectController;
use App\Models\CompanyInformation;
use App\Models\Reseller;
use App\Services\RadiusClientSync;
use Exception;
use SebastianBergmann\Diff\Diff;

class IdEnableDisableController extends Controller
{

    public function enableDisable(request $request)
    {
        if ($request->activity_name == 'disable') {
            $this->idDisable($request->id, $request->details);
        } elseif ($request->activity_name == 'active') {
            $this->idEnable($request->id, $request->details);
        } elseif ($request->activity_name == 'deactive') {
            $this->idDeactive($request->id, $request->details);
        }

        return redirect()->back();
    }

    public function statusChange($type, $id)
    {
        // dd("comes");
        $client = Client::with('pop', 'pop.nas')->find($id);

        if ($type == 'deactive') {
            $status = $this->disable($client, 'Client deactive');
            // dd($status);
        } elseif ($type == 'reactive') {
            // dd("comes");
            return $this->idEnable($client->id, 'Client reactive');
            $status = 'success';
        }

        if ($status == 'success') {
            Toastr::success('Your Action ' . $type . ' the ' . $client->userid . ' is successfully', 'success');
            return response($client);
        } else {
            Toastr::error('Something is wrong.', 'error');
            return redirect()->back();
        }
    }




    public function idEnable($id, $details = 'Client enable')
    {

        // There is a clone function in Customer Re-active controller
        $client = Client::with('pop', 'pop.nas', 'packages', 'customerAccount')->find($id);


        if ($client->pop->pop_disable == 'yes') {
            Toastr::error('pop has been disabled. you can\'t enable this client.', 'error');
            return redirect()->back();
        }

        if ($client->clients_status == 'deactive') {
            if (!auth()->user()->can('customer-reactivate')) {
                Toastr::error('You are not authorized to Reactive this user', 'error');
                return response()->json([
                    'success' => false,
                    'message' => 'You are not authorized to Reactive this user'
                ]);
            }
        }
        if ($client->clients_status == 'disable') {
            if (!auth()->user()->can('id-enable')) {
                Toastr::error('You are not authorized to Enable this user', 'error');
                return response()->json([
                    'success' => false,
                    'message' => 'You are not authorized to Enable this user'
                ]);
            }
        }


        if (checkSettings('disable_limit_over_user') == 'enable') {

            $totalUpload = $client->down_bandwidth ?? 0;
            $totalDownload = $client->up_bandwidth ?? 0;
            $packageLimit = $client->packages->limite_quantity ?? 0;

            $extraLimit = $client->bandwidth_limit ?? 0;

            $totalLimit = $packageLimit + $extraLimit;

            $totalUsed = $totalUpload + $totalDownload;

            // dd($totalUsed, $totalLimit);

            if ($totalUsed > $totalLimit) {
                if (!auth()->user()->can('enable-limit-over-user')) {
                    Toastr::error('You are not authorized to Enable this user because of limit over', 'error');
                    return response()->json([
                        'success' => false,
                        'message' => 'You are not authorized to Enable this user because of limit over'
                    ]);
                }
            }
        }





        DB::beginTransaction();

        try {

            if (getBillingType() != 'day_to_day') {
                $condition = false;
                if (globalPermission('expire_before_expire_date')) {
                    $time = collect(json_decode(siteinfo()->settings))->where('type', 'expire_time')->first()->value ?? '00:00:00';
                    $expireDate = Carbon::parse($client->expire_date)->toDateString();
                    $expDateTime = Carbon::parse($expireDate . ' ' . $time)->addDay($client->payment_dadeline);
                    $condition = $expDateTime < now();
                } else {
                    $condition = Carbon::parse($client->expire_date)->addDay($client->payment_dadeline) < today();
                }

                // if (Carbon::parse($client->expire_date)->addDay($client->payment_dadeline) < today()) {
                if ($condition) {

                    $dif = Carbon::parse($client->expire_date)->diffInMonths(today());

                    if ($dif > 0 && $client->pop->bill_generate == 'yes') {


                        $new_exp = Carbon::parse(date($client->billing_cycle . '-m-Y'));
                        $newExpireDayWithCurrentDay = date('Y-m-d 00:00:00');

                        if ($client->billing_cycle > date('d')) {

                            if (getBillingType() != 'day_to_day') {
                                // $this->reactiveBillGenerate($client, $new_exp);
                                (new GenerateMonthlyBill)->generate($client);
                            }

                            $client->expire_date = Carbon::parse($newExpireDayWithCurrentDay)->subDay(1);
                            $client->billing_cycle = date('d');
                            $client->clients_status = $client->pop->experity_check == 'Yes' ? 'expired' : 'disable';
                            $client->save();
                            (new GenerateMonthlyBill)->generate($client);
                        } else {

                            $new_exp = Carbon::parse($new_exp)->addMonth();
                            $newExpireDayWithCurrentDay = date('Y-m-d 00:00:00');


                            // dd($expire_date);
                            if (getBillingType() != 'day_to_day') {
                                // $this->reactiveBillGenerate($client, $new_exp);
                            }

                            $client->expire_date = Carbon::parse($newExpireDayWithCurrentDay)->subDay(1);
                            $client->billing_cycle = date('d') - 1;
                            $client->clients_status =  $client->pop->experity_check == 'Yes' ? 'expired' : 'disable';
                            $client->save();

                            (new GenerateMonthlyBill)->generate($client);
                        }
                    } else {


                        $this->generatePreviousMonthBill($client);
                        (new GenerateMonthlyBill)->generate($client);


                        $client->clients_status = 'expired';
                        $client->save();
                    }
                } else {
                    $client->clients_status = 'active';
                    $client->save();
                }
            } else {
                if (globalPermission('expire_before_expire_date')) {
                    $time = collect(json_decode(siteinfo()->settings))->where('type', 'expire_time')->first()->value ?? '00:00:00';
                    $expireDate = Carbon::parse($client->expire_date)->toDateString();
                    $expDateTime = Carbon::parse($expireDate . ' ' . $time)->addDay($client->payment_dadeline);
                    $condition = $expDateTime < now();
                } else {
                    $condition = Carbon::parse($client->expire_date)->addDay($client->payment_dadeline) < today();
                }

                if ($condition) {
                    $client->clients_status = 'expired';
                    $client->save();
                } else {
                    $client->clients_status = 'active';
                    $client->save();
                }
            }




            User_log::create([
                'log_type' => 'id_enable',
                'user_id' => auth()->id(),
                'details' => $details,
                'client_id' => $client->id
            ]);

            if (checkAPI()) {
                $mikrotik = new SyncWithMk();
                $mikrotik->syncSingleClient($client->id);
            } else {
                (new RadiusClientSync)->syncSingleRadiusClient($client->id);
            }



            DB::commit();
            if (request()->ajax()) {
                (new Notification)->notify("..::[Customer Enable]::.. \n Customer Enabled.\n Enable By " . auth()->user()->name . " \nCustomer Username : " . $client->userid . " \nPassword : " . $client->password . "\n Enable Time : " . now());
                Toastr::success($client->userid . ' Enabled', 'success');
                return response($client);
            } else {
                (new Notification)->notify("..::[Customer Enable]::.. \n Customer Enabled.\n Enable By " . auth()->user()->name . " \nCustomer Username : " . $client->userid . " \nPassword : " . $client->password . "\n Enable Time : " . now());
                Toastr::success($client->userid . ' Enabled', 'success');
                return redirect()->back();
            }
        } catch (\Throwable $th) {
            // dd($th);
            DB::rollback();

            Toastr::error($th, 'error');
            return redirect()->back();
        }
    }


    public function generatePreviousMonthBill($client)
    {

        if (Carbon::parse($client->expire_date)->isCurrentMonth()) return false;

        $genbill = BillGenerate::where('client_id', $client->id)
            ->whereBetween('created_at', [today()->subMonth()->startOfMonth(), today()->subMonth()->endOfMonth()])
            ->where('billing_type', 'monthly')
            ->orderBy('id', 'desc')
            ->first();

        if ($genbill == null) {

            $cost = $client->packages->package_rate;
            CustomerAccount::updateCustomrAccount($client->id, $cost, 0, 0, $cost);
            $client_id_time = $client->id . '_reactive' . '_' . now();

            BillGenerate::insert([
                'description'           => 'Reactive Customer Monthly Bill ' . today()->subMonth()->firstOfMonth(),
                'bill_amount'           => $cost,
                'client_id'             => $client->id,
                'billing_type'          => 'monthly',
                'due_date'              => $client->expire_date,
                'due_amount'            => $client->customerAccount->dueAmount ?? 0,
                'parmanent_discount'    => $client->parmanent_discount,
                'package_name'          => $client->packages->package_name,
                'package_rate'          => $cost,
                'client_id_time'        => $client_id_time,
                'created_at'            => today()->subMonth()->firstOfMonth(),
                'updated_at'            => today()->subMonth()->firstOfMonth(),
            ]);
        }
    }

    public function reactiveBillGenerate($client, $exp)
    {

        $genbill = BillGenerate::where('client_id', $client->id)
            ->whereMonth('created_at', '=', date('m'))
            ->whereYear('created_at', '=', date('Y'))
            ->where('billing_type', 'monthly')
            ->orderBy('id', 'desc')
            ->first();
        // if($genbill)

        if ($genbill == null) {

            if ($client->pop->subreseller == 'yes') {
                $expire = ExpireCheck::expireNew($client->pop, $client->sub_package_id, $client->billing_cycle);
            } else {
                $expire = ExpireCheck::expireNew($client->pop, $client->packages->id, $client->billing_cycle, $client->sub_package_id);
            }

            // dd($expire);

            $cost = $expire['cost'] ?? 0;

            CustomerAccount::updateCustomrAccount($client->id, $cost, 0, 0, $cost);

            if ($cost > 0) {

                BillGenerateController::entryBillGenerate(
                    $client->id,
                    $expire['cost'],
                    'Reactive Customer Bill from ' . today() . ' to ' . $expire['exp_date'],
                    'reactive',
                    $expire['exp_date']
                );
            }
        }
    }


    public function idDisable($id, $details = 'Client disable')
    {
        // dd("comes");
        $user = Client::with('pop', 'pop.nas', 'clientsinfo')->find($id);
        $status = $this->disable($user, $details);

        if ($user->pop->pop_disable == 'yes') {
            Toastr::error('pop has been disabled. you can\'t disable this client.', 'error');
            return redirect()->back();
        }

        if ($status == 'success') {
            (new Notification)->notify("..::[Customer Disable]::.. \n Customer Disabled.\n Disable By " . auth()->user()->name . " \nCustomer Username : " . $user->userid . " \nPassword : " . $user->password . "\n Disable Time : " . now());
            Toastr::success($user->userid . ' Disabled', 'success');
            return redirect()->back();
        } else {
            Toastr::error('Something is wrong.', 'error');
            return redirect()->back();
        }
    }

    public function disable($user, $details)
    {

        if ($user->pop->pop_disable == 'yes') {
            Toastr::error('pop has been disabled. you can\'t disable this client.', 'error');
            return redirect()->back();
        }
        DB::beginTransaction();
        try {



            Client::where('id', $user->id)
                ->update([
                    'clients_status' => 'disable'
                ]);

            DB::table('radcheck')
                ->whereUsername($user->userid)
                ->update([
                    'op' => '!='
                ]);

            IdDisconnectController::disconnect($user);

            User_log::create([
                'log_type' => 'id_disable',
                'user_id' => auth()->id(),
                'details' => $details,
                'client_id' => $user->id
            ]);

            $mikrotik = new SyncWithMk();
            $mikrotik->syncSingleClient($user->id);

            DB::commit();

            if ($user->pop->user = 'yes' && $user->clientsinfo->contact_no != null) {
                $send_sms_after_disable = new DisableCustomerSms();
                $send_sms_after_disable->sendSms($user->id);
            }

            return 'success';
        } catch (\Throwable $th) {

            DB::rollback();
            return 'error';
        }
    }



    public function idDeactive($id, $details = 'Client deactive')
    {
        $user = Client::with('pop', 'pop.nas')->find($id);
        $status = $this->deactive($user, $details);

        // dd(Client::find($id));
        if ($status == 'success') {
            (new Notification)->notify("..::[Customer Deactive]::.. \n Customer Deactivated.\nDeactive By " . auth()->user()->name . " \nCustomer Username : " . $user->userid . " \nPassword : " . $user->password . "\nDeactive Time : " . now());
            Toastr::success($user->userid . ' Deactive', 'success');
            return redirect()->back();
        } else {
            Toastr::error('Something is wrong.', 'error');
            return redirect()->back();
        }
    }

    function deactive($user, $details)
    {

        if ($user->pop->pop_disable == 'yes') {
            Toastr::error('pop has been disabled. you can\'t deactive this client.', 'error');
            return redirect()->back();
        }

        DB::beginTransaction();
        try {


            $this->disableInRadius($user);


            Client::where('id', $user->id)
                ->update([
                    'clients_status' => 'deactive'
                ]);

            User_log::create([
                'log_type' => 'id_deactive',
                'user_id' => auth()->id(),
                'details' => $details,
                'client_id' => $user->id
            ]);
            if (checkAPI()) {
                if (checkSettings("close-or-deactive-without-mikrotik") != "enable") {
                    $mikrotik = new SyncWithMk();
                    $mikrotik->syncSingleClient($user->id);
                }
            }


            DB::commit();
            return 'success';
        } catch (\Throwable $th) {
            // dd($th);
            DB::rollback();
            return 'error';
        }
    }

    function enableInRadius($user, $status = true)
    {

        $count = DB::table('radcheck')->whereUsername($user->userid)->count();

        if ($count == 2) {

            DB::table('radcheck')
                ->whereUsername($user->userid)
                ->update([
                    'op' => $status == false ? '!=' : ':=',
                ]);
        } elseif ($count == 0) {
            DB::table('radcheck')->insert([
                'username'  => $user->userid,
                'attribute' => 'Cleartext-Password',
                'op'        => $status == false ? '!=' : ':=',
                'value'     => $user->password
            ]);

            DB::table('radcheck')->insert([
                'username'  => $user->userid,
                'attribute' => 'NAS-IP-Address',
                'op'        => $status == false ? '!=' : ':=',
                'value'     => $user->pop->nas->nasname
            ]);
        } else {
            DB::table('radcheck')
                ->whereUsername($user->userid)
                ->delete();

            DB::table('radcheck')->insert([
                'username'  => $user->userid,
                'attribute' => 'Cleartext-Password',
                'op'        => $status == false ? '!=' : ':=',
                'value'     => $user->password
            ]);

            DB::table('radcheck')->insert([
                'username'  => $user->userid,
                'attribute' => 'NAS-IP-Address',
                'op'        => $status == false ? '!=' : ':=',
                'value'     => $user->pop->nas->nasname
            ]);
        }
        $user_reduser_group = DB::table('radusergroup')->where('username', $user->userid)->first();

        if ($user_reduser_group == null) {

            DB::table('radusergroup')->insert([
                'username' => $user->userid,
                'groupname' => $user->packages->id,
                'priority' => 1
            ]);
        }
    }

    function disableInRadius($user)
    {
        DB::table('radcheck')
            ->whereUsername($user->userid)
            ->delete();

        IdDisconnectController::disconnect($user);
    }

    public function activeUserInMikrotik($username)
    {
        $mkIp = $username->pop->nas->nasname;
        $mkUser = $username->pop->nas->mikrotick_user;
        $mkPass = $username->pop->nas->mikrotick_user_password;
        $mkPort = $username->pop->nas->mikrotick_port;
        $mk = new Mikrotik($mkIp, $mkUser, $mkPass, $mkPort ? (int)$mkPort : 8728);
        $mk->enableSecret($username->userid);
    }

    public function disableAnddisconectInMikrotik($username)
    {
        $mkIp = $username->pop->nas->nasname;
        $mkUser = $username->pop->nas->mikrotick_user;
        $mkPass = $username->pop->nas->mikrotick_user_password;
        $mkPort = $username->pop->nas->mikrotick_port;
        $mk = new Mikrotik($mkIp, $mkUser, $mkPass, $mkPort ? (int)$mkPort : 8728);
        try {
            $mk->disconnectSecret($username->userid);
        } catch (\Exception $err) {
        }

        $mk->disableSecret($username->userid);
    }

    public function idEnaleDisableReport()
    {
        $start = today()->firstOfMonth();
        $end = today();
        return view('clients.activedeactivereport.index', [
            'page_title' => 'Active Deactive Report',
            'start'             => $start,
            'end'               => $end,
            'reseller'          => Reseller::resellerList()->get(),
        ]);
    }

    public function idEnaleDisableResult(Request $request)
    {
        $from = $request->from_date == '' ? today() : Carbon::parse($request->from_date)->format('Y-m-d 00:00:00');
        $to   = $request->to_date == '' ? today() : Carbon::parse($request->to_date)->format('Y-m-d 23:59:59');
        // dd($request->type);

        if ($request->type == '') {
            $query = User_log::with('client', 'user')
                ->whereBetween('created_at', [$from, $to])
                ->orderBy('id', 'desc')
                ->groupBy('client_id')
                ->latest('created_at');
        } else {
            $query = User_log::with('client', 'user')
                ->where('details', $request->type)
                ->whereBetween('created_at', [$from, $to])
                ->orderBy('id', 'desc')
                ->groupBy('client_id')
                ->latest('created_at');
        }

        $query->whereHas('client', function ($query) use ($request) {
            if ($request->pop_id != '') {
                $query->whereHas('pop', function ($query) use ($request) {
                    $query->where('id', $request->pop_id);
                });
            } elseif ($request->reseller_id != '') {
                $query->whereHas('pop', function ($query) use ($request) {
                    $query->where('reseller_id', $request->reseller_id);
                });
            }
        });

        // $query = User_log::with('client', 'user')
        //     ->where('details', $request->type)
        //     ->whereBetween('created_at', [$from, $to])
        //     ->orderBy('id', 'desc')
        //     ->groupBy('client_id')
        //     ->latest('created_at');

        // if ($request->pop_id != '') {
        //     $query->whereHas('client.pop', function ($query) use ($request) {
        //         $query->where('id', $request->pop_id);
        //     });
        // } else {
        //     if ($request->reseller_id != '') {
        //         $query->whereHas('client.pop', function ($query) use ($request) {
        //             $query->where('reseller_id', $request->reseller_id);
        //         });
        //     }
        // }

        $data = $query->get();
        // dd($data);

        return view('clients.activedeactivereport.result', [
            'data' => $data,
        ]);
    }
}
