<?php

namespace App\Http\Controllers;

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

class CustomerRechargeController extends Controller
{
    /**
     * Cached settings to avoid repeated database calls
     */
    private array $cachedSettings = [];

    /**
     * Main entry point for customer recharge
     */
    public function CustomerRecharge(Request $request)
    {
        // Handle dynamic recharge if permitted
        if (Auth::user()->hasPermissionTo('dynamic-recharge')) {
            if ($this->getSetting('reseller-client-dynamic-recharge') === 'enable') {
                if ($request->dynamic_recharge === 'yes' && !empty($request->ids) && $request->type === 'Recharge') {
                    $result = (new DynamicRechargeController)->dynamicRechargeProcess($request);
                    return $result['status'] === 'success'
                        ? ['status' => 'success', 'message' => 'All Recharge Done...']
                        : ['status' => 'error', 'message' => $result['message']];
                }
            } else {
                Toastr::error('Dynamic Recharge is not enable', 'Error');
            }
            return ['status' => 'error', 'message' => 'Dynamic recharge not processed'];
        }

        // Handle regular recharge
        if ($request->type === 'Recharge' && !empty($request->ids)) {
            return $this->processBulkRecharge($request);
        }

        // Handle billing cycle change
        if ($request->type === 'billingCycleChange' && !empty($request->ids)) {
            return $this->doBillingCycleChange($request);
        }

        return [
            'status' => 'error',
            'message' => 'Invalid users or did not select recharge'
        ];
    }

    /**
     * Process bulk recharge for multiple clients
     */
    private function processBulkRecharge(Request $request): array
    {
        try {
            DB::beginTransaction();

            // Pre-load all clients with their relationships in a single query
            $clients = Client::with([
                'pop.reseller',
                'pop.nas',
                'packages',
                'subpack'
            ])->whereIn('id', $request->ids)->get()->keyBy('id');

            // Pre-load all required balances
            $popIds = $clients->pluck('pop_id')->unique();
            $resellerIds = $clients->pluck('pop.reseller_id')->unique();

            $resellerBalances = Balance::where('type', 'reseller')
                ->whereIn('type_id', $resellerIds)
                ->pluck('amount', 'type_id');

            $popBalances = Balance::where('type', 'pop')
                ->whereIn('type_id', $popIds)
                ->pluck('amount', 'type_id');

            // Cache settings once at the start
            $this->cacheRequiredSettings();

            $processedIds = [];
            $errors = [];

            foreach ($request->ids as $id) {
                $client = $clients->get($id);

                if (!$client) {
                    $errors[] = "Client {$id} not found";
                    continue;
                }

                $result = $this->doCustomerRechargeOptimized(
                    $client,
                    $request->uuid,
                    $resellerBalances,
                    $popBalances
                );

                if ($result === 'balance_error') {
                    DB::rollBack();
                    return [
                        'status' => 'balance_error',
                        'message' => 'Insufficient Balance'
                    ];
                }

                if ($result === 'sub_package_error') {
                    DB::rollBack();
                    return [
                        'status' => 'sub_package_error',
                        'message' => 'There is no Sub Package'
                    ];
                }

                if ($result === 'bill_generate_active') {
                    continue; // Skip clients with bill_generate enabled
                }

                $processedIds[] = $id;
            }

            DB::commit();
            Toastr::success('Recharge Done..', 'Success');

            // Queue SMS notifications instead of sending synchronously
            $this->queueRechargeNotifications($processedIds);

            return [
                'status' => 'success',
                'message' => 'All Recharge Done..'
            ];
        } catch (\Throwable $th) {
            DB::rollBack();
            Log::error('Customer Recharge Error: ' . $th->getMessage(), [
                'trace' => $th->getTraceAsString(),
                'ids' => $request->ids ?? []
            ]);

            return [
                'status' => 'error',
                'message' => 'Recharge failed: ' . $th->getMessage()
            ];
        }
    }

    /**
     * Cache required settings to avoid repeated database queries
     */
    private function cacheRequiredSettings(): void
    {
        $settingsToCache = [
            'recharge_expire_customer_today',
            'd2d_recharge_for_reseller',
            'round_expire_date',
            'addDay-toExpire-client-for-d2d-reseller-recharge',
            'round_expire_date_after_d2d_extend_ExpireDate_By_Month',
            'RadiusExpiration',
            'commission_from_manager_pop',
            'main_sms_gateway_for_own_other'
        ];

        foreach ($settingsToCache as $setting) {
            $this->cachedSettings[$setting] = checkSettings($setting);
        }
    }

    /**
     * Get cached setting value
     */
    private function getSetting(string $key): string
    {
        if (!isset($this->cachedSettings[$key])) {
            $this->cachedSettings[$key] = checkSettings($key);
        }
        return $this->cachedSettings[$key];
    }

    /**
     * Check if a permission is enabled (cached)
     */
    private function isPermissionEnabled(string $key): bool
    {
        return $this->getSetting($key) === 'enable';
    }

    /**
     * Optimized customer recharge with pre-loaded data
     */
    private function doCustomerRechargeOptimized(
        Client $client,
        string $uniqueString,
        &$resellerBalances,
        &$popBalances
    ) {
        $pop = $client->pop;
        $package = $client->packages;

        // Skip if bill_generate is enabled
        if ($pop->bill_generate === 'yes') {
            return 'bill_generate_active';
        }

        $resellerId = $pop->reseller_id;
        $currentResellerBalance = $resellerBalances[$resellerId] ?? 0;

        // Calculate recharge details
        $rechargeDetails = $this->calculateRechargeDetails($client, $package);
        $totalCost = $rechargeDetails['totalCost'];
        $nextExpire = $rechargeDetails['nextExpire'];
        $actionDaysMessage = $rechargeDetails['actionDaysMessage'];
        $totalDay = $rechargeDetails['totalDay'] ?? null;

        // Check if reseller has sufficient balance (running total across all recharges)
        if ($currentResellerBalance < $totalCost) {
            return 'balance_error';
        }

        // Build action description
        $action = "Recharge For " . $actionDaysMessage .
            " . For package " . $package->package_name .
            " cost BDT " . $totalCost;

        // Update in-memory reseller balance to prevent over-usage in the same bulk operation
        $resellerBalances[$resellerId] = $currentResellerBalance - $totalCost;

        // Deduct reseller balance in database
        Balance::balanceDeductForUserRecharge('reseller', $resellerId, $totalCost);

        // Get balance after deduction for logging (from updated in-memory balance)
        $resellerBalanceAfterRecharge = $resellerBalances[$resellerId];

        // Create reseller balance log report
        $resellerBalanceReport = ReselleBalanceLogReport::create([
            'reseller_id' => $resellerId,
            'client_id' => $client->id,
            'action' => $action,
            'amount' => $totalCost,
            'remarks' => 'Created BY ' . Auth::user()->email,
            'reseller_balance' => $currentResellerBalance,
            'after_balance' => $resellerBalanceAfterRecharge,
            'uniqueId' => $uniqueString . $client->id,
            'pop_id' => $pop->id,
            'commission_amount' => getCommissionForResellerRecharge($client->id, $totalCost),
            'reseller_commission_percentage' => $pop->reseller->commission_percentage ?? 0,
            'pop_commission_percentage' => $pop->commission_percentage ?? 0,
        ]);

        // Handle sub-reseller billing if applicable
        if ($pop->billable === 'yes' && $pop->subreseller === 'yes') {
            $subPackageResult = $this->handleSubResellerBilling(
                $client,
                $pop,
                $popBalances,
                $rechargeDetails,
                $totalCost,
                $resellerId,
                $resellerBalanceReport->id
            );

            if ($subPackageResult !== true) {
                return $subPackageResult;
            }
        }

        // Handle commission
        if ($package->commission > 0 || $this->isPermissionEnabled('commission_from_manager_pop')) {
            (new CommissionService())->reseller_commission(
                $totalCost,
                $action,
                $resellerId,
                $package->commission,
                $package->package_rate,
                $client->id
            );
        }

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

        // Update client with new expire date and status - single save
        $oldExpireDate = $client->expire_date;
        $billingCycleUpdated = $rechargeDetails['billingCycleUpdated'] ?? false;

        $updateData = [
            'expire_date' => $nextExpire,
            'clients_status' => 'active',
            'billing_cycle' => Carbon::parse($nextExpire)->format('d'),
        ];

        // Only update billing_cycle if it was changed during calculation
        if ($billingCycleUpdated) {
            $updateData['billing_cycle'] = $rechargeDetails['newBillingCycle'];
        }

        $client->update($updateData);

        // Handle radius expiration
        if ($this->isPermissionEnabled('RadiusExpiration')) {
            (new ExpirationService())->handleExpiration(
                $client->userid,
                $oldExpireDate,
                $client->payment_dadeline,
                $pop->experity_check ?? null
            );
        }

        // Sync with MikroTik or Radius
        $this->syncClient($client);

        return null; // Success
    }

    /**
     * Calculate recharge details based on various settings
     */
    private function calculateRechargeDetails(Client $client, Packages $package): array
    {
        $expire = Carbon::parse($client->expire_date);
        $today = today();
        $totalCost = $package->package_rate;
        $totalDay = null;
        $billingCycleUpdated = false;
        $newBillingCycle = $client->billing_cycle;

        // Get site info for d2d settings
        $extraDayForD2d = siteinfo()->d2dactiveday ?? 0;

        // Determine calculation mode based on settings
        if ($this->isPermissionEnabled('d2d_recharge_for_reseller')) {
            return $this->calculateD2DRecharge($client, $package, $expire, $today);
        }

        if ($extraDayForD2d > 0) {
            return $this->calculateWithExtraDays($client, $package, $expire, $today, $extraDayForD2d);
        }

        if ($this->isPermissionEnabled('recharge_expire_customer_today')) {
            return $this->calculateExpireToday($client, $package, $expire, $today);
        }

        return $this->calculateStandardRecharge($client, $package, $expire, $today);
    }

    /**
     * Calculate D2D (Day to Day) recharge
     */
    private function calculateD2DRecharge(Client $client, Packages $package, Carbon $expire, Carbon $today): array
    {
        $totalCost = $package->package_rate;

        if ($expire < $today) {
            $totalDayOfThisMonth = now()->lastOfMonth()->format('d') - 1;

            if ($this->isPermissionEnabled('addDay-toExpire-client-for-d2d-reseller-recharge')) {
                $totalDayOfThisMonth++;
            }

            $nextExpire = Carbon::parse($today)->addDay($totalDayOfThisMonth);

            if ($this->isPermissionEnabled('round_expire_date')) {
                $nextExpire = (new ExpireDateRoundService())->roundExpireDateForRecharge(now(), $nextExpire);
            }

            if ($this->isPermissionEnabled('round_expire_date_after_d2d_extend_ExpireDate_By_Month')) {
                $nextExpire = (new ExpireDateRoundService())->roundExpireDateForRecharge($today, $nextExpire);
            }

            $actionMessage = ' 1 Month. From ' . $client->expire_date . ' To ' . $nextExpire;
        } else {
            $totalDayOfExpireDate = Carbon::parse($client->expire_date)->lastOfMonth()->format('d');
            $nextExpire = Carbon::parse($client->expire_date)->addDay($totalDayOfExpireDate);

            if ($this->isPermissionEnabled('round_expire_date')) {
                $nextExpire = (new ExpireDateRoundService())->roundExpireDateForRecharge($client->expire_date, $nextExpire);
            }

            if ($this->isPermissionEnabled('round_expire_date_after_d2d_extend_ExpireDate_By_Month')) {
                $nextExpire = (new ExpireDateRoundService())->roundExpireDateForRecharge($client->expire_date, $nextExpire);
            }



            if (globalPermission('always_set_february_last_date_to_march_last_date')) {
                $year = Carbon::parse($client->expire_date)->format('Y');
                $last_date_of_february = Carbon::parse($year . '-2-1')->lastOfMonth();
                $expire_date_month_day = Carbon::parse($client->expire_date)->format('m-d');
                if ($expire_date_month_day == '02-29' || $expire_date_month_day == '02-28') {
                    $nextExpire = $last_date_of_february->copy()->addMonth()->lastOfMonth()->format('Y-m-d');
                }
            }

            $actionMessage = ' 1 Month. From ' . $client->expire_date . ' To ' . $nextExpire;
        }

        return [
            'totalCost' => $totalCost,
            'nextExpire' => $nextExpire,
            'actionDaysMessage' => $actionMessage,
            'totalDay' => null,
            'billingCycleUpdated' => false,
        ];
    }

    /**
     * Calculate recharge with extra days for D2D
     */
    private function calculateWithExtraDays(Client $client, Packages $package, Carbon $expire, Carbon $today, int $extraDays): array
    {
        if (Carbon::parse($client->expire_date)->addDay($extraDays) < $today) {
            return $this->calculateProRatedRecharge($client, $package, $today);
        }

        $nextExpire = Carbon::parse($client->expire_date)->addMonth();
        if ($this->isPermissionEnabled('round_expire_date')) {
            $nextExpire = (new ExpireDateRoundService())->roundDate($client->expire_date);
        }

        return [
            'totalCost' => $package->package_rate,
            'nextExpire' => $nextExpire,
            'actionDaysMessage' => ' 1 Month. From ' . $client->expire_date . ' To ' . $nextExpire,
            'totalDay' => null,
            'billingCycleUpdated' => false,
        ];
    }

    /**
     * Calculate when expired customer should start from today
     */
    private function calculateExpireToday(Client $client, Packages $package, Carbon $expire, Carbon $today): array
    {
        if ($expire < $today) {
            return $this->calculateProRatedRecharge($client, $package, $today);
        }

        $nextExpire = Carbon::parse($client->expire_date)->addMonth();
        if ($this->isPermissionEnabled('round_expire_date')) {
            $nextExpire = (new ExpireDateRoundService())->roundDate($client->expire_date);
        }

        return [
            'totalCost' => $package->package_rate,
            'nextExpire' => $nextExpire,
            'actionDaysMessage' => ' 1 Month. From ' . $client->expire_date . ' To ' . $nextExpire,
            'totalDay' => null,
            'billingCycleUpdated' => false,
        ];
    }

    /**
     * Calculate standard recharge
     */
    private function calculateStandardRecharge(Client $client, Packages $package, Carbon $expire, Carbon $today): array
    {
        // If expired more than a month ago, use pro-rated
        if ($expire < $today && Carbon::parse($client->expire_date)->addMonth() < $today) {
            return $this->calculateProRatedRecharge($client, $package, $today);
        }

        $nextExpire = Carbon::parse($client->expire_date)->addMonth();
        if ($this->isPermissionEnabled('round_expire_date')) {
            $nextExpire = (new ExpireDateRoundService())->roundDate($client->expire_date);
        }

        return [
            'totalCost' => $package->package_rate,
            'nextExpire' => $nextExpire,
            'actionDaysMessage' => ' 1 Month. From ' . $client->expire_date . ' To ' . $nextExpire,
            'totalDay' => null,
            'billingCycleUpdated' => false,
        ];
    }

    /**
     * Calculate pro-rated recharge starting from today
     */
    private function calculateProRatedRecharge(Client $client, Packages $package, Carbon $today): array
    {
        $billingCycle = $client->billing_cycle;
        $billingCycleUpdated = false;
        $newBillingCycle = $billingCycle;

        // Adjust billing cycle if needed
        if (date('t') < $billingCycle) {
            $newBillingCycle = date('t');
            $billingCycleUpdated = true;
        }

        $nextExpire = date('d') > $newBillingCycle
            ? Carbon::parse(date('Y-m-' . $newBillingCycle))->addMonth()
            : Carbon::parse(date('Y-m-' . $newBillingCycle));

        $totalDay = $nextExpire->diffInDays($today) + 1;
        $totalCost = PriceCalculate::calculate($today->daysInMonth, $package->package_rate, $totalDay);
        $actionMessage = 'Total ' . $totalDay . ' days. From ' . $today . ' To ' . $nextExpire;

        return [
            'totalCost' => $totalCost,
            'nextExpire' => $nextExpire,
            'actionDaysMessage' => $actionMessage,
            'totalDay' => $totalDay,
            'billingCycleUpdated' => $billingCycleUpdated,
            'newBillingCycle' => $newBillingCycle,
        ];
    }

    /**
     * Handle sub-reseller billing
     */
    private function handleSubResellerBilling(
        Client $client,
        Pop $pop,
        $popBalances,
        array $rechargeDetails,
        float $totalCost,
        int $resellerId,
        int $resellerBalanceLogId
    ) {
        $subPackage = $client->subpack;

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

        $currentPopBalance = $popBalances[$pop->id] ?? 0;
        $subTotalCost = $this->calculateSubPackageCost($client, $subPackage, $rechargeDetails);

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

        // Update in-memory pop balance to prevent over-usage in the same bulk operation
        $popBalances[$pop->id] = $currentPopBalance - $subTotalCost;

        // Deduct pop balance in database
        Balance::balanceDeductForUserRecharge('pop', $pop->id, $subTotalCost);

        $subResellerAction = "Recharge For " . $rechargeDetails['actionDaysMessage'] .
            " . For package " . $subPackage->name .
            " cost BDT " . $subTotalCost;

        // Handle commission
        if ($subPackage->commission > 0 || $this->isPermissionEnabled('commission_from_manager_pop')) {
            (new CommissionService())->subreseller_commission(
                $subTotalCost,
                $subResellerAction,
                $pop->id,
                $subPackage->commission,
                $subPackage->rate,
                $client->id
            );
        }

        $popBalanceAfterRecharge = $popBalances[$pop->id];

        SubResellerBalanceLogReport::create([
            'reseller_id' => $resellerId,
            'sub_reseller_id' => $pop->id,
            'client_id' => $client->id,
            'action' => $subResellerAction,
            'amount' => $subTotalCost,
            'remarks' => 'Created BY ' . Auth::user()->email,
            'before_balance' => $currentPopBalance,
            'after_balance' => $popBalanceAfterRecharge,
            'reseller_cost' => $totalCost,
            'commission_amount' => getCommissionForSubResellerRecharge($client->id, $subTotalCost),
            'reseller_balance_log_id' => $resellerBalanceLogId,
        ]);

        return true;
    }

    /**
     * Calculate sub-package cost based on settings
     */
    private function calculateSubPackageCost(Client $client, SubPackage $subPackage, array $rechargeDetails): float
    {
        $expire = Carbon::parse($client->expire_date);
        $today = today();

        // D2D recharge always uses full rate
        if ($this->isPermissionEnabled('d2d_recharge_for_reseller')) {
            return $subPackage->rate;
        }

        // Extra day setting
        $extraDays = siteinfo()->d2dactiveday ?? 0;
        if ($extraDays > 0) {
            if (Carbon::parse($client->expire_date)->addDay($extraDays) < $today) {
                return PriceCalculate::calculate($today->daysInMonth, $subPackage->rate, $rechargeDetails['totalDay']);
            }
            return $subPackage->rate;
        }

        // Standard calculation
        if ($this->isPermissionEnabled('recharge_expire_customer_today')) {
            if ($expire < $today && isset($rechargeDetails['totalDay'])) {
                return PriceCalculate::calculate($today->daysInMonth, $subPackage->rate, $rechargeDetails['totalDay']);
            }
            return $subPackage->rate;
        }

        // Default calculation
        if ($expire < $today && Carbon::parse($client->expire_date)->addMonth() < $today && isset($rechargeDetails['totalDay'])) {
            return PriceCalculate::calculate($today->daysInMonth, $subPackage->rate, $rechargeDetails['totalDay']);
        }

        return $subPackage->rate;
    }

    /**
     * Sync client with MikroTik or Radius
     */
    private function syncClient(Client $client): void
    {
        try {
            if (checkAPI()) {
                // $mk = new SyncWithMk();
                ClientSyncJobForSingle::dispatch($client->id);
            } else {
                (new IdEnableDisableController)->enableInRadius($client);
            }
        } catch (\Exception $e) {
            Log::error("Sync error in customer recharge: " . $e->getMessage(), [
                'client_id' => $client->id
            ]);
        }
    }

    /**
     * Queue recharge notifications for background processing
     */
    private function queueRechargeNotifications(array $clientIds): void
    {
        if (empty($clientIds)) {
            return;
        }

        try {
            // Dispatch a job to handle SMS notifications in background
            // This significantly improves response time for bulk recharges
            dispatch(function () use ($clientIds) {
                $this->sendRechargeNotifications($clientIds);
            })->afterResponse();
        } catch (\Exception $e) {
            Log::error("Failed to queue recharge notifications: " . $e->getMessage());
        }
    }

    /**
     * Send recharge notifications (SMS)
     */
    private function sendRechargeNotifications(array $clientIds): void
    {
        $clients = Client::with(['pop.reseller', 'clientsinfo', 'packages'])
            ->whereIn('id', $clientIds)
            ->get();

        foreach ($clients as $client) {
            try {
                if (useResellerSmsGatewayForOwnWhenMainEnabled($client)) {
                    $this->sendOwnResellerRechargeViaResellerGateway($client);
                } else {
                    $resellerRecharge = new ResellerRechargeSms();
                    $resellerRecharge->send($client->id);
                }

                if (checkSettings('main_sms_gateway_for_own_other') === 'disable') {
                    $this->sendOtherResellerSms($client);
                }
            } catch (\Exception $e) {
                Log::error("SMS sending failed for client {$client->id}: " . $e->getMessage());
            }
        }
    }

    /**
     * When main_sms_gateway_for_own_other is enable, customResellerSmsGatewaySetup disable,
     * reseller sms_gateway_type is own and pop sms_send is yes: send recharge from reseller_sms_getways.
     */
    private function sendOwnResellerRechargeViaResellerGateway(Client $client): void
    {
        $resellerSmsGateway = ResellerSmsGetway::with('reseller')
            ->where('reseller_id', $client->pop->reseller_id)
            ->first();

        if (!$resellerSmsGateway) {
            return;
        }

        $smsFormats = json_decode($resellerSmsGateway->sms_formate);
        $customerRecharge = collect($smsFormats)->where('sms_type', 'other_reseller_customer_recharge')->first();

        if ($customerRecharge && $customerRecharge->send_sms === "Yes") {
            (new ResellerRechargeSms())->sendOtherResellerCustomerRechargeSms(
                $client,
                $resellerSmsGateway->sms_gateway,
                $resellerSmsGateway->reseller->name,
                $resellerSmsGateway->reseller->contact,
                $customerRecharge->sms_body,
                $resellerSmsGateway->reseller->id
            );
        }
    }

    /**
     * Send SMS through other reseller gateway
     */
    private function sendOtherResellerSms(Client $client): void
    {
        $resellerSmsGateway = ResellerSmsGetway::with('reseller')
            ->where('reseller_id', $client->pop->reseller_id)
            ->first();

        if (!$resellerSmsGateway) {
            return;
        }

        $smsFormats = json_decode($resellerSmsGateway->sms_formate);
        $customerRecharge = collect($smsFormats)->where('sms_type', 'other_reseller_customer_recharge')->first();

        if ($customerRecharge && $customerRecharge->send_sms === "Yes") {
            (new ResellerRechargeSms())->sendOtherResellerCustomerRechargeSms(
                $client,
                $resellerSmsGateway->sms_gateway,
                $resellerSmsGateway->reseller->name,
                $resellerSmsGateway->reseller->contact,
                $customerRecharge->sms_body,
                $resellerSmsGateway->reseller->id
            );
        }
    }

    /**
     * Legacy method - kept for backward compatibility
     * @deprecated Use processBulkRecharge instead
     */
    public function doCustomerRecharge($id, $uniqueString)
    {
        $client = Client::with(['pop.reseller', 'pop.nas', 'packages', 'subpack'])->find($id);

        if (!$client) {
            return 'client_not_found';
        }

        $this->cacheRequiredSettings();

        $resellerBalances = Balance::where('type', 'reseller')
            ->where('type_id', $client->pop->reseller_id)
            ->pluck('amount', 'type_id');

        $popBalances = Balance::where('type', 'pop')
            ->where('type_id', $client->pop_id)
            ->pluck('amount', 'type_id');

        // Update status to active
        $client->clients_status = 'active';
        $client->save();

        return $this->doCustomerRechargeOptimized($client, $uniqueString, $resellerBalances, $popBalances);
    }

    /**
     * Legacy SMS method - kept for backward compatibility
     * @deprecated Use queueRechargeNotifications instead
     */
    public function resellerCustomerRechargeSms($request)
    {
        $this->sendRechargeNotifications($request->ids);
    }

    /**
     * Handle billing cycle change
     */
    public function doBillingCycleChange($request)
    {
        // Implementation placeholder
        return ['status' => 'success', 'message' => 'Billing cycle change completed'];
    }

    /**
     * Get client info data for API
     */
    public function clientInfoData($id)
    {
        $client = Client::find($id);

        if (!$client) {
            return response()->json(['error' => 'Client not found'], 404);
        }

        $expireBd = Carbon::parse($client->expire_date)->format('d-M-Y');
        $expirePd = Carbon::parse($client->expire_date)->addDay($client->payment_dadeline)->format('d-M-Y');

        return response()->json([
            'expire_bd' => $expireBd,
            'expire_pd' => $expirePd,
        ]);
    }
}
