<?php

namespace App\Services;

use App\Http\Controllers\Reseller\ResellerRechargeController;
use App\Models\Balance;
use App\Models\Client;
use App\Models\Income;
use App\Models\IncomeHead;
use App\Models\Packages;
use App\Models\Pop;
use App\Models\ReselleBalanceLogReport;
use App\Models\Reseller;
use App\Models\ResellerClientBillPayment;
use App\Models\ResellerRechargeReport;
use App\Models\SubResellerBalanceLogReport;
use App\Models\SubResellerRechargeReport;
use App\Models\User;
use App\Models\UserAccounting;
use Carbon\Carbon;
use Exception;
use Facade\Ignition\Support\Packagist\Package;
use Illuminate\Support\Facades\DB;

class ResellerClientOlineRechargeService{
// payment_gateway is the method like Bkash Online or pgw

    public function resellerClientPayBillPaymentProcess($client_id, $amount, $trx_id, $user_id,$payment_gateway)
    {
        DB::beginTransaction();
        try{

           $createResellerClientBillPaymentLog =  $this->createResellerClientBillPaymentLog($client_id, $amount, $trx_id, $user_id);

           if($createResellerClientBillPaymentLog){
                return ['status' => 'duplicate_error', 'message' => $createResellerClientBillPaymentLog['message']];
           }

            $this->addPaymentAmountToClientTable($client_id,$amount);

            $client = Client::with('pop')->find($client_id);

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

                $this->doRechargeInSubReseller($amount,$user_id,$client_id,$payment_gateway,$client->pop->id,'pop',$trx_id);
            }


            $this->doRechargeInReseller($client->pop->reseller_id, $amount, $user_id, $client_id, $trx_id, $payment_gateway);

            $this->rechargeClientWithUnPaidAmount($client_id);

            DB::commit();
            return ['status' => 'success', 'message' => 'success'];

        }catch(Exception $e){

            DB::rollBack();
            return ['status' => 'duplicate_error', 'message' => $e->getMessage()];
        }

    }

    public function createResellerClientBillPaymentLog($client_id, $amount, $trx_id, $payment_by)
    {
        $checkDuplicateTrx = ResellerClientBillPayment::where('trx_id',$trx_id)->first();
        if($checkDuplicateTrx){
            return [
                'status' => "Failed",
                'message' => "Duplicate Trx Id",
            ];
        }

        $resellerClientOnlinePayment = new ResellerClientBillPayment();
        $resellerClientOnlinePayment->client_id = $client_id;
        $resellerClientOnlinePayment->amount = $amount;
        $resellerClientOnlinePayment->trx_id = $trx_id;
        $resellerClientOnlinePayment->user_id = $payment_by;
        $resellerClientOnlinePayment->save();


    }

    public function addPaymentAmountToClientTable($client_id, $amount){
        $client = Client::find($client_id);
        $client->un_recharge_amount = $client->un_recharge_amount + $amount;
        $client->save();
    }



    public function doRechargeInReseller($reseller_id,$amount,$user_id,$clientUserId,$trx_id,$payment_method)
    {

        $income_id = $this->addRechargeToIncome($amount,$clientUserId);
        $this->addOrUpdateBalanceResellerOrPop("reseller",$reseller_id,$amount);
        $this->addResellerRechargeBalanceLogAddUserAccounting($amount,$user_id,$clientUserId, $payment_method, $reseller_id, "reseller",$income_id,$trx_id);
    }


    public function addOrUpdateBalanceResellerOrPop($type,$type_id,$amount){
        $balance = Balance::where('type', $type)
                                    ->where('type_id', $type_id)
                                    ->first();
        $old_balance = $balance->amount;

        if($balance == null){

            Balance::create([
                'type' => $type,
                'type_id' => $type_id,
                'amount'  => $amount,
                'remarks' => "create reseller account"
            ]);
        }else{

            Balance::where('type', $type)
                    ->where('type_id', $type_id)
                    ->update([
                        'amount' => $balance['amount'] + $amount
                    ]);

        }

        $balance = Balance::where('type', $type)
                                    ->where('type_id', $type_id)
                                    ->first();

        return [
            'oldBalance' => $old_balance,
            'newBalance' => $balance->amount,
        ];

    }

    public function addRechargeToIncome($amount,$userId)
    {
        $income_type = IncomeHead::find(12);

        $income =   Income::create([
            'name' => $income_type->name ?? 'Bill Payment',
            'date' => now(),
            'amount' => $amount,
            'description' => 'Bill Payment from reseller customer : ' . $userId,
            'incomeHead' => 11
        ]);

        return $income->id;
    }

    public function addResellerRechargeBalanceLogAddUserAccounting( $paid_amount,  $user_id,  $client_id, $payment_method, $type_id, $type, $income_id,$trx_id)
    {
        $user = User::find($user_id);

        $client = Client::with('clientsinfo')->find($client_id);

        $actions = 'Manager recharge received from online client by ' . $user->name .' '. $payment_method. ' from '. $client->clientsinfo->clients_name ;

        UserAccounting::userAcStore($paid_amount, $actions, $client->id, "", "", $user_id);

        $after_amount = Balance::where('type', $type)
                        ->where('type_id', $type_id)
                        ->first()->amount;



        $this->createResellerRecharge($type_id,$paid_amount,$after_amount, $actions, $user_id, $income_id,"online",$payment_method,null,$trx_id);


        clearCache('reseller');

    }

    public function createResellerRecharge($type_id, $paid_amount, $after_amount, $remark, $user_id, $income_id, $payment_type, $payment_gateway, $payment_gateway_transaction_id, $txn_id)
    {
        ResellerRechargeReport::create([
            'reseller_id'                       => $type_id,
            'amount'                            => $paid_amount,
            'after_recharge_balance'            => $after_amount,
            'remarks'                           => $remark ?? '',
            'user_id'                           => $user_id,
            'income_id'                         => $income_id,
            'paid_amount'                       => $paid_amount,
            'payment_type'                      => $payment_type,
            'payment_gateway'                   => $payment_gateway,
            'payment_gateway_transaction_id'    => $payment_gateway_transaction_id,
            'txn_id'                            => $txn_id,
        ]);
    }

    public function createResellerBalanceLog($reseller_id,$pop_id,$client_id,$action,$reseller_amount,$before_reseller_balance,$after_reseller_balance){

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

        ReselleBalanceLogReport::create(
            [
                'reseller_id' => $reseller_id,
                'client_id'   => $client_id,
                'action'      => $action,
                'amount'      => $reseller_amount,
                'remarks'     => 'Created BY Client Recharge',
                'reseller_balance' => $before_reseller_balance,
                'after_balance' => $after_reseller_balance,
                'uniqueId'    =>  createUUID(),
                'pop_id'       => $pop_id,
                'reseller_commission_percentage' => $pop->reseller->commission_percentage,
                'pop_commission_percentage' => $pop->commission_percentage,
            ]
        );
    }

    public function createSubResellerBalanceLog($reseller_id,$pop_id,$client_id,$action,$sub_reseller_cost,$before_pop_balance,$after_pop_balance,$reseller_cost){

        SubResellerBalanceLogReport::create(
            [
                'reseller_id'       => $reseller_id,
                'sub_reseller_id'   => $pop_id,
                'client_id'         => $client_id,
                'action'            => $action,
                'amount'            => $sub_reseller_cost,
                'remarks'           => 'Created BY Client Recharge',
                'before_balance'    => $before_pop_balance,
                'after_balance'    => $after_pop_balance,
                'reseller_cost' => $reseller_cost,
                'commission_amount' => getCommissionForSubResellerRecharge($client_id,$sub_reseller_cost),
            ]
        );
    }



    public function doRechargeInSubReseller( $paid_amount,  $user_id,  $client_id, $payment_method, $type_id, $type, $trx_id){

        $this->addOrUpdateBalanceResellerOrPop($type,$type_id,$paid_amount);

        $user = User::find($user_id);

        $client = Client::with('clientsinfo')->find($client_id);

        $actions = 'Sub Manager recharge received from online client by ' . $user->name .' '. $payment_method. ' from '. $client->clientsinfo->clients_name ;

        $after_amount = Balance::where('type', $type)
                                    ->where('type_id', $type_id)
                                    ->first()->amount;


        $this->createSubResellerRecharge($type_id,$paid_amount,$after_amount, $actions, $user_id, "online",$payment_method,null,$trx_id);

        clearCache('pop');
    }

    public function createSubResellerRecharge($type_id,$paid_amount,$after_amount,$remarks,$user_id,$payment_type,$payment_gateway,$payment_gateway_transaction_id,$trx_id)
    {

        SubResellerRechargeReport::create([
            'pop_id'                            => $type_id,
            'amount'                            => $paid_amount,
            'after_recharge_balance'            => $after_amount,
            'remarks'                           => $remarks ?? '',
            'user_id'                           => $user_id,
            'payment_type'                      => $payment_type,
            'payment_gateway'                   => $payment_gateway,
            'payment_gateway_transaction_id'    => $payment_gateway_transaction_id,
            'txn_id'                            => $trx_id,
        ]);

    }

    public function rechargeClientWithUnPaidAmount($client_id)
    {
        $client = Client::with('pops.reseller','packages','subpack')->find($client_id);
        $client_payment_amount = 0;
        $subReseller =  false;

        if($client->pops->subreseller == "yes"){
            if(isset($client->subpack)){
                $client_payment_amount = $client->subpack->client_payment_amount;
                $subReseller = true;
            }
        }else{
            if(isset($client->packages)){
                $client_payment_amount = $client->packages->client_payment_amount;
            }
        }

        if(globalPermission('setClientPaymentAmountToClient')){
            $client_payment_amount = $client->client_payment_amount;
        }


        if($client_payment_amount > 0){
            $unRechargeAmount = $client->un_recharge_amount;
            while($unRechargeAmount >= $client_payment_amount){

                $newClintObject = Client::find($client_id);
                $newClintObject->un_recharge_amount = $client->un_recharge_amount - $client_payment_amount;
                $newClintObject->save();

                $action =  $this->getCommentAndChangeExpireDate($client->id);

                if($subReseller){
                    $popBalanceDeduct = $this->addOrUpdateBalanceResellerOrPop('pop',$client->pop->id,-$client->subpack->rate);
                    $this->createSubResellerBalanceLog($client->pop->reseller_id, $client->pop->id, $client->id, $action, $client->subpack->rate,
                                                        $popBalanceDeduct['oldBalance'], $popBalanceDeduct['newBalance'], $client->packages->package_rate);
                }

                $resellerBalanceDeduct = $this->addOrUpdateBalanceResellerOrPop('reseller',$client->pop->reseller_id,-$client->packages->package_rate);

                $this->createResellerBalanceLog($client->pop->reseller_id,$client->pop->id,$client->id, $action, $client->packages->package_rate,
                                                $resellerBalanceDeduct['oldBalance'],$resellerBalanceDeduct['newBalance']);

                $unRechargeAmount = Client::find($client_id)->un_recharge_amount;


            }
        }


    }


    public function getCommentAndChangeExpireDate($clientId)
    {
        $user = Client::find($clientId);

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

        if (checkSettings('recharge_expire_customer_today') == 'enable') {
            if ($expire < today()) {
                $currentDate = today();
                $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($currentDate) + 1;
                $action_days_message        = 'Total ' . $totalDay . ' days. From ' . $currentDate . ' To ' . $nextExpire;

            } else {
                $nextExpire = Carbon::parse($user->expire_date)->addMonth();
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
            }
        } else {
            if ($expire < today() && Carbon::parse($user->expire_date)->addMonth() < today()) {
                $currentDate = 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($currentDate) + 1;
                $action_days_message        = 'Total ' . $totalDay . ' days. From ' . $currentDate . ' To ' . $nextExpire;


            } else {
                $nextExpire = Carbon::parse($user->expire_date)->addMonth();
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
            }
        }

        $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() ) {
                $nextExpire = Carbon::parse(today())->addDay(29);
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
          }else{
                $nextExpire = Carbon::parse($user->expire_date)->addDay(30);
                $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);
                $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);
                $action_days_message = ' 1 Month. From ' . $user->expire_date . ' To ' . $nextExpire;
          }
        }

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

        return $action_days_message;
    }

}
