<?php

namespace App\Http\Controllers;

use App\Classes\EditLogHistory;
use Exception;
use App\Models\Nas;
use App\Models\Pop;
use App\Models\Client;
use App\Models\Balance;
use App\Models\Reseller;
use App\Classes\MikrotikService\Mikrotik;
use App\Classes\MikrotikService\SyncWithMk;
use Illuminate\Http\Request;
use App\Classes\Notification;
use App\Classes\SMS\PopExceptionDeletSms;
use App\Classes\SMS\ResellerAccountRechargeSms;
use App\Http\Controllers\OnlinePayment\BkashResellerController;
use App\Http\Controllers\OnlinePayment\UpayController;
use App\Http\Controllers\OnlinePopRecharge\BkashPopRechargeController;
use App\Http\Controllers\OnlinePopRecharge\NagadPoprechargeController;
use App\Http\Controllers\OnlinePopRecharge\UpayPopRechargeController;
use Illuminate\Support\Facades\DB;
use Brian2694\Toastr\Facades\Toastr;
use App\Jobs\RadiusUserDisconnectJob;
use App\Models\SubResellerRechargeReport;
use App\Jobs\PopCloseJob;
use App\Jobs\PopDeactiveJob;
use App\Models\LogHistory;
use App\Models\PopEditLog;
use App\Models\ResellerArea;
use App\Models\ResellerRechargeReport;
use App\Models\User;
use App\Models\UserAccounting;
use App\Services\ExpirationService;
use App\Services\RadiusClientSync;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class PopController extends Controller
{

    public function __construct()
    {
        $this->middleware('permission:pop_index|pop_create|pop_edit|pop_destroy|specific_management_services', ['only' => ['index', 'show']]);
        $this->middleware('permission:pop_create', ['only' => ['create', 'store']]);
        $this->middleware('permission:pop_edit|pop-accounts-edit', ['only' => ['edit', 'update']]);
        $this->middleware('permission:pop_destroy', ['only' => ['destroy']]);
        $this->middleware('permission:pop-recharge', ['only' => ['subResellerRecharge']]);
        $this->middleware('permission:pop_exception', ['only' => ['popException']]);
    }
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $pop = Pop::list();


        return view('pop.index', [
            'page_title' => 'POP/Zone list',
            'pop'        => $pop
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function sub_package_permission()
    {
    }

    public function create()
    {
        // $reseller_list = DB::table('resellers')->pluck('name','id');
        // $mikrotik_list = DB::table('nas')->pluck('nasname','id');

        $reseller_list = Reseller::all();
        $mikrotik_list = Nas::all();

        return view('pop.create', [
            'page_title' => 'Add New POP/Zone',
            'resellers'   => $reseller_list,
            'naslist'        => $mikrotik_list
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {



        $this->validate(
            $request,
            [
                'popname'       => 'required|unique:pops',
                'pop_location'  => 'required',
                'pop_contact'   => 'required',
                'billable'      => 'required',
                'reseller_id'   => 'required',
                'nas_id'        => 'required',
                'longitude'     => 'required',
                'latitude'      => 'required'

            ],
        );

        $payment = json_encode([
            'bkash_charges' => $request->bkash_charges,
            'rocket_charges' => $request->rocket_charges,
            'nagad_charges' => $request->nagad_charges,
            'upay_charges' => $request->upay_charges,
            'ucash_charges' => $request->ucash_charges,
        ]);
        DB::beginTransaction();
        try{
            $pop = Pop::create([
                'popname'               => $request->popname,
                'pop_location'          => $request->pop_location,
                'pop_contact'           => $request->pop_contact,
                'reseller_id'           => $request->reseller_id,
                'nas_id'                => $request->nas_id,
                'billable'              => $request->billable,
                'longitude'             => $request->longitude,
                'latitude'              => $request->latitude,
                'server_authentication' => $request->server_authentication,
                'subreseller'           => $request->subreseller,
                'bill_generate'         => $request->bill_generate_value,
                'package_change_pricing' => $request->package_change_pricing,
                'payment_charges' => $payment,
                'commission_percentage' => $request->commission_percentage,

            ]);

            Balance::create([
                'type' => 'pop',
                'type_id' => $pop->id,
                'amount'  => 0,

            ]);

            DB::commit();
            clearCache('pop');

            Toastr::success('POP/Zone Created Successfully', 'Success');
            return redirect()->route('pop.index');
        }catch(Exception $e){
            Toastr::error('POP/Zone Created Faild', 'Error');
            return redirect()->back();
        }




    }


    public function edit($id)
    {
        $reseller_list = Reseller::all();

        $list = Pop::with('reseller')->find($id);
        $mikrotik_list = Nas::all();
        $payment = json_decode($list->payment_charges);


        return view('pop.update', [
            'page_title' => 'Add New POP/Zone',
            'reseller'  => $reseller_list,
            'naslist'    => $mikrotik_list,
            'list'       => $list,
            'payment' => $payment
        ]);
    }


    public function update(Request $request, $id)
    {
        $this->validate(
            $request,
            [
                'popname'       => 'required|unique:pops,popname,' . $id,
                'pop_location'  => 'required',
                'pop_contact'   => 'required',
                'billable'      => 'required',
                'reseller_id'   => 'required',
                'nas_id'        => 'required',
                'longitude'    => 'required',
                'latitude'     => 'required',
                'bill_generate_value' => 'required'
            ]
        );

        $payment = json_encode([
            'bkash_charges' => $request->bkash_charges,
            'rocket_charges' => $request->rocket_charges,
            'nagad_charges' => $request->nagad_charges,
            'upay_charges' => $request->upay_charges,
            'ucash_charges' => $request->ucash_charges,
        ]);

        $type = 'POP';
        $old_info = Pop::where('id', $id)->first();

        $pop = Pop::find($id);
        $pop->popname = $request->popname;
        $pop->pop_location = $request->pop_location;
        $pop->pop_contact = $request->pop_contact;
        $pop->reseller_id = $request->reseller_id;
        $pop->subreseller = $request->subreseller;
        $pop->nas_id = $request->nas_id;
        $pop->billable = $request->billable;
        $pop->longitude = $request->longitude;
        $pop->latitude = $request->latitude;
        $pop->sms_send = $request->sms_send;
        $pop->server_authentication = $request->server_authentication;
        $pop->enable_online_recharge = $request->enable_online_recharge;

        if ($request->bill_generate_value != null) {

            $pop->bill_generate = $request->bill_generate_value;
        }
        $pop->package_change_pricing = $request->package_change_pricing;
        $pop->payment_charges = $payment;

        if($request->commission_percentage != null){
            $pop->commission_percentage = $request->commission_percentage;
        }
        $pop->update();

        $new_info = Pop::find($pop->id);
        (new EditLogHistory)->editLogSave($pop, $type, $old_info, $new_info);

        clearCache('pop');

        Toastr::success('POP/Zone Updated Successfully', 'Success');
        return redirect()->route('pop.index');
    }


    public function popException()
    {
        $non_expired_pops = Pop::where('experity_check', 'No')->get();
        $expired_pops = Pop::where('experity_check', 'Yes')->get();


        return view('pop.expired', [
            'page_title' => 'Attach OR Detach POP Exception',
            'non_expired_pops'  => $non_expired_pops,
            'expired_pops'    => $expired_pops
        ]);
    }


    public function statusException()
    {
        $non_expired_pops = Pop::where('status', 'Enable')->get();
        $expired_pops = Pop::where('status', 'Disable')->get();


        return view('pop.status', [
            'page_title' => 'Attach OR Detach POP Status Exception',
            'non_expired_pops'  => $non_expired_pops,
            'expired_pops'    => $expired_pops

        ]);
    }
    public function statusChange(Request $request)
    {
        $pop = Pop::find($request->pop_id);
        if ($pop->status == 'Enable') {
            $pop->status = 'Disable';
            $pop->update();
        } else {
            $pop->status = 'Enable';
            $pop->update();
        }

        clearCache('pop');

        Toastr::success('POP/Zone Exception Changed Successfully', 'Success');
        return redirect()->route('status.exception');
    }

    public function experityCheckChange(Request $request)
    {

        $type = 'POP';
        $old_info = Pop::where('id', $request->pop_id)->first();
        $pop = Pop::find($request->pop_id);

        if ($pop->experity_check == 'Yes') {

            $lists = Client::where('pop_id', $request->pop_id)
                ->where('clients_status', '!=', 'deactive')
                ->where('clients_status', '!=', 'close')
                ->where('clients_status', '!=', 'disable')
                ->select('userid', 'expire_date', 'payment_dadeline')
                ->get();

            foreach ($lists as $user) {
                $acutal_expire_date = $user->expire_date;
                if ($user->payment_dadeline > 0) {
                    $acutal_expire_date = Carbon::parse($acutal_expire_date)->addDays($user->payment_dadeline);
                }
                if ($acutal_expire_date < today()) {
                    DB::table('radcheck')
                        ->where('username', $user->userid)
                        ->update([
                            'op' => '!='
                        ]);
                    // SessionRefreshController::userDisconnectProcess($user->userid);
                    if (checkAPI() == false) {
                        RadiusUserDisconnectJob::dispatch($user->userid);
                    }

                    $send_sms = new PopExceptionDeletSms();
                    $send_sms->sendPopExceptionDeletSms($user->userid);
                }
            }



            $pop->experity_check = 'No';
            $pop->update();

            $new_info = Pop::find($pop->id);
            (new EditLogHistory)->editLogSave($pop, $type, $old_info, $new_info);

            // enableing user from mik
            if (checkAPI()) {
                $mkAPI = new syncWithMk();
                $mkAPI->syncSinglePop($pop->id);
            }
        } else {

            $list = Client::where('pop_id', $request->pop_id)
                ->where('clients_status', '!=', 'deactive')
                ->where('clients_status', '!=', 'close')
                ->where('clients_status', '!=', 'disable')
                ->pluck('userid')->toArray();

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

            $pop->experity_check = 'Yes';
            $pop->update();

            $new_info = Pop::find($pop->id);
            (new EditLogHistory)->editLogSave($pop, $type, $old_info, $new_info);

            // enableing user from mik
            if (checkAPI()) {
                $mkAPI = new SyncWithMk();
                $mkAPI->syncSinglePop($pop->id);
            }
        }

        clearCache('pop');

        Toastr::success('POP/Zone Exception Changed Successfully', 'Success');
        return redirect()->route('pop.exception');
    }




    public function subResellerRecharge($id)
    {
        $pop = Pop::find($id);
        $popList = SubResellerRechargeReport::with('pop', 'user', 'balance')
            ->where('pop_id', $id)
            ->orderBy('id', 'desc')
            ->take(10);

        return view('pop.subResellerRecharge', [
            'page_title' => 'Sub Reseller Recharge',
            'pop'   => $pop,
            'popList' => $popList->get()
        ]);
    }

    public function rechargeByOnlinePayment($type, $type_id, $amount, $remark, $paid_amount, $user_id)
    {
        $status = Balance::balanceUpdate($type, $type_id, $amount, $remark, $paid_amount, $user_id, 'online');
        clearCache('pop');
    }


    public function subRsellerRechargeUpdate(Request $request)
    {


        if ($request->amount == 0) {
            Toastr::error('Something is worng', 'error');
            return redirect()->back();
        }

        $status = Balance::balanceUpdate($request->type, $request->type_id, $request->amount, $request->remark, null, null, 'cash');
        clearCache('pop');

        if ($status === 'success') {

            (new Notification)->notify('Pop Recharge by by ' . auth()->user()->name . ' Amount : ' . $request->amount . ' Remark: ' . $request->remark);
            Toastr::success('Recharge Success', 'success');
            return redirect()->back()->with('modalopen', 'true');
        } else {
            Toastr::error('Something is worng' . $status, 'error');
            return redirect()->back();
        }
    }

    public function syncPopWithMikrotik(Request $request)
    {
        $pop_id = $request->pop_id;

        try {
            $mk = new SyncWithMk();
            $mk->syncSinglePop($pop_id);
            Toastr::success("successfully synchronized.");
            return back();
        } catch (\Exception $err) {
            Toastr::error("something went wrong while syncing.");
            return back();
        }
    }

    public function syncPopForRadius(Request $request)
    {
        $clients = Client::with('pops.nas', 'packages')->where('pop_id', $request->pop_id)->get();

        foreach ($clients as $client) {
            if ($client) {
                if(globalPermission('RadiusExpiration')){
                    (new ExpirationService())->syncExpiration($client->userid);
                }else{
                    (new RadiusClientSync())->syncSingleRadiusClient($client->id);
                }
            }
        }

        Toastr::success("successfully synchronized Pop.");
        return back();
    }


    public function getSubPopOfReseller(Request $request)
    {
        if (request()->ajax() && !empty($request->id)) {

            $pop = Pop::conditionalList()->where('reseller_id', $request->id)->where('subreseller', 'yes');

            $option = '<option value="all">All</option>';

            foreach ($pop as $p) {

                $option .= "<option value='" . $p->id . "'>" . $p->popname . "</option>";
            }


            echo $option;
        }
    }

    public function deactiveAllCustomer($id)
    {
        PopDeactiveJob::dispatch($id);
        Toastr::success('All Client Deactive Successfully', 'Success');
        return redirect()->back();
    }

    public function popClose($id)
    {
        $userId = auth()->user()->id;
        $client = Client::where('pop_id', $id)->get();
        foreach ($client as $value) {
            PopCloseJob::dispatch($value->id, $userId);
        }



        Toastr::success('All Client Closed Successfully', 'Success');
        return redirect()->back();
    }

    public function getPopWiseAreaList(Request $request)
    {
        if (request()->ajax() && !empty($request->id)) {

            $area = ResellerArea::where('pop_id', $request->id)->get();

            if(globalPermission('getResellerAreaOnSelectPop')){
                $getPop = Pop::find($request->id);
                $area = ResellerArea::where('reseller_id', $getPop->reseller_id)->get();
            }

            $option = '<option value="">Select One</option>';

            foreach ($area as $p) {
                $option .= "<option value='" . $p->area . "'>" . $p->area . "</option>";
            }
            echo $option;
        }
    }

    public function getPop(Request $request)
    {
        $pops = Pop::whereIn('reseller_id', $request->reseller_ids)->where('subreseller', 'yes')->get();
        return $pops;
    }

    public function onlinePopRecharge($id)
    {
        $pop = Pop::find($id);
        $popList = SubResellerRechargeReport::with('pop', 'user', 'balance')
            ->where('pop_id', $id)
            ->orderBy('id', 'desc')
            ->take(10);

        return view('pop.onlineRecharge', [
            'page_title' => 'Sub Reseller Online Recharge',
            'pop'   => $pop,
            'popList' => $popList->get()
        ]);
    }

    public function onlinePopRechargeExecute(Request $request)
    {
        if ($request->payment_method == 'upay') {
            return (new UpayPopRechargeController())->createPayment($request);
        } elseif ($request->payment_method == 'bkash') {
            return (new BkashPopRechargeController())->createPayment($request);
        } elseif ($request->payment_method == 'nagad') {
            return (new NagadPoprechargeController())->createPayment($request);
        }
    }

    public function upayPopRechargeCallback(Request $request)
    {
        $data = (new UpayPopRechargeController())->validation($request);

        if ($data['data']['status'] == 'cancelled') {
            Toastr::error('Recharge Canceled', 'Recharge Canceled');
            return redirect()->back();
        }

        $paid_amount = $data['data']['amount'];
        $gateway_transaction_id = $data['data']['trx_id'];


        // new code
        $pop_online_recharge = SubResellerRechargeReport::where('payment_gateway_transaction_id', $gateway_transaction_id)->count();
        if ($request->status == 'successful' && $data['data']['txn_id'] == $request->transaction_id && $data['data']['status'] == 'success' && $pop_online_recharge == 0) {



            $user_id = User::onlinePaymentUser('Upay-Online')->id;

            // pop online recharge report
            $pop = Pop::find($request->pop_id);
            $reduse_amount = 0;
            if ($pop->payment_charges) {
                $payment = json_decode($pop->payment_charges);
                $upay_percentage = $payment->upay_charges ?? 0;
                $reduse_amount = ($paid_amount * $upay_percentage) / 100;
            }
            $paid_amount = $this->getPaidAmountForOnlinePopRecharge($pop, 'Upay-Online', $paid_amount);

            $remark = 'Upay Online Recharge by ' . auth()->user()->email . ' Amount : ' . $paid_amount;
            $pop_recharge_status = Balance::balanceUpdate('pop', $pop->id, $paid_amount, $remark, $paid_amount, $user_id, 'online', 'Upay', $gateway_transaction_id, $request->transaction_id);
            clearCache('pop');

            if ($pop_recharge_status === 'success') {

                (new Notification)->notify('Pop Recharge by by ' . auth()->user()->name . ' Amount : ' . $request->amount . ' Remark: ' . $remark);
            } else {
                Toastr::error('Something is wrong' . $pop_recharge_status, 'error');
                return redirect()->back();
            }


            //reseller online recharge report
            $reseller = Reseller::find($pop->reseller_id);

            if ($reseller->reseller_type == 'other') {
                $actions = 'Reseller payment received from ' . $reseller->name . ' ' . $reseller->contact;
                UserAccounting::userAcStore($paid_amount, $actions, null, 'Upay', 'Upay', $user_id);
            }

            $status = Balance::balanceUpdate('reseller', $reseller->id, $paid_amount, $remark, $paid_amount, $user_id, 'online', 'Upay', $gateway_transaction_id, $request->transaction_id);
            clearCache('reseller');

            $totalRecharge = ResellerRechargeReport::with('reseller', 'user', 'balance')->where('reseller_id', $reseller->id)->sum('amount');

            if ($status === 'success') {

                $sms_setting = json_decode(getSmsMessage()->where('tamplate_name', 'reseller_balance_recharge_sms')->first()->tamplate_body, true);

                if ($sms_setting["sendsms"] == "Yes") {
                    (new ResellerAccountRechargeSms())->sendSms($reseller->id, $request->amount, $totalRecharge);
                }

                Toastr::success('Recharge Successfull', 'Recharge Successfull');
                return redirect()->route('pop.index');
            } else {
                Toastr::error('Recharge UnSuccessfull', 'Recharge UnSuccessfull');
                return redirect()->route('pop.index');
            }
        } else {
            Toastr::error('Recharge UnSuccessfull', 'Recharge UnSuccessfull');
            return redirect()->route('pop.index');
        }

        // end new code






    }


    public function getPaidAmountForOnlinePopRecharge($pop, $payment_method, $paid_amount)
    {
        $charges = json_decode($pop->payment_charges, true);

        if ($charges == null) {
            return $paid_amount;
        } elseif (isset($charges['bkash_charges']) && $charges['bkash_charges'] > 0 && $payment_method == 'Bkash-Online') {
            $paid_amount = $paid_amount - ($paid_amount * ($charges['bkash_charges'] / 100));
        } elseif (isset($charges['upay_charges']) && $charges['upay_charges'] > 0 && $payment_method == 'Upay-Online') {
            $paid_amount = $paid_amount - ($paid_amount * ($charges['upay_charges'] / 100));
        } elseif (isset($charges['rocket_charges']) && $charges['rocket_charges'] > 0 && $payment_method == 'Rocket-Online') {
            $paid_amount = $paid_amount - ($paid_amount * ($charges['rocket_charges'] / 100));
        } elseif (isset($charges['nagad_charges']) && $charges['nagad_charges'] > 0 && $payment_method == 'Nagad-Online') {
            $paid_amount = $paid_amount - ($paid_amount * ($charges['nagad_charges'] / 100));
        }

        return $paid_amount;
    }

    public function getPopList()
    {
        $pops = Pop::all();

        return response()->json([
            'pops' => $pops
        ]);
    }
}
