<?php

namespace App\Classes\Modules\Transactions\Processors;


use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Transaction;

class CreatePurchaseOrderTransactionProcessor
{

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

    /** @var CreatesTransaction */
    private $createsTransaction;

    /** @var CreatesTransactionDetail */
    private $createsTransactionDetail;

    /** @var UpdatesTransaction */
    private $updatesTransaction;

    /** @var DeletesTransactionDetails */
    private $deletesTransactionDetails;

    /**
     * CreatePurchaseOrderTransactionProcessor constructor.
     * @param UpdatesTransactionStatus $updatesTransactionStatus
     * @param CreatesTransaction $createsTransaction
     * @param CreatesTransactionDetail $createsTransactionDetail
     * @param UpdatesTransaction $updatesTransaction
     * @param DeletesTransactionDetails $deletesTransactionDetails
     */
    public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, DeletesTransactionDetails $deletesTransactionDetails)
    {
        $this->updatesTransactionStatus = $updatesTransactionStatus;
        $this->createsTransaction = $createsTransaction;
        $this->createsTransactionDetail = $createsTransactionDetail;
        $this->updatesTransaction = $updatesTransaction;
        $this->deletesTransactionDetails = $deletesTransactionDetails;
    }


    /**
     * @param Booking $booking
     * @param TransactionObject $object
     * @param bool $append
     * @return Transaction|\Illuminate\Database\Eloquent\Model
     * @throws \App\Classes\Exceptions\MalformedRequestException
     */
    public function execute(Booking $booking, TransactionObject $object, bool $append = false){
        /** @var Transaction $transaction */
        $transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first();

        if($append){
            $object->setAmount($transaction->amount + $object->getAmount());
            $object->setOriginalAmount($transaction->original_amount + $object->getOriginalAmount());
        }

        !$transaction ? $transaction = $this->createsTransaction->execute($booking, $object) : $transaction = $this->updatesTransaction->execute($transaction, $object);

        $this->updatesTransactionStatus->execute($transaction, (float) number_format($object->getAmount(), 2, '.', '')  === (float) number_format((float)$booking->fix_amount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION);

        if(!$append){
            $this->deletesTransactionDetails->execute($transaction);
        }

        foreach ($object->getDetails() as $product){
            $this->createsTransactionDetail->execute($transaction, $product);
        }

        return $transaction;
    }

}
