<?php

namespace App\Services;

use Carbon\Carbon;
use App\Models\Pop;
use App\Models\Client;
use App\Models\Balance;
use App\Models\Packages;
use App\Models\SubPackage;
use Illuminate\Http\Request;
use App\Services\ExpireCheck;
use App\Models\CustomerAccount;
use App\Services\ClientServices;
use App\Services\PriceCalculate;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Models\ReselleBalanceLogReport;
use App\Models\SubResellerBalanceLogReport;
use App\Http\Controllers\BillGenerateController;
use App\Http\Controllers\SessionRefreshController;

class BillingCycleChange
{

    protected $billCycleChangeIncomeHead = 3;

    public function billingCycleChange($pop, $user, $newBillingDate, $uniqueString)
    {

        $exp = Carbon::parse($user->expire_date);
        $currentBillingDate = $user->billing_cycle;



        if (checkSettings('expire_billing_change_today_from_billing_date') == 'enable' && $exp < today()) {

            $currentBillingDate = today()->day;
            if ($currentBillingDate < $newBillingDate) {

                $total_day = ($newBillingDate - $currentBillingDate) + 1;
                $new_expire = today()->addDay($total_day - 1);
            } else {

                $date = date($newBillingDate . '-' . today()->month . '-' . today()->year);
                $new_expire = Carbon::parse($date)->addMonth();
                $total_day = today()->diffInDays($new_expire) + 1;
            }
        } else {

            if (date('Y') == $exp->year) {
                if ($currentBillingDate < $newBillingDate) {

                    $total_day = $newBillingDate - $currentBillingDate;
                    $new_expire = $exp->addDay($total_day);
                } else {

                    $date = date($newBillingDate . '-' . $exp->month . '-' . $exp->year);
                    $new_expire = Carbon::parse($date)->addMonth();

                    $total_day = $exp->diffInDays($new_expire);
                }
            } elseif (date('Y') > $exp->year) {

                $date = date($newBillingDate . '-' . $exp->month . '-' . $exp->year);
                $new_expire = Carbon::parse($date)->addMonth();

                $total_day = $exp->diffInDays($new_expire);
            } else {

                if (date('Y') + 1 == $exp->year) {

                    if ($currentBillingDate < $newBillingDate) {

                        $total_day = $newBillingDate - $currentBillingDate;
                        $new_expire = $exp->addDay($total_day);
                    } else {

                        $date = date($newBillingDate . '-' . $exp->month . '-' . $exp->year);
                        $new_expire = Carbon::parse($date)->addMonth();

                        $total_day = $exp->diffInDays($new_expire);
                    }
                } else {
                    $date = date($newBillingDate . '-' . $exp->month . '-' . $exp->year);
                    $new_expire = Carbon::parse($date)->addMonth();

                    $total_day = $exp->diffInDays($new_expire);
                }
            }
        }

        // d2d extend after days for billing cycle change
        // $extra_day_for_day_day = (isset(siteinfo()->d2dactiveday) ? siteinfo()->d2dactiveday : 0);

        // if($extra_day_for_day_day > 0){
        //   if (Carbon::parse($user->expire_date)->addDay($extra_day_for_day_day) < today() ) {
        //     $currentBillingDate = today()->day;

        //     if ($currentBillingDate <= $newBillingDate) {
        //       $total_day = $newBillingDate - $currentBillingDate;
        //       $new_expire = today()->addDay($total_day);
        //       $total_day = $total_day + 1;
        //     } else {

        //       $date = date($newBillingDate . '-' . today()->month . '-' . today()->year);
        //       $new_expire = Carbon::parse($date)->addMonth();
        //       $total_day = today()->diffInDays($new_expire);
        //       $total_day = $total_day + 1;
        //     }
        //   }

        // }


        if (date('m') == '02' && checkSettings('february_add_2_days') == 'enable' && $new_expire > today()->lastOfMonth()) {
            $total_day = $total_day + 2;
        }




        $days_in_month = Carbon::parse($new_expire)->daysInMonth;

        $reseller_cost = PriceCalculate::calculate($days_in_month, $user->packages->package_rate, $total_day);

        $sub_reseller_cost = $user->pop->subreseller == 'yes' ? PriceCalculate::calculate($days_in_month, $user->subpack->rate, $total_day) : 0;


        // dd($user);
        if (globalPermission('check_client_balance_before_package_billing_date_change') && $user->pop->reseller->reseller_type == 'own') {
            // Get customer's advance balance (credit)

            $advanceBalance = $user->customerAccount->dueAmount <= 0
                ? abs($user->customerAccount->dueAmount)
                : 0;

            $billingCycleChangeCost = $reseller_cost;

            if ($advanceBalance < $billingCycleChangeCost) {

                return "Insufficient balance client";

            }
        }
        //kalam
        if ($pop->bill_generate == "yes") {
            // dd($reseller_cost, "check");
            if ($user->customerAccount->dueAmount < 0 &&  abs($user->customerAccount->dueAmount) >= $reseller_cost) {

                $status = $this->customer_bill_cycle_change_for_advanced_balance($user, $reseller_cost, $sub_reseller_cost, $total_day, $new_expire, $newBillingDate, $uniqueString);
            } elseif ($user->customerAccount->dueAmount < 0 && abs($user->customerAccount->dueAmount) < $reseller_cost) {

                $status = $this->customer_bill_cycle_change_for_advanced_balance_and_extra_amount($user, $reseller_cost, $sub_reseller_cost, $total_day, $new_expire, $newBillingDate, $uniqueString);
            } else {

                $status = $this->reseller_billing_cycle_change_process($user, $total_day, $new_expire, $newBillingDate, $reseller_cost, $uniqueString);
            }
        } else {

            // dd($reseller_cost, "check df");
            $status = $this->reseller_billing_cycle_change_process($user, $total_day, $new_expire, $newBillingDate, $reseller_cost, $uniqueString);
        }


        $client = Client::with('pop')->find($user->id);
        if (globalPermission('RadiusExpiration')) {

            (new ExpirationService())->handleExpiration($client->userid, $exp, $client->payment_dadeline, $client->pop->experity_check);
        }



        return $status;
    }

    public function customer_bill_cycle_change_for_advanced_balance($user, $reseller_cost, $sub_reseller_cost, $total_day, $new_expire, $newBillingDate, $uniqueString)
    {

        $action = "Billing Cycle Changed. For Package: " . $user->packages->package_name .
            " . Expire: " . $new_expire .
            " Total " . $total_day .
            " days cost BDT " . $reseller_cost .
            ". Cusomer has advanced balance so not deducted.";

        $bill_for_billing_cycle_change = (new CustomerAccountService)->customer_account_update($user, $reseller_cost, 'Customer Billing Cycle Change', 'billing_cycle_change');

        $resellerBalanceLogId = $this->update_reseller_balance_and_log_report($user, $new_expire, $action, 0, $newBillingDate, $uniqueString, $bill_for_billing_cycle_change->id);

        if ($user->pop->subreseller == 'yes') {
            $this->update_sub_reseller_balance_and_log_report($user, $action, 0, 0, $resellerBalanceLogId);
        }
    }



    public function customer_bill_cycle_change_for_advanced_balance_and_extra_amount($user, $reseller_cost, $sub_reseller_cost, $total_day, $new_expire, $newBillingDate, $uniqueString)
    {

        $customer_advanced_balance = $user->customerAccount->dueAmount < 0 ? abs($user->customerAccount->dueAmount) : 0;

        $reseller_adjustable_amount = abs($reseller_cost == 0 ? 0 : $customer_advanced_balance - $reseller_cost);

        if ($reseller_adjustable_amount > floatval(Balance::getBalance('reseller', $user->pop->reseller_id))) { //reseller balance checking
            return 'reseller_balance_error';
        }

        $action = "Billing Cycle Changed. From Package: " . $user->packages->package_name .
            " . Expire: " . $new_expire .
            " Total  " . $total_day .
            " days cost BDT " . $reseller_cost .
            ". Cusomer advanced balance: " . abs($user->customerAccount->dueAmount) .
            ".Reseller Deductable Amount: " . $reseller_adjustable_amount;

        $bill_for_billing_cycle_change = (new CustomerAccountService)->customer_account_update($user, $reseller_cost, 'Customer Billing Cycle Change', 'billing_cycle_change', $reseller_adjustable_amount, $this->billCycleChangeIncomeHead);


        $resellerBalanceLogId = $this->update_reseller_balance_and_log_report($user, $new_expire, $action, $reseller_adjustable_amount, $newBillingDate, $uniqueString, $bill_for_billing_cycle_change->id);

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

            $sub_reseller_adjustable_amount = abs($sub_reseller_cost == 0 ? 0 : $customer_advanced_balance - $sub_reseller_cost);

            $action = "Billing Cycle Changed. From Package: " . $user->subpack->package_name .
                " . Expire: " . $new_expire .
                " Total  " . $total_day .
                " days cost BDT " . $sub_reseller_cost .
                ". Cusomer advanced balance: " . abs($user->customerAccount->dueAmount) .
                ".Reseller Deductable Amount: " . $sub_reseller_adjustable_amount;

            $this->update_sub_reseller_balance_and_log_report($user, $action, $sub_reseller_adjustable_amount, $reseller_adjustable_amount, $resellerBalanceLogId);
        }
    }


    public function reseller_billing_cycle_change_process($user, $total_day, $new_expire, $newBillingDate, $reseller_cost, $uniqueString)
    {

        $action = "Billing Cycle Changed. For Package: " . $user->packages->package_name .
            " . Expire Date: " . $new_expire .
            " Total " . $total_day .
            " days cost BDT " . $reseller_cost;

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

        if ($resellerBalance >= $reseller_cost) {



            if (isset($bill)) {
                $resellerBalanceLogId = $this->update_reseller_balance_and_log_report($user, $new_expire, $action, $reseller_cost, $newBillingDate, $uniqueString, $bill->id);
            } else {
                $resellerBalanceLogId = $this->update_reseller_balance_and_log_report($user, $new_expire, $action, $reseller_cost, $newBillingDate, $uniqueString);
            }


            if ($user->pop->subreseller == 'no' && $user->pop->bill_generate == 'yes') {

                $bill = (new CustomerAccountService)->customer_account_update($user, $reseller_cost, 'Customer Billing Cycle Change', 'billing_cycle_change', $reseller_cost, $this->billCycleChangeIncomeHead);
            } elseif ($user->pop->subreseller == 'yes') {

                $status = $this->sub_reseller_billing_cycle_change_process($user, $total_day, $new_expire, $reseller_cost, $resellerBalanceLogId);
            }

            return isset($status) ? $status : 'success';
        } else {
            return 'error';
        }
    }

    public function update_sub_reseller_balance_and_log_report($user, $action, $sub_reseller_cost, $reseller_cost = 0, $resellerBalanceLogId = null)
    {

        SubResellerBalanceLogReport::create(
            [
                'reseller_id'       => $user->pop->reseller_id,
                'sub_reseller_id'   => $user->pop->id,
                'client_id'         => $user->id,
                'action'            => $action,
                'amount'            => $sub_reseller_cost,
                'remarks'           => 'Created BY ' . Auth::user()->email,
                'reseller_cost' => $reseller_cost,
                'commission_amount' => getCommissionForSubResellerRecharge($user->id, $sub_reseller_cost),
                'reseller_balance_log_id' => $resellerBalanceLogId,
            ]
        );

        if (isset($user->subpack) && $user->subpack->commission > 0 || globalPermission('commission_from_manager_pop')) {
            (new CommissionService())->subreseller_commission($sub_reseller_cost, $action, $user->pop->id, $user->subpack->commission, $user->subpack->rate, $user->id);
        }

        if ($sub_reseller_cost > 0) {
            Balance::balanceDeductForUserRecharge('pop', $user->pop->id, $sub_reseller_cost);
        }
    }


    public function update_reseller_balance_and_log_report($user, $new_expire_date, $action, $reseller_cost, $newBillingDate, $uniqueString, $bill_id = null)
    {

        Client::where('id', $user->id)
            ->update([
                'expire_date'   => $new_expire_date,
                'billing_cycle' => $newBillingDate
            ]);

        if ($user->packages->commission > 0 || globalPermission('commission_from_manager_pop')) {
            (new CommissionService())->reseller_commission($reseller_cost, $action, $user->pop->reseller_id, $user->packages->commission, $user->packages->package_rate, $user->id, 'bill', $bill_id);
        }

        if ($reseller_cost > 0) {
            Balance::balanceDeductForUserRecharge('reseller', $user->pop->reseller_id, $reseller_cost);
        }
        $cur_balance = Balance::whereType('reseller')->whereType_id($user->pop->reseller_id)->first('amount');

        $pop = Pop::with('reseller')->find($user->pop_id);

        // Use the uniqueString directly (already includes user ID, timestamp, and microtime)
        // This prevents duplicate entry errors when same user is processed multiple times
        $resellerBalanceLogId = ReselleBalanceLogReport::create([
            'reseller_id' => $user->pop->reseller_id,
            'client_id'   => $user->id,
            'action'      => $action,
            'amount'      => $reseller_cost,
            'remarks'     => ' BY ' . Auth::user()->email,
            'reseller_balance'     => $cur_balance->amount,
            'uniqueId'      => $uniqueString,
            'pop_id'        => $user->pop_id,
            'commission_amount' => getCommissionForResellerRecharge($user->id, $reseller_cost),
            'reseller_commission_percentage' => $pop->reseller->commission_percentage,
            'pop_commission_percentage' => $pop->commission_percentage,
        ]);

        return $resellerBalanceLogId->id;
    }



    public function sub_reseller_billing_cycle_change_process($user, $total_day, $new_expire, $resellerCost, $resellerBalanceLogId = null)
    {

        $reseller_id = $user->pop->reseller_id;

        $SR_package = SubPackage::where('id', $user->sub_package_id)->first();
        $days_in_month = Carbon::parse($new_expire)->daysInMonth;

        $sub_reseller_cost = PriceCalculate::calculate($days_in_month, $SR_package->rate, $total_day);

        $SubResellerAction = "Billing Cycle Changed. For Package: " . $SR_package->name .
            " . Expire Date: " . $new_expire .
            " Total " . $total_day .
            " days cost BDT " . $sub_reseller_cost;

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

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

        $this->update_sub_reseller_balance_and_log_report($user, $SubResellerAction, $sub_reseller_cost, $resellerCost, $resellerBalanceLogId);

        if ($user->pop->bill_generate == 'yes') {
            (new CustomerAccountService)->customer_account_update($user, $sub_reseller_cost, 'Customer Billing Cycle Change', 'billing_cycle_change', $sub_reseller_cost, $this->billCycleChangeIncomeHead);
        }
    }
}
