<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use App\Models\Pop;
use App\Models\Client;
use App\Models\Balance;
use App\Models\Packages;
use App\Classes\MikrotikService\Mikrotik;
use App\Classes\MikrotikService\SyncWithMk;
use App\Classes\SMS\ResellerRechargeSms;
use App\Http\Controllers\Clients\IdEnableDisableController;
use App\Models\SubPackage;
use Illuminate\Http\Request;
use App\Models\CustomerAccount;
use App\Services\PriceCalculate;
use Illuminate\Support\Facades\DB;
use App\Services\CommissionService;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Auth;
use App\Models\ReselleBalanceLogReport;
use App\Models\Reseller;
use App\Models\ResellerSmsGetway;
use App\Models\SubResellerBalanceLogReport;
use App\Services\ExpirationService;
use App\Services\ExpireDateRoundService;
use Faker\Core\Uuid;
use Illuminate\Support\Facades\Log;

class CustomerRechargeController extends Controller
{
    //

    public function CustomerRecharge(Request $request)
    {

        if (Auth::user()->hasPermissionTo('dynamic-recharge')) {
            if (checkSettings('reseller-client-dynamic-recharge') == 'enable') {
                if ($request->dynamic_recharge == 'yes' && !empty($request->ids) && $request->type == 'Recharge') {
                    $result = (new DynamicRechargeController)->dynamicRechargeProcess($request);
                    if ($result['status'] == 'success') {
                        return [
                            'status' => 'success',
                            'message' => 'All Recharge Done...'
                        ];
                    } else {
                        // dd($result);
                        return [
                            'status' => 'error',
                            'message' => $result['message']
                        ];
                    }
                }
            } else {
                Toastr::error('Dynamic Recharge is not enable', 'Error');
            }
        } else {
            if ($request->type == 'Recharge' && !empty($request->ids)) {
                try {
                    DB::beginTransaction();

                    foreach ($request->ids as $id) {
                        $st = $this->doCustomerRecharge($id,$request->uuid);
                        if ($st == 'balance_error') {
                            return [
                                'status' => 'balance_error',
                                'message' => 'Insufficient Balance'
                            ];
                        } elseif ($st == 'sub_package_error') {
                            return [
                                'status' => 'sub_package_error',
                                'message' => 'There is not Sub Package'
                            ];
                        }
                    }
                    DB::commit();
                    Toastr::success('Recharge Done..', 'Success');
                    try {

                        $this->resellerCustomerRechargeSms($request);
                    } catch (\Exception $e) {
                    }
                    return [
                        'status' => 'success',
                        'message' => 'All Recharge Done..'
                    ];
                } catch (\Throwable $th) {
                    DB::rollBack();
                    return [
                        'status' => 'error',
                        'message' => $th
                    ];
                }
            } elseif ($request->type == 'billingCycleChange' && !empty($request->ids)) {
                $this->doBillingCycleChange($request);
            } else {
                return [
                    'status' => 'error',
                    'message' => 'Invalid users or did not select recharge'
                ];
            }
        }
    }

    public function resellerCustomerRechargeSms($request)
    {

        foreach ($request->ids as $id) {
            $reseller_recharge = new ResellerRechargeSms();
            $reseller_recharge->send($id);

            $client = Client::with('pop', 'clientsinfo', 'packages')->find($id);
            $reseller_sme_getway = ResellerSmsGetway::with('reseller')->where('reseller_id', $client->pop->reseller_id)->first();
            // dd($reseller_sme_getway);
            if ($reseller_sme_getway) {
                $customer_recharge = collect(json_decode($reseller_sme_getway->sms_formate))->where('sms_type', 'other_reseller_customer_recharge')->first();
                if ($customer_recharge->send_sms == "Yes") {

                    (new ResellerRechargeSms())->sendOtherResellerCustomerRechargeSms(
                        $client,
                        $reseller_sme_getway->sms_gateway,
                        $reseller_sme_getway->reseller->name,
                        $reseller_sme_getway->reseller->contact,
                        $customer_recharge->sms_body,
                        $reseller_sme_getway->reseller->id
                    );
                }
            }
        }
    }


    public function doCustomerRecharge($id,$uniqueString)
    {

        $user = Client::find($id);

        $user->clients_status = "active";
        $user->save();




        $pop  = Pop::with('reseller')->find($user->pop_id);
        if ($pop->bill_generate == 'yes') {
            return false;
        }

        $package          = Packages::find($user->package_id);
        $resellerBalance  = Balance::getBalance('reseller', $pop->reseller_id);


        $expire = Carbon::parse($user->expire_date);

        if (checkSettings('recharge_expire_customer_today') == 'enable') {
            if ($expire < today()) {
                $cur = today();


                if (date('t') < $user->billing_cycle) {
                    $user->billing_cycle = date('t');
                    $user->save();
                }

                $nextExpire                 = date('d') > $user->billing_cycle ? Carbon::parse(date('Y-m-' . $user->billing_cycle))->addMonth() : Carbon::parse(date('Y-m-' . $user->billing_cycle));
                $totalDay                   = $nextExpire->diffInDays($cur) + 1;
                $action_days_message        = 'Total ' . $totalDay . ' days. From ' . $cur . ' To ' . $nextExpire;
                $totalCost                  = PriceCalculate::calculate(today()->daysInMonth, $package->package_rate, $totalDay);

            } else {

                $nextExpire = Carbon::parse($user->expire_date)->addMonth();
                if(globalPermission("round_expire_date")){
                    $nextExpire = (new ExpireDateRoundService())->roundDate($user->expire_date);
                }
                $totalCost = $package->package_rate;
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
            }
        } else {

            if ($expire < today() && Carbon::parse($user->expire_date)->addMonth() < today()) {
                $cur = today();

                if (date('t') < $user->billing_cycle) {
                    $user->billing_cycle = date('t');
                    $user->save();
                }

                $nextExpire                 = date('d') > $user->billing_cycle ? Carbon::parse(date('Y-m-' . $user->billing_cycle))->addMonth() : Carbon::parse(date('Y-m-' . $user->billing_cycle));
                $totalDay                   = $nextExpire->diffInDays($cur) + 1;
                $action_days_message        = 'Total ' . $totalDay . ' days. From ' . $cur . ' To ' . $nextExpire;
                $totalCost                  = PriceCalculate::calculate(today()->daysInMonth, $package->package_rate, $totalDay);


            } else {

                $nextExpire = Carbon::parse($user->expire_date)->addMonth();
                if(globalPermission("round_expire_date")){
                    $nextExpire = (new ExpireDateRoundService())->roundDate($user->expire_date);
                }
                $totalCost = $package->package_rate;
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
                // dd($nextExpire);
            }
        }

        $extra_day_for_day_day = (isset(siteinfo()->d2dactiveday) ? siteinfo()->d2dactiveday : 0);
        $subPackageFullPrice = false;
        if($extra_day_for_day_day > 0){
          if (Carbon::parse($user->expire_date)->addDay($extra_day_for_day_day) < today() ) {
                $cur = today();


                if (date('t') < $user->billing_cycle) {
                    $user->billing_cycle = date('t');
                    $user->save();
                }

                $nextExpire                 = date('d') > $user->billing_cycle ? Carbon::parse(date('Y-m-' . $user->billing_cycle))->addMonth() : Carbon::parse(date('Y-m-' . $user->billing_cycle));
                $totalDay                   = $nextExpire->diffInDays($cur) + 1;
                $action_days_message        = 'Total ' . $totalDay . ' days. From ' . $cur . ' To ' . $nextExpire;
                $totalCost                  = PriceCalculate::calculate(today()->daysInMonth, $package->package_rate, $totalDay);
          }else{
            $nextExpire = Carbon::parse($user->expire_date)->addMonth();
            if(globalPermission("round_expire_date")){
                $nextExpire = (new ExpireDateRoundService())->roundDate($user->expire_date);
            }
            $totalCost = $package->package_rate;
            $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
          }
        }

        if(checkSettings('d2d_recharge_for_reseller') == 'enable'){
            if (Carbon::parse($user->expire_date) < today() ) {
                $total_day_of_this_month = now()->lastOfMonth()->format('d') - 1;

                $nextExpire = Carbon::parse(today())->addDay($total_day_of_this_month);
                if(globalPermission("round_expire_date")){
                    $nextExpire = (new ExpireDateRoundService())->roundExpireDateForRecharge(now(),$nextExpire);
                }
                $totalCost = $package->package_rate;
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
          }else{
            $total_day_of_expire_date = Carbon::parse($user->expire_date)->lastOfMonth()->format('d');

            $nextExpire = Carbon::parse($user->expire_date)->addDay($total_day_of_expire_date);
            if(globalPermission("round_expire_date")){
                $nextExpire = (new ExpireDateRoundService())->roundExpireDateForRecharge($user->expire_date,$nextExpire);
            }
            $totalCost = $package->package_rate;

            $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
          }
        }

        $reseller_id      = $pop->reseller_id;


        if ($resellerBalance >= $totalCost) {

            if ($pop->billable == 'yes') {

                Balance::balanceDeductForUserRecharge('reseller', $reseller_id, $totalCost);

                if ($pop->subreseller == 'yes') {

                    $subPackage = SubPackage::find($user->sub_package_id);
                    $popBalance  = Balance::getBalance('pop', $pop->id);

                    if (empty($subPackage)) {
                        return 'sub_package_error';
                    }

                    if (checkSettings('recharge_expire_customer_today') == 'enable') {
                        if ($expire < today()) {
                            $subTotalCost = PriceCalculate::calculate(today()->daysInMonth, $subPackage->rate, $totalDay);
                        } else {
                            $subTotalCost = $subPackage->rate;
                        }
                    } else {
                        if ($expire < today() && Carbon::parse($user->expire_date)->addMonth() < today()) {
                            $subTotalCost = PriceCalculate::calculate(today()->daysInMonth, $subPackage->rate, $totalDay);
                        } else {
                            $subTotalCost = $subPackage->rate;
                        }
                    }


                    if(checkSettings('d2d_recharge_for_reseller') == 'enable'){
                        $subTotalCost = $subPackage->rate;
                    }


                    if($extra_day_for_day_day > 0){
                        if (Carbon::parse($user->expire_date)->addDay($extra_day_for_day_day) < today() ) {
                            $subTotalCost = PriceCalculate::calculate(today()->daysInMonth, $subPackage->rate, $totalDay);
                        }else{
                            $subTotalCost = $subPackage->rate;
                        }
                      }




                    if($subPackageFullPrice){
                        $subTotalCost = $subPackage->rate;
                    }





                    if ($subTotalCost > $popBalance) {
                        return 'balance_error';
                    }



                    $SubResellerAction = "Recharge For " . $action_days_message .
                        " . For package " . $subPackage->name .
                        " cost BDT " . $subTotalCost;

                    Balance::balanceDeductForUserRecharge('pop', $pop->id, $subTotalCost);

                    if ($subPackage->commission > 0) {
                        (new CommissionService())->subreseller_commission($subTotalCost, $SubResellerAction, $pop->id, $subPackage->commission, $subPackage->rate, $user->id);
                    }
                    $popBalance_after_recharge  = Balance::getBalance('pop', $pop->id);

                    SubResellerBalanceLogReport::create(
                        [
                            'reseller_id'       => $reseller_id,
                            'sub_reseller_id'   => $pop->id,
                            'client_id'         => $id,
                            'action'            => $SubResellerAction,
                            'amount'            => $subTotalCost,
                            'remarks'           => 'Created BY ' . Auth::user()->email,
                            'before_balance'    => $popBalance,
                            'after_balance'    => $popBalance_after_recharge,
                            'reseller_cost' => $totalCost,
                            'commission_amount' => getCommissionForSubResellerRecharge($id,$subTotalCost,),
                        ]
                    );
                }
            }



            $action = "Recharge For " . $action_days_message .
                " . For package " . $package->package_name .
                " cost BDT " . $totalCost;

            $resellerBalanceAfterRecharge  = Balance::getBalance('reseller', $pop->reseller_id);

            ReselleBalanceLogReport::create(
                [
                    'reseller_id' => $reseller_id,
                    'client_id'   => $id,
                    'action'      => $action,
                    'amount'      => $totalCost,
                    'remarks'     => 'Created BY ' . Auth::user()->email,
                    'reseller_balance' => $resellerBalance,
                    'after_balance' => $resellerBalanceAfterRecharge,
                    'uniqueId'    =>  $uniqueString.$id,
                    'pop_id'       => $pop->id,
                    'commission_amount' => getCommissionForResellerRecharge($id,$totalCost),
                    'reseller_commission_percentage' => $pop->reseller->commission_percentage,
                    'pop_commission_percentage' => $pop->commission_percentage,
                ]
            );

            if ($package->commission > 0) {
                (new CommissionService())->reseller_commission($totalCost, $action, $reseller_id, $package->commission, $package->package_rate, $user->id);
            }



            if ($pop->bill_generate == 'yes') {
                CustomerAccount::updateCustomrAccount($id, $package->package_rate, 0, 0, $totalCost);
                BillGenerateController::entryBillGenerate($id, $totalCost, 'Customer Recharge', 'recharge', $nextExpire);
            }


            $client = Client::with("pop.nas", 'packages')->find($user->id);
            $old_expire_date = $client->expire_date;

            $client->expire_date    = $nextExpire;

            $client->clients_status = 'active';
            $client->billing_cycle = Carbon::parse($nextExpire)->format('d');
            $client->save();


            if(globalPermission('RadiusExpiration')){
                (new ExpirationService())->handleExpiration($client->userid,$old_expire_date,$client->payment_dadeline,$client->pop->experity_check);
            }


            if (checkAPI()) {
                $mk = new SyncWithMk();
                $mk->syncSingleClient($client->id);
            } else {
                (new IdEnableDisableController)->enableInRadius($client);
            }
        } else {
            return 'balance_error';
        }
    }

    public function doCustomerRecharge1($id, $uniqueString)
    {
        $client = Client::find($id);
        if (!$client) {
            return response()->json(['error' => 'Client not found.'], 404);
        }

        $client->update(['clients_status' => 'active']);
        $pop = $client->pop;
        $package = $client->package;

        if (!$pop || !$package || $pop->bill_generate === 'yes') {
            return false;
        }

        // Calculate recharge details
        $rechargeDetails = $this->calculateRechargeDetails($client, $package);
        if (!$rechargeDetails['valid']) {
            return $rechargeDetails['error'];
        }

        // Deduct balance
        $balanceDeducted = $this->deductBalance($rechargeDetails, $pop, $client);
        if (!$balanceDeducted) {
            return 'balance_error';
        }

        // Update client details
        $this->updateClientDetails($client, $rechargeDetails['nextExpire'], $rechargeDetails['totalCost']);

        // Log recharge and handle external sync
        $this->logRechargeAction($client, $pop, $rechargeDetails, $uniqueString);
        $this->syncClient($client);

        return response()->json(['success' => 'Recharge completed.'], 200);
    }

    /**
     * Calculate recharge details based on client and package information.
     */
    private function calculateRechargeDetails(Client $client, Packages $package)
    {
        $expireDate = Carbon::parse($client->expire_date);
        $totalCost = $package->package_rate;
        $nextExpire = $expireDate->addMonth();
        $valid = true;

        // Adjust cost and expiration based on settings
        if (checkSettings('recharge_expire_customer_today') == 'enable' && $expireDate < today()) {
            $currentDate = today();
            $billingCycleDate = Carbon::parse(date('Y-m-' . $client->billing_cycle));

            if (date('t') < $client->billing_cycle) {
                $client->billing_cycle = date('t');
                $client->save();
            }

            $nextExpire = date('d') > $client->billing_cycle
                ? $billingCycleDate->addMonth()
                : $billingCycleDate;

            $totalDays = $nextExpire->diffInDays($currentDate) + 1;
            $totalCost = PriceCalculate::calculate(today()->daysInMonth, $package->package_rate, $totalDays);
        }

        return [
            'valid' => $valid,
            'totalCost' => $totalCost,
            'nextExpire' => $nextExpire,
        ];
    }

    /**
     * Deduct balance from the reseller or sub-reseller as applicable.
     */
    private function deductBalance(array $rechargeDetails, Pop $pop, Client $client)
    {
        $resellerBalance = Balance::getBalance('reseller', $pop->reseller_id);

        if ($resellerBalance < $rechargeDetails['totalCost']) {
            return false;
        }

        Balance::balanceDeductForUserRecharge('reseller', $pop->reseller_id, $rechargeDetails['totalCost']);

        if ($pop->subreseller === 'yes') {
            $subPackage = SubPackage::find($client->sub_package_id);
            $popBalance = Balance::getBalance('pop', $pop->id);

            if (!$subPackage || $subPackage->rate > $popBalance) {
                return false;
            }

            Balance::balanceDeductForUserRecharge('pop', $pop->id, $subPackage->rate);
        }

        return true;
    }

    /**
     * Update the client's details after successful recharge.
     */
    private function updateClientDetails(Client $client, $nextExpire, $totalCost)
    {
        $client->update([
            'expire_date' => $nextExpire,
            'clients_status' => 'active',
            'billing_cycle' => Carbon::parse($nextExpire)->format('d'),
        ]);

        if (globalPermission('RadiusExpiration')) {
            (new ExpirationService())->handleExpiration(
                $client->userid,
                $client->expire_date,
                $client->payment_deadline,
                $client->pop->experity_check
            );
        }
    }

    /**
     * Log the recharge action and update necessary reports.
     */
    private function logRechargeAction(Client $client, Pop $pop, array $rechargeDetails, $uniqueString)
    {
        $action = "Recharge for 1 month. From {$client->expire_date} to {$rechargeDetails['nextExpire']}. Cost: {$rechargeDetails['totalCost']}";
        $reseller = Reseller::find($pop->reseller_id);

        ReselleBalanceLogReport::create([
            'reseller_id' => $pop->reseller_id,
            'client_id' => $client->id,
            'action' => $action,
            'amount' => $rechargeDetails['totalCost'],
            'remarks' => 'Created by ' . Auth::user()->email,
            'uniqueId' => $uniqueString . $client->id,
            'pop_id' => $pop->id,
            'commission_amount' => getCommissionForResellerRecharge($client->id, $rechargeDetails['totalCost']),
            'reseller_commission_percentage' => $reseller->commission_percentage,
            'pop_commission_percentage' => $pop->commission_percentage,
        ]);
    }

    /**
     * Synchronize client details with external systems.
     */
    private function syncClient(Client $client)
    {
        if (checkAPI()) {
            (new SyncWithMk())->syncSingleClient($client->id);
        } else {
            (new IdEnableDisableController())->enableInRadius($client);
        }
    }



    public function doBillingCycleChange($request)
    {
        # code...
    }





    public function recharge($r)
    {
        $user = Client::find($r->recharge);



        $now = Carbon::now();
        $expire = Carbon::parse($user->expire_date);


        $month = $now->diffInMonths($expire);




        if ($month > 0 && $expire > $now) {
            $expire = $now;
            $next = Carbon::parse(date($user->billing_cycle . '-M-Y'));
            $totalDay = $next->diffInDays($expire);
        } else {
            $expire = $expire;
            $next = Carbon::parse($expire)->addMonth();
            $totalDay = $next->diffInDays($expire);
        }



        $pop              = Pop::with('reseller')->find($user->pop_id);
        $package          = Packages::find($user->package_id);
        $resellerBalance  = $this->getResellerBalance('reseller', $pop->reseller_id);
        $totalCost        = $package->package_rate;



        if ($resellerBalance > $totalCost) {


            $reseller_id = $pop->reseller_id;


            $action = "Recharge For 1 Month. From Date: " . $expire .
                " To : " . $next .
                " . For package " . $package->package_name .
                " Total " . $totalDay .
                " days cost BDT " . $totalCost;


            Client::where('id', $user->id)
                ->update(
                    [
                        'expire_date'  => Carbon::createFromFormat('Y-m-d H:i:s', $next)
                    ]
                );

            ReselleBalanceLogReport::create(
                [
                    'reseller_id' => $reseller_id,
                    'client_id'   => $user->id,
                    'action'      => $action,
                    'amount'      => $totalCost,
                    'remarks'     => ' BY ' . Auth::user()->email,
                    'uniqueId'     => createUUID(),
                    'pop_id'       => $user->pop_id,
                    'commission_amount' => getCommissionForResellerRecharge($user->id,$totalCost),
                    'reseller_commission_percentage' => $pop->reseller->commission_percentage,
                    'pop_commission_percentage' => $pop->commission_percentage,
                ]
            );
            Balance::balanceDeductForUserRecharge('reseller', $reseller_id, $totalCost);
            $this->clientExpire($user->id);
            $this->activeRadcheck($user->userid);

            return 'success';
        } else {
            return 'error';
        }
    }


    public function clientInfoData($id)
    {
        $client = Client::find($id);
        $expire_bd = Carbon::parse($client->expire_date)->format('d-M-Y');
        $expire_pd = Carbon::parse($client->expire_date)->addDay($client->payment_dadeline)->format('d-M-Y');
        return response()->json([
            'expire_bd'       => $expire_bd,
            'expire_pd'       => $expire_pd,

        ]);
    }
}
