<?php

namespace App\Classes\Modules\PackingLists\Processors;

use App\Classes\Modules\Orders\Services\FetchesDataFromVTPortal;
use App\Classes\Modules\Schedules\DataTransferObjects\ScheduleObject;
use App\Classes\Modules\Schedules\Services\CreatesSchedule;
use App\Classes\Modules\Transports\DataTransferObjects\TransportObject;
use App\Classes\Modules\Transports\Services\CreatesTransport;
use App\Classes\Modules\Unity\Services\UpdatesContractObligation;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Models\PackingList;
use App\Models\Transport;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class FetchDeliveryListFromVTPortalProcessor
{

    /** @var FetchesDataFromVTPortal */
    private $fetchesDataFRomVTPortal;

    /** @var CreatesTransport */
    private $createsTransport;

    /** @var CreatesSchedule */
    private $createsSchedule;

    /** @var UpdatesContractObligation */
    private $updatesContractObligations;

    /**
     * FetchDeliveryListFromVTPortalProcessor constructor.
     * @param FetchesDataFromVTPortal $fetchesDataFRomVTPortal
     * @param CreatesTransport $createsTransport
     * @param CreatesSchedule $createsSchedule
     * @param UpdatesContractObligation $updatesContractObligations
     */
    public function __construct(FetchesDataFromVTPortal $fetchesDataFRomVTPortal, CreatesTransport $createsTransport, CreatesSchedule $createsSchedule, UpdatesContractObligation $updatesContractObligations)
    {
        $this->fetchesDataFRomVTPortal = $fetchesDataFRomVTPortal;
        $this->createsTransport = $createsTransport;
        $this->createsSchedule = $createsSchedule;
        $this->updatesContractObligations = $updatesContractObligations;
    }


    /**
     * @return array
     */
    public function execute(){

        try {
            $packingLists = PackingList::where('type', '=', PackingListType::SHIPPING_PACKING_LIST)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::SUSPENDED])->get();

            /** @var PackingList $packingList */
            foreach($packingLists as $packingList){
                try {
                    $filter = '["PoNumber:=%js%\"'.$packingList->reference.'\"\u0000"]';

                    $shippingPackingListsRequest = $this->fetchesDataFRomVTPortal->clientRequest('http://portal.vtnation.com.my/Services/DataControllerService.asmx/GetPage', 'POST', json_decode('{"controller":"VPodetailparcel","view":"grid1","request":{"PageIndex":-1,"PageSize":10000,"SortExpression":"CreatedOn asc","Filter":'.$filter.'}}'), '');

                    $shippingPackingLists = $this->fetchesDataFRomVTPortal->getResponseBody($shippingPackingListsRequest);

                    if(!array_key_exists(0, $shippingPackingLists->Rows)){
                        continue;
                    }

                    $shippingPackingList = $shippingPackingLists->Rows[0];

                    if(!$shippingPackingList[9] && !$shippingPackingList[10]) {
                        continue;
                    }

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

                    $deliveryDate = Carbon::parse($shippingPackingList[9] ? $shippingPackingList[9]:$shippingPackingList[10]);
                    $transportObject = new TransportObject(TransportType::LAND, null, null,  $deliveryDate, $deliveryDate, ApprovalStatus::APPROVED);
                    /** @var Transport $transport */
                    $transport = $this->createsTransport->execute($transportObject, $packingList);
                    $this->createsSchedule->execute($transport, new ScheduleObject($deliveryDate, $deliveryDate, ApprovalStatus::APPROVED));

                    $deliveryStep = $packingList->steps()->where('reference', '=', 'LAST_MILE_DELIVERY')->first();
                    $signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
                    $this->updatesContractObligations->execute($signature, $deliveryStep->obligation_hash_id);
                    $deliveryStep->update(['status' => ApprovalStatus::COMPLETED]);

                } catch (GuzzleException $exception) {
                    dd($exception);
                    continue;
                }

            }
        } catch (\Exception $exception){
            Log::error($exception);
        }

        return [];

    }


}
