<?php

namespace App\Http\Controllers;

use App\Classes\Accounting\Accounting;
use App\Classes\MikrotikService\Mikrotik;
use App\Classes\MikrotikService\SyncWithMk;
use App\Models\Pop;
use App\Models\Client;
use Illuminate\Http\Request;
use App\Jobs\BillGenerateJob;
use App\Jobs\ApiClientExpireJob;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\SessionRefreshController;
use App\Http\Controllers\Clients\IdEnableDisableController;
use App\Jobs\ExpireRadiusUserJob;
use App\Services\ExpirationService;
use App\Services\RadiusClientSync;
use Exception;
use Illuminate\Support\Facades\Log;
use Pusher\Pusher;

class ExpireCheckController extends Controller
{

    static function checkAdvanced()
    {

        $bill_month = null;

        Client::with('packages')
            ->select('clients.id', 'clients.expire_date', 'clients.package_id', 'clients.parmanent_discount', 'customer_accounts.dueAmount', 'packages.package_rate')
            ->join('customer_accounts', 'clients.id', '=', 'customer_accounts.client_id')
            ->join('packages', 'clients.package_id', '=', 'packages.id')
            ->where('customer_accounts.dueAmount', '<', 0)
            ->where('clients.clients_status', '!=', 'deactive')
            ->whereRaw('packages.package_rate <= ABS(customer_accounts.dueAmount - clients.parmanent_discount)')
            ->orderBy('clients.id', 'asc')
            ->chunk(100, function ($clients) use ($bill_month) {
                // dd($clients->count());
                BillGenerateJob::dispatch($clients, $bill_month);
            });
    }

    static function check($time = '00:00:00')
    {

        if(globalPermission('expire_before_expire_date')){
            $before = 0;
        } else{
            $before = 1;
        }
        Log::error("start expire");

        DB::table('clients')
            ->where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->whereRaw("ADDTIME(DATE_ADD(expire_date,INTERVAL payment_dadeline DAY), '$time') < SUBDATE(NOW(),INTERVAL '$before' DAY)")
            ->update([
                'clients_status' => 'expired'
            ]);





        DB::table('radcheck')
            // ->select('username')
            ->whereRaw("username IN (SELECT userid FROM clients WHERE ADDTIME(DATE_ADD(expire_date,INTERVAL payment_dadeline DAY), '$time') < SUBDATE(NOW(),INTERVAL '$before' DAY) AND experity_check = 'Yes' AND pop_id IN (SELECT id FROM pops where experity_check = 'No'))")
            // ->get();
            ->update([
                'op' => globalPermission('RadiusExpiration') ? ':=' : '!=',
            ]);

        $lists = DB::table('radcheck')
            ->select('username')
            ->whereRaw("username IN (SELECT userid FROM clients WHERE ADDTIME(DATE_ADD(expire_date,INTERVAL payment_dadeline DAY), '$time') < SUBDATE(NOW(),INTERVAL '$before' DAY) AND experity_check = 'Yes' AND pop_id IN (SELECT id FROM pops where experity_check = 'No'))")
            ->distinct()
            ->pluck('username')
            ->toArray();

        $dlist = DB::table('clients')->where('clients_status', 'deactive')->orWhere('clients_status', 'disable')->pluck('userid')->toArray();

        DB::table('radcheck')
            ->whereIn('username', $dlist)
            ->update([
                'op' => globalPermission('RadiusExpiration') ? ':=' : '!=',
            ]);

        if(globalPermission('RadiusExpiration')){
           (new ExpirationService())->setExpireTimeClients($dlist);
           (new ExpirationService())->setExpireTimeClients($lists);
        }

        $info = json_encode($lists);
        DB::table('check_expire')->insert([
            'info' => $info
        ]);

        $count = 0;
        $expire_user = [];

        $accounting = new Accounting();
        foreach ($lists as $username) {

            try {
                $accounting->singleUserDisconnect($username);
            } catch (\Exception $e) {

            }
        }

        foreach ($dlist as $username) {
            try {

                $accounting->singleUserDisconnect($username);
            } catch (\Exception $e) {

            }
        }



    }


    static function check_backup()
    {





        $exception_pop_list = Pop::where('experity_check', 'Yes')->pluck('id')->toArray();

        $lists = Client::whereIn('pop_id', $exception_pop_list)
            ->where('expire_date', '<', today())
            ->where(function ($q) {
                $q->where('clients_status', '!=', 'deactive')
                    ->where('clients_status', '!=', 'disable');
            })
            ->pluck('userid')
            ->toArray();


        DB::table('clients')
            ->whereIn('userid', $lists)
            ->update([
                'clients_status' => 'expired'
            ]);


        $pop_list = Pop::where('experity_check', 'No')->pluck('id')->toArray();

        Client::where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->where('expire_date', '<', today())
            ->whereIn('userid', $pop_list)
            ->update(['clients_status' => 'expired']);


        $lists = Client::whereIn('pop_id', $pop_list)
            ->where('expire_date', '<', today())
            ->where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->pluck('userid')
            ->toArray();


        $info = json_encode($lists);

        DB::table('clients')
            ->whereIn('userid', $lists)
            ->update([
                'clients_status' => 'expired'
            ]);

        DB::table('radcheck')
            ->whereIn('username', $lists)
            ->update([
                'op' => '!='
            ]);

        foreach ($lists as $l) {
            SessionRefreshController::userDisconnectProcess($l);
        }

        DB::table('check_expire')->insert([
            'info' => $info
        ]);



        // disable and deactive customer fix
        $lists = Client::where('clients_status', 'deactive')
            ->where('clients_status', 'disable')
            ->pluck('userid')
            ->toArray();


        DB::table('radcheck')
            ->whereIn('username', $lists)
            ->update([
                'op' => '!='
            ]);

        foreach ($lists as $l) {
            SessionRefreshController::userDisconnectProcess($l);
        }

        DB::table('check_expire')->insert([
            'info' => $info
        ]);


    }




    static public function recheck()
    {
        $lists = Client::with('pop', 'pop.nas');

        if(globalPermission('expire_before_expire_date')){
            $lists->whereRaw('DATE_ADD(expire_date,INTERVAL payment_dadeline DAY) > CURDATE()');
        } else{
            $lists->whereRaw('DATE_ADD(expire_date,INTERVAL payment_dadeline DAY) >= CURDATE()');
        }

        $lists->where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->get();

        if (checkAPI()) {
            $list_array = $lists->pluck('userid')->toArray();
            DB::table('clients')
                ->whereIn('userid', $list_array)
                ->update([
                    'clients_status' => 'active'
                ]);

            // foreach ($lists as $l) {
            //     if ($l->pop) {

            //         (new IdEnableDisableController)->activeUserInMikrotik($l);
            //     }
            // }
        } else {
            $lists = $lists->pluck('userid')->toArray();
            DB::table('clients')
                ->whereIn('userid', $lists)
                ->update([
                    'clients_status' => 'active'
                ]);

            DB::table('radcheck')
                ->whereIn('username', $lists)
                ->update([
                    'op' => ':='
                ]);
        }
    }




    static public function api_expair_check($time)
    {
        if(globalPermission('expire_before_expire_date')){
            $before = 0;
        } else{
            $before = 1;
        }

        $expire_customers =   DB::table('clients')
            ->whereNull('deleted_at')
            ->where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->whereRaw("ADDTIME(DATE_ADD(expire_date,INTERVAL payment_dadeline DAY), '$time') < SUBDATE(NOW(),INTERVAL '$before' DAY)")
            ->whereRaw("pop_id IN (SELECT id FROM pops where experity_check = 'No')")
            ->select('id', 'userid', 'pop_id')
            ->get()
            ->groupBy('pop_id')
            ->toArray();

        $expire_customers_id = DB::table('clients')
            ->whereNull('deleted_at')
            ->where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->whereRaw("ADDTIME(DATE_ADD(DATE(expire_date),INTERVAL payment_dadeline DAY), '$time') < SUBDATE(NOW(),INTERVAL '$before' DAY)")
            ->whereRaw("pop_id IN (SELECT id FROM pops where experity_check = 'No')")
            ->pluck('id')
            ->toArray();

        DB::beginTransaction();
        try {
            Client::whereIn('id', $expire_customers_id)->update(["clients_status" => "expired"]);
            DB::commit();
        } catch (Exception $err) {
            DB::rollBack();
        }

        // deprecated: gonna delete this shortly.
        // foreach ($expire_customers as $expire) {
        //     $new_list = array_chunk($expire, 100);
        //     foreach ($new_list as $l) {
        //         ApiClientExpireJob::dispatch($l);
        //     }
        // }

        $info = json_encode($expire_customers);
        DB::table('check_expire')->insert([
            'info' => $info
        ]);

        DB::table('clients')
            ->whereNull('deleted_at')
            ->where('clients_status', '!=', 'deactive')
            ->where('clients_status', '!=', 'disable')
            ->whereRaw("ADDTIME(DATE_ADD(expire_date,INTERVAL payment_dadeline DAY), '$time') < SUBDATE(NOW(),INTERVAL '$before' DAY)")
            ->whereRaw("pop_id IN (SELECT id FROM pops where experity_check = 'Yes')")
            ->update([
                'clients_status' => 'expired'
            ]);
    }

    static public function disconnectExpireButOnline($time)
    {
        $pop = Pop::where('experity_check', '!=', 'Yes')->get();
        $clients = Client::where('clients_status','expired')->whereIn('pop_id', $pop->pluck('id'))->pluck('userid')->toArray();

        $accounting = new Accounting();

        $online_users_who_expire = $accounting->totalOnlineUserWithInformation($clients);


        foreach ($online_users_who_expire as $key => $value) {

            $client = Client::where('userid',$value->username,['id','expire_date','payment_dadeline'])->first();
            $check_expire = (new SyncWithMk())->isExpire($client);

            if($check_expire){
                if(globalPermission('RadiusExpiration')){
                    (new ExpirationService())->syncExpiration($value->username);
                }

                try{
                    (new RadiusClientSync())->syncSingleRadiusClient($client->id);
                    $accounting->singleUserDisconnect($value->username);
                    $accounting->setAcctStopTimeNow($value->username);

                }catch(\Exception $e){

                }
            }
        }
    }


}
