<?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);
        }



        $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()
    {



        $before = globalPermission('expire_before_expire_date') ? 0 : 1;

        $time = collect(json_decode(siteinfo()->settings))
            ->where('type', 'expire_time')
            ->first()->value ?? '00:00:00';

        $remove_disable_and_de_active = Client::where('clients_status', 'expired')
            ->whereNotIn('clients_status', ['deactive', 'disable']) // filter disabled/deactive clients
            ->whereRaw("
        ADDTIME(
            DATE_ADD(DATE(expire_date), INTERVAL payment_dadeline DAY),
            ?
        ) >= SUBDATE(NOW(), INTERVAL ? DAY)
    ", [$time, $before])
            ->pluck('id')
            ->toArray();


        Client::whereIn('id', $remove_disable_and_de_active)
            ->update(['clients_status' => 'active']);
    }




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


        $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)")
            ->pluck('id')
            ->toArray();

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

    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) {
                }
            }
        }
    }
}
