<?php

namespace App\Classes\Modules\Billplzs\ControllersLogic;

use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;

use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Http\Resources\TransactionResource;
use App\Models\Booking;
use App\Models\User;
use App\Models\Wallet;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class CallbackBillplzLogic
{
    /** @var GetBillplzBill */
    private $getBillplzBill;

    /** @var FetchesTransaction */
    private $fetchesTransaction;

    /** @var UpdatesTransactionStatus */
    private $updatesTransactionStatus;

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

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

    /**
     * CallbackBillplzLogic constructor.
     * @param GetBillplzBill $getBillplzBill
     * @param FetchesTransaction $fetchesTransaction
     * @param UpdatesTransactionStatus $updatesTransactionStatus
     * @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
     * @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
     */
    public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor)
    {
        $this->getBillplzBill = $getBillplzBill;
        $this->fetchesTransaction = $fetchesTransaction;
        $this->updatesTransactionStatus = $updatesTransactionStatus;
        $this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
        $this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
    }


    /**
     * @param Request $request
     * @return bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
     * @throws MalformedRequestException
     * @throws ResourceNotFoundException
     * @throws \App\Classes\Exceptions\InternalServerErrorException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function execute(Request $request)
    {
        $billplzXSignatureObject = new BillplzXSignatureObject($request);

        if(!$billplzXSignatureObject->isValidSignature()){
            throw new MalformedRequestException('Billplz Payment validation failed.');
        }

        $billPlz = $this->getBillplzBill->execute($billplzXSignatureObject->getBillPlzId());

        if(!$billPlz) throw new ResourceNotFoundException('Billplz bill not found.');

        $transaction = $this->fetchesTransaction->execute(['payment_reference' => $billplzXSignatureObject->getBillPlzId()]);

        $invoice = $transaction->owner;
        $packingList = $invoice->owner;
        $order = $packingList->owner;

        $status = ApprovalStatus::PENDING_VERIFICATION;

        if($billPlz->state === 'paid') {
            $status = ApprovalStatus::APPROVED;
        }

        if($billPlz->state === 'due') {
            $status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION;
        }

        $token = Auth::fromUser(User::find(1));
        $request->headers->set('Authorization', 'Bearer '.$token);

        $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED);

        if(($invoice->amount - $transaction->amount) < 0.01) {
            $this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);

            $packingList->status = ApprovalStatus::APPROVED;
            $packingList->save();

            if(app()->environment('production')){
                $this->updateDoFromVTPortalProcessor->execute($packingList);
                $this->updateDoFromYDPortalProcessor->execute($packingList);
            }
        }




        return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $order->reference, 'transaction' => $transaction, 'status' => $status]);
    }
}
