<?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);

        $resellerBalanceLogId =  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,
            ]
        );

        return $resellerBalanceLogId->id;
    }

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

        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),
                'reseller_balance_log_id'     => $resellerBalanceLogId,
            ]
        );
    }



    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);



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

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

                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,
                        $resellerBalanceLogId
                    );
                }

                $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;
    }
}
