<?php

namespace App\Http\Controllers\Billing;

use App\Classes\BillgenerateUpdate;
use App\Classes\EditLogHistory;
use App\Classes\MikrotikService\Mikrotik;
use App\Classes\MikrotikService\SyncWithMk;
use App\Classes\Notification;
use App\Http\Controllers\ClientController;
use App\Models\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Jobs\BatchExpChange;
use App\Jobs\BillGenerateUpdateJob;
use App\Models\BillGenerate;
use App\Models\CustomerBillingCycleInfo;
use App\Services\BillingCycleChange;
use Brian2694\Toastr\Facades\Toastr;
use Brian2694\Toastr\Toastr as ToastrToastr;
use Illuminate\Support\Facades\Auth;

class ClientBillingCycleChangeController extends Controller
{



    public function billingCycleChange()
    {
        $confday = config('app.billing_cycle');

        return view('clients.billCycleChange', [
            'page_title' => 'Bill Cycle Change',
            'confday' => $confday
        ]);
    }

    public function batchUserBillingCycleChange(Request $request)
    {
        if($request->change_without_cost == 'yes'){
            $auth_user = Auth::user()->id;
            $exp_date = $request->expire_date;
            $users = Client::with('pop.nas', 'packages', 'subpack', 'pop.reseller', 'customerAccount', "clientsinfo")
                ->whereIn('id', $request->id)
                ->chunk(100, function ($clients) use($exp_date, $auth_user) {
                    BatchExpChange::dispatch($clients, $exp_date, $auth_user);
                });
            Toastr::success('Request is in processing Queue', 'success');
        } else{
            if (empty($request->billCycle)) {
                Toastr::error('Please Select a Billing Cycle Date', 'error');
                return redirect()->back();
            }
            $users = Client::with('pop.nas', 'packages', 'subpack', 'pop.reseller', 'customerAccount', "clientsinfo")->whereIn('id', $request->id)->get();
            $processedUserIds = [];
            $uniqueId = $request->uuid;
            foreach ($users as $user) {
                if (in_array($user->id, $processedUserIds)) {
                    Toastr::error('User ID ' . $user->id . ' has already been processed', 'error');
                    continue;
                }
                if (checkSettings('expire_billing_change_today_from_billing_date') != 'enable') {
                    if (now()->subMonth() > $user->expire_date) {
                        Toastr::error('Customer Expired or Deactivated or expired one month older', 'error');
                        continue;
                    }
                }

                if ($request->billCycle == $user->billing_cycle) {
                    Toastr::error('Select a Different Billing Cycle Date', 'error');
                    continue;
                }

                $old_bill_cycle = $user->billing_cycle;
                $new_bill_cycle = $request->billCycle;

                $status =  $this->doBillingCycleChange($user, $old_bill_cycle, $new_bill_cycle,$uniqueId);

                if ($status['status'] == 'error') {
                    Toastr::error('user: ' . $user->userid . ' | ' . $status['message'], 'error');
                    continue;
                } elseif ($status['status'] == 'success') {
                    Toastr::success('user: ' . $user->userid . ' | ' . 'Bill Cycle Changed Successfully', 'success');
                }
                $processedUserIds[] = $user->id;
            }
        }

        sleep(30);

        return redirect()->back();
    }


    public function updateMikrotikUser($user)
    {
        if (checkAPI()) {
            $mk = new SyncWithMk();
            $mk->syncSingleClient($user->id);
        } else {

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


    public function doBillingCycleChange($user, $old_bill_cycle, $new_bill_cycle,$uniqueString)
    {
        DB::beginTransaction();

        try {

            $status = (new BillingCycleChange)->billingCycleChange($user->pop, $user, $new_bill_cycle,$uniqueString);

            if ($status == 'error' || $status == 'balance_error') {
                return [
                    'status' => 'error',
                    'message' => 'Not Enough Balance..'
                ];
            }

            DB::commit();

            $client = Client::find($user->id);
            $client->clients_status = $client->expire_date < today() ? 'expired' : 'active';
            $client->save();
            $this->updateMikrotikUser($user);


            try {
                BillGenerateUpdateJob::dispatch($user->id);

                $this->sendSmsAfterBillgenerate($user);
                $this->saveCustomerBillingCycleInfo($user, $old_bill_cycle, $new_bill_cycle);
            } catch (\Throwable $th){

            }



            return [
                'status' => 'success',
                'message' => 'Bill Cycle Changed Successfully'
            ];
        } catch (\Throwable $th) {
            dd($th);
            DB::rollBack();
            return [
                'status' => 'error',
                'message' => $th->getMessage()
            ];
        }
    }

    public function saveCustomerBillingCycleInfo($user, $old_bill_cycle, $new_bill_cycle)
    {
        $customerBillingCycleInfo = new CustomerBillingCycleInfo();
        $customerBillingCycleInfo->client_id = $user->id;
        $customerBillingCycleInfo->previous_billing_cycle = $old_bill_cycle;
        $customerBillingCycleInfo->current_billing_cycle = $new_bill_cycle;
        $customerBillingCycleInfo->save();
    }

    public function sendSmsAfterBillgenerate($user)
    {
        if ($user->pop->bill_generate == "yes") {
            $bill_generate = BillGenerate::where('client_id', $user->id)->orderBy('id', 'desc')->first();
            if ($bill_generate) {
                if ($bill_generate->billing_type == "billing_cycle_change") {
                    sendSmsAfterBillgenerate($bill_generate->id);
                }
            }
        }
    }


    public function userBillingCycleChange(Request $request)
    {

        if (!empty($request->id) && !empty($request->billCycle)) {
            // dd($request->all());

            $uniqueString = $request->uuid;

            $user = Client::with('pop.nas', 'packages', 'subpack', 'pop.reseller', 'customerAccount', "clientsinfo")->find($request->id);

            if (checkSettings('expire_billing_change_today_from_billing_date') != 'enable') {
                if (now()->subMonth() > $user->expire_date) {
                    Toastr::error('Customer Expired or Deactivated or expired one month older', 'error');
                    return redirect()->back();
                }
            }

            if ($request->billCycle == $user->billing_cycle) {
                Toastr::error('Select a Different Billing Cycle Date', 'error');
                return redirect()->back();
            }


            if ($user->pop->reseller->reseller_type == 'own' && $user->customerAccount->dueAmount > 0) {
                Toastr::error('Customer Has due amount!! Please Clear Previous Due.', 'error');
                return redirect()->back();
            }

            $old_bill_cycle = $user->billing_cycle;
            $new_bill_cycle = $request->billCycle;

            $status = $this->doBillingCycleChange($user, $old_bill_cycle, $new_bill_cycle,$uniqueString);

            if ($status['status'] == 'success') {
                (new Notification)->notify("..::[Customer Billing Cycle Change]::.. \n Billing Cycle Changed.\n Change By " . auth()->user()->email . " \nCustomer Username : " . $user->userid . "\n Change Time : " . now());
                Toastr::success($status['message'], 'success');
            } else {
                Toastr::error($status['message'], 'error');
            }
            return redirect()->back();
        } else {
            return redirect()->back();
        }
    }

    public function autoDeactiveDateStore(Request $request)
    {
        $old_client = Client::with('clientsinfo')->find($request->id);

        $user = Client::find($request->id);
        $user->auto_deactive = $request->auto_deactive;
        $user->save();

        $new_data_client = Client::with('clientsinfo')->find($request->id);
        (new ClientController)->clientEditLog($user, $old_client, $new_data_client);

        Toastr::success('Auto Deactive Date Updated Successfully', 'success');
        return redirect()->back();
    }
}
