<?php


namespace App\Classes\Modules\Transactions\ControllersLogic;

use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Storage;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
use App\Classes\Modules\Documents\DataTransferObjects\FileObject;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;

use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\FetchesTransactionDetail;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;

class UpdateShippingInvoiceTransactionLogic extends AbstractControllerLogic
{


    /**
     * @return array
     */
    protected function notification():array {
        return [
            'title' => 'Update Shipping Invoice Transaction',
            'message' => 'You have successfully update shipping invoice transaction'
        ];
    }

    /** @var FetchesPackingList */
    private $fetchesPackingList;

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

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

    /** @var FetchesTransactionDetail */
    private $fetchesTransactionDetail;

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

    /** @var UpdatesTransactionDetail */
    private $updatesTransactionDetail;

    /** @var DeletesTransactionDetails */
    private $deletesTransactionDetails;
    
    public function __construct(
        FetchesPackingList $fetchesPackingList,  
        FetchesTransaction $fetchesTransaction,
        UpdatesTransaction $updatesTransaction,
        FetchesTransactionDetail $fetchesTransactionDetail,
        CreatesTransactionDetail $createsTransactionDetail,
        UpdatesTransactionDetail $updatesTransactionDetail,
        DeletesTransactionDetails $deletesTransactionDetails
    )
    {

        $this->fetchesPackingList = $fetchesPackingList;
        $this->fetchesTransaction = $fetchesTransaction;
        $this->updatesTransaction = $updatesTransaction;
        $this->fetchesTransactionDetail = $fetchesTransactionDetail;
        $this->createsTransactionDetail = $createsTransactionDetail;
        $this->updatesTransactionDetail = $updatesTransactionDetail;
        $this->deletesTransactionDetails = $deletesTransactionDetails;
    }

    public function logic(Request $request) : JsonResponse
    {
        $invoice_transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);

        $old_transaction_details = $invoice_transaction->transactionDetails->whereNotIn('reference', ['SHIPPING_FEE', 'OVER_WEIGHT_CHARGES', 'MIN_CBM_CHARGES'])->pluck('id')->toArray();

        $new_transaction_details = collect($request->input('transaction_details'));

        $total_cbm = $invoice_transaction->amount;

        foreach($old_transaction_details as $old_transaction_detail_id){
            $old_transaction_detail = $this->fetchesTransactionDetail->execute(['id' => $old_transaction_detail_id]);

            $total_cbm -= $old_transaction_detail->price;

            if(!$new_transaction_details->contains('id', $old_transaction_detail_id)){
                $this->deletesTransactionDetails->execute($old_transaction_detail);
            }
        }

        foreach($new_transaction_details as $transaction_detail){
            $transaction_detail = (object) $transaction_detail;

            if(!in_array($transaction_detail->reference, ['SHIPPING_FEE', 'OVER_WEIGHT_CHARGES', 'MIN_CBM_CHARGES'])){
                $object_detail = new TransactionDetailObject(
                    'CUSTOM_CHARGES',
                    isset($transaction_detail->name) ? $transaction_detail->name : TransactionDetailType::CUSTOM_CHARGES,
                    $transaction_detail->quantity,
                    $transaction_detail->price
                );

                if(isset($transaction_detail->id)){
                    $new_transaction_detail = $this->updatesTransactionDetail->execute($this->fetchesTransactionDetail->execute(['id' => $transaction_detail->id]), $object_detail);
                }else{
                    $new_transaction_detail = $this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
                }
            }
        }

        $object = new TransactionObject(
            $invoice_transaction->bill_no, 
            TransactionType::SHIPPING_INVOICE, 
            1, 
            $invoice_transaction->issuer,
            1, 
            PaymentMethodType::CASH,
            $invoice_transaction->transactionDetails()->sum('amount'),
            $invoice_transaction->transactionDetails()->sum('amount'),
            1,
            1, 
            0, 
            0, 
            0,
            null, 
            ApprovalStatus::PENDING_VERIFICATION
        );

        /** @var Transaction $invoice_transaction */
        $invoice_transaction = $this->updatesTransaction->execute($invoice_transaction, $object);

        return $this->response([]);
    }

}
