<?php

namespace App\Classes\Modules\Billplzs\Processors;

use Illuminate\Http\Request;
use App\Models\Wallet;
use App\Models\Group;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use Illuminate\Support\Facades\Log;

class CallbackBillplzProcessor
{
    /** @var UpdatesTransactionStatus */
    private $updatesTransactionStatus;

    /** @var UpdateDoFromVTPortalProcessor */
    private $updateDoFromVTPortalProcessor;

    /** @var UpdateDoFromYDPortalProcessor */
    private $updateDoFromYDPortalProcessor;

    /** @var UpdatesWalletBalance */
    private $updatesWalletBalance;

    /** @var CreatePaymentTransactionProcessor */
    private $createPaymentTransactionProcessor;

    /** @var ReleaseGoodsToCustomerProcessor */
    private $releaseGoodsToCustomerProcessor;

    /**
     * CreateUserProcessor constructor.
     * @param UpdatesTransactionStatus $updatesTransactionStatus
     * @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
     * @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
     * @param UpdatesWalletBalance $updatesWalletBalance
     * @param CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
     * @param ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
     */
    public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor, ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor)
    {
        $this->updatesTransactionStatus = $updatesTransactionStatus;
        $this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
        $this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
        $this->updatesWalletBalance = $updatesWalletBalance;
        $this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
        $this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
    }


    /**
     * @param Request $request
     * @throws \App\Classes\Exceptions\MalformedRequestException
     */
    public function execute($transaction, $status)
    {
        $invoice = $transaction->owner;
        $packingList = $invoice->owner;

        $proceed = $this->checkForGroupPayment($transaction);
        if(!$proceed) return false;

        $this->updatesTransactionStatus->execute($transaction, $status);

        // check if is wallet top up
        if ($transaction->owner instanceof Wallet && $status === ApprovalStatus::APPROVED) {

            $this->updatesWalletBalance->execute($transaction->owner, $transaction->amount);

            $group = Group::where('reference', $transaction->payment_reference)->first();

            // check if is group payment
            if ($group) {
                foreach ($group->groupTransactions as $groupTransaction) {
                    $invoice = $groupTransaction->transaction;
                    if($invoice->status !== ApprovalStatus::COMPLETED){
                        $paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);

                        if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
                            $pL = $invoice->owner;
                            $this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
                        }
                    }
                }

                $group->status = $status;
                $group->save();
            }
        }

        if (!$transaction->owner instanceof Wallet) {
            $this->releaseGoodsToCustomerProcessor->execute($packingList, $invoice);
        }

        return true;
    }

    private function checkForGroupPayment($transaction){
        //This check is targetting group payment that expired and soft deleted
        //command:check-storage-invoices must already run for this part of the code to work properly
        $group = Group::withTrashed()->where('reference', $transaction->payment_reference)->first();
        if ($group) {
            $totalAmountToBePaid = 0;
            $actualAmountPaid = $transaction->amount;

            foreach ($group->groupTransactions as $groupTransaction) {
                $invoice = $groupTransaction->transaction;
                if($invoice->status !== ApprovalStatus::COMPLETED){
                    $totalAmountToBePaid += $invoice->amount;
                }
            }

            if(($totalAmountToBePaid - $actualAmountPaid) < 0.01){

            }
            else{
                Log::channel('storage_invoices')->info('Total amount from current transaction: '.$totalAmountToBePaid); //cief todo: to be removed
                Log::channel('storage_invoices')->info('Total amount from paid transaction: '.$transaction->amount); //cief todo: to be removed
                return false;
            }
        }
        return true;
    }
}
