<?php

namespace App\Classes\Modules\Bookings\Processors;


use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Bookings\Services\Convert1688PurchaseOrderToProductList;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;

class CreatePurchaseOrderFor1688OrderProcessor
{
    /** @var GeneratesTransactionBillNumber */
    private $generatesTransactionBillNumber;

    /** @var CreatePurchaseOrderTransactionProcessor */
    private $createPurchaseOrderTransactionProcessor;

    /** @var Convert1688PurchaseOrderToProductList */
    private $convert1688PurchaseOrderToProductList;

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

    /** @var CreateInvoiceTransactionProcessor */
    private $createInvoiceTransactionProcessor;

    /**
     * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
     * @param CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor
     * @param Convert1688PurchaseOrderToProductList $convert1688PurchaseOrderToProductList
     * @param UpdatesTransactionStatus $updatesTransactionStatus
     * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
     */
    public function __construct(GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor, Convert1688PurchaseOrderToProductList $convert1688PurchaseOrderToProductList, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor)
    {
        $this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
        $this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor;
        $this->convert1688PurchaseOrderToProductList = $convert1688PurchaseOrderToProductList;
        $this->updatesTransactionStatus = $updatesTransactionStatus;
        $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
    }


    public function execute(Booking $booking)
    {
        $billNumber = $this->generatesTransactionBillNumber->execute('PO-');

        $documents = $booking->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->get();
        $products = [];
        foreach ($documents as $document) {
            foreach ($document->files as $file) {
                try {
                    $products = $this->convert1688PurchaseOrderToProductList->execute($file);
                } catch (MalformedRequestException $exception) {
                    continue;
                }
            }
        }

        if (empty($products)){
            $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1,
                1, PaymentMethodType::CASH,
                0, 0, $booking->fix_currency_id, $booking->fix_currency_id,
                1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, []);
            $this->createPurchaseOrderTransactionProcessor->execute($booking, $object);
            return false;
        }

        $total = collect($products)->sum(function($product){
            return $product['quantity'] * floatval(str_replace(',', '', $product['unit_price']));
        });

        $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1,
            1, PaymentMethodType::CASH,
            $total, $total, $booking->fix_currency_id, $booking->fix_currency_id,
            1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products);

        $purchaseOrder = $this->createPurchaseOrderTransactionProcessor->execute($booking, $object);

        if($purchaseOrder->amount === $booking->fix_amount){
            $this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED);
            $this->createInvoiceTransactionProcessor->execute($booking);
        }

    }

}
