<?php

namespace App\Classes\Modules\PerfexCRM\Processors;

use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\Jobs\UpdatePerfexCRMPrelude;
use App\Models\PackingList;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMTasksYDStages;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use Illuminate\Support\Facades\Log;

class PackingListToPerfexCRMProcessor
{
    /**
     * @param PackingList $packingList
     * @return bool
     * @throws \App\Classes\Exceptions\MalformedRequestException
     */
    public function execute(PackingList $packingList, int $stage = PerfexCRMTasksYDStages::DEFAULT): bool
    {
        try {
            if($packingList->owner instanceof \App\Models\Order) {
                $info = $this->extractInfo($packingList);
                $tasks = $this->defineTasks($stage);

                $updatePerfexCRMObject = new UpdatePerfexCRMObject(
                    $info['companyName'],
                    $info['companyReference'],
                    $info['contactName'],
                    $info['contactEmail'],
                    $info['bookingMarking'], //For Exchange-2.0
                    $info['projectName'],
                    PerfexCRMProjectStatus::NOT_STARTED,
                    0,
                    [],
                    $tasks
                );
                $this->dispatchUpdateJob($packingList, $updatePerfexCRMObject);
            }
        } catch (\Exception $exception){
            Log::error('PackingListToPerfexCRMProcessor: ' . json_encode($packingList));
            Log::error($exception);
        }
        return true;
    }

     //Level 1
    private function extractInfo(PackingList $packingList): array
    {
        $order = $packingList->owner;
        $companyModule  = $order->companyModule()->first();
        $employee = $companyModule->employees()->first();

        $info = [];
        $info['companyName'] = $companyModule->name;
        $info['companyReference'] = $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
        $info['contactName'] = $employee->name;
        $info['contactEmail'] = $employee->email;
        $info['bookingMarking'] = ''; //For Exchange-2.0
        $info['projectName'] = 'IZYIM | X1 Shipping | '.$packingList->owner->reference.' | '.$packingList->reference;

        return $info;
    }

    private function defineTasks(int $stage): array
    {
        $tasks = [];

        if ($stage === PerfexCRMTasksYDStages::DEFAULT) {
            $tasks = $this->defineAllYDStagesTasks();
        }
        else if ($stage === PerfexCRMTasksYDStages::LOAD_CONTAINER) {
            $tasks = $this->updateLoadContainerTasks();
        }
        else if ($stage === PerfexCRMTasksYDStages::SHIP_SAILED) {
            $tasks = $this->updateShipSailedTasks();
        }
        else if ($stage === PerfexCRMTasksYDStages::SHIP_ARRIVED) {
            $tasks = $this->updateShipArrivedTasks();
        }
        else if ($stage === PerfexCRMTasksYDStages::UNSTUFFING) {
            $tasks = $this->updateUnstuffingTasks();
        }
        else if ($stage === PerfexCRMTasksYDStages::DELIVERY) {
            $tasks = $this->updateDeliveryTasks();
        }

        return $tasks;
    }

    private function dispatchUpdateJob(PackingList $packingList, UpdatePerfexCRMObject $updatePerfexCRMObject)
    {
        UpdatePerfexCRMPrelude::dispatch($packingList, null, $updatePerfexCRMObject, false);
    }


     //Level Others: Nested
    private function defineAllYDStagesTasks(): array
    {
        $tasks = [
            PerfexCRMTasks::TASK_YD_LOADED_CONTAINER_1,
            PerfexCRMTasks::TASK_YD_LOADED_CONTAINER_2,
            PerfexCRMTasks::TASK_YD_LOADED_CONTAINER_3,
            PerfexCRMTasks::TASK_YD_SHIPPING_1,
            PerfexCRMTasks::TASK_YD_UNSTUFFING_1,
            PerfexCRMTasks::TASK_YD_DELIVERY_1,
        ];

        return $tasks;
    }

    private function updateLoadContainerTasks(): array
    {
        $tasks = [];
        $tasks = $this->completeTask(null, PerfexCRMTasks::TASK_YD_LOADED_CONTAINER_3);
        return $tasks;
    }

    private function updateShipSailedTasks(): array
    {
        $tasks = [];
        $tasks = $this->completeTask(PerfexCRMTasks::TASK_YD_LOADED_CONTAINER_3, PerfexCRMTasks::TASK_YD_SHIPPING_1);
        return $tasks;
    }

    private function updateShipArrivedTasks(): array
    {
        $tasks = [];
        $tasks = $this->completeTask(PerfexCRMTasks::TASK_YD_SHIPPING_1, PerfexCRMTasks::TASK_YD_UNSTUFFING_1);
        return $tasks;
    }

    private function updateUnstuffingTasks(): array
    {
        $tasks = [];
        $tasks = $this->completeTask(PerfexCRMTasks::TASK_YD_UNSTUFFING_1, PerfexCRMTasks::TASK_YD_DELIVERY_1);
        return $tasks;
    }

    private function updateDeliveryTasks(): array
    {
        $tasks = [];
        $tasks = $this->completeTask(PerfexCRMTasks::TASK_YD_DELIVERY_1, null);
        return $tasks;
    }

    private function completeTask($startTask, $endTask) {
        $resultArray = [];
        if($startTask){
            $startTask['status'] = PerfexCRMTaskStatus::COMPLETED;
            array_push($resultArray, $startTask);
        }
        if($endTask){
            $endTask['status'] = PerfexCRMTaskStatus::IN_PROGRESS;
            array_push($resultArray, $endTask);
        }

        return $resultArray;
    }

}
