<?php

namespace App\Classes\Modules\PerfexCRM\Processors;

use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use App\Classes\Jobs\UpdatePerfexCRMPrelude;
use App\Models\Booking;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;

class TransactionToPerfexCRMProcessorV2
{
    public function execute(Transaction $model, int $status)
    {
        try {
            if(in_array($model->type, [TransactionType::PAYMENT, TransactionType::BILL, TransactionType::PURCHASE_ORDER])) {
                $transaction = ($model->type === TransactionType::BILL ? $model->owner : $model);
                $bookingInfo = $this->extractBookingInfo($transaction);
                $projectName = 'Exchange | ' . $bookingInfo['serviceTypeName'] . ' | ' . $bookingInfo['bookingMarking'];
                $tasks = $this->defineTasks($model, $status);

                //Log::error("TransactionToPerfexCRMProcessorV2 status: ".$status." - for project name: ".$projectName);

                if(count($tasks) > 0) {
                    $updatePerfexCRMObject = new UpdatePerfexCRMObject(
                        $bookingInfo['companyName'],
                        $bookingInfo['companyReference'],
                        $bookingInfo['contactName'],
                        $bookingInfo['contactEmail'],
                        $bookingInfo['bookingMarking'],
                        $projectName,
                        PerfexCRMProjectStatus::IN_PROGRESS,
                        0,
                        [],
                        $tasks
                    );
                    $this->dispatchUpdateJob($transaction, $status, $updatePerfexCRMObject);
                }
            }
        } catch (\Exception $exception) {
            Log::error($exception);
        }
        return true;
    }

    private function extractBookingInfo(Transaction $model): array
    {
        $bookingInfo = [];
        $bookingInfo['companyReference'] = $model->owner->company->reference;
        $bookingInfo['companyName'] = $model->owner->company->name;
        $bookingInfo['contactEmail'] = $model->owner->company->employees()->first()->email;
        $bookingInfo['contactName'] = $model->owner->company->employees()->first()->name;
        $bookingInfo['bookingMarking'] = $model->owner->marking;
        $bookingInfo['serviceTypeName'] = $model->owner->company->services()->where('id', $model->owner->service_id)->first()->name;

        return $bookingInfo;
    }

    private function defineTasks(Transaction $model, int $status): array
    {
        $tasks = [];
        $ownerServiceId = $model->type === TransactionType::BILL ? $model->owner->owner->service_id : $model->owner->service_id;

        if ($status === ApprovalStatus::PENDING_VERIFICATION) {
            $tasks = $this->handlePendingVerificationStatus($model, $ownerServiceId);
        } elseif ($status === ApprovalStatus::APPROVED) {
            $tasks = $this->handleApprovedStatus($model, $ownerServiceId);
        }

        return $tasks;
    }

    private function handlePendingVerificationStatus(Transaction $model, int $serviceId): array
    {
        $tasks = [];
        switch($model->type) {
            case TransactionType::PAYMENT:
                $tasks = $this->definePaymentTasks($model);
                break;
            case TransactionType::PURCHASE_ORDER:
                if ($serviceId === 1 || $serviceId === 3) {
                    $task = PerfexCRMTasks::TASK_PURCHASE_ORDER_1;
                    $task['status'] = PerfexCRMTaskStatus::IN_PROGRESS;
                    $tasks = [$task];
                }
                break;
            case TransactionType::BILL:
                $tasks = $this->handleBillPendingStatus($serviceId);
                break;
        }

        return $tasks;
    }

    private function handleApprovedStatus(Transaction $model, int $serviceId): array
    {
        $tasks = [];
        switch($model->type) {
            case TransactionType::PAYMENT:
                $tasks = $this->handlePaymentApprovedStatus($serviceId);
                break;
            case TransactionType::BILL:
                if ($serviceId === 4) {
                    $tasks = $this->completeTask(PerfexCRMTasks::TASK_1688_PAYMENT_9, PerfexCRMTasks::TASK_1688_PAYMENT_10);
                }
                break;
        }

        return $tasks;
    }

    private function handlePaymentApprovedStatus(int $serviceId): array
    {
        $tasks = [];
        switch ($serviceId) {
            case 1:
                $tasks = $this->completeTask(PerfexCRMTasks::TASK_1_DAY_TRANSFER_2, PerfexCRMTasks::TASK_1_DAY_TRANSFER_5);
                break;
            case 3:
                $tasks = $this->completeTask(PerfexCRMTasks::TASK_3_DAY_TRANSFER_2, PerfexCRMTasks::TASK_3_DAY_TRANSFER_5);
                break;
            case 4:
                $tasks = $this->completeTask(PerfexCRMTasks::TASK_1688_PAYMENT_2, PerfexCRMTasks::TASK_1688_PAYMENT_5);
                break;
        }

        return $tasks;
    }

    private function handleBillPendingStatus(int $serviceId): array
    {
        $tasks = [];
        switch ($serviceId) {
            case 1:
                $tasks = $this->completeTask(PerfexCRMTasks::TASK_1_DAY_TRANSFER_5, PerfexCRMTasks::TASK_1_DAY_TRANSFER_6);
                break;
            case 3:
                $tasks = $this->completeTask(PerfexCRMTasks::TASK_3_DAY_TRANSFER_5, PerfexCRMTasks::TASK_3_DAY_TRANSFER_6);
                break;
            case 4:
                $tasks = $this->completeTask(PerfexCRMTasks::TASK_1688_PAYMENT_5, PerfexCRMTasks::TASK_1688_PAYMENT_7);
                break;
        }

        return $tasks;
    }

    private function definePaymentTasks(Transaction $model): array
    {
        $tasks = [
//            PerfexCRMTasks::TASK_1
        ];

        if ($model->owner->service_id === 1) {
            $tasks = array_merge($tasks, $this->oneDayTransferTasks());
        } elseif ($model->owner->service_id === 3) {
            $tasks = array_merge($tasks, $this->threeDayTransferTasks());
        } elseif ($model->owner->service_id === 4) {
            $tasks = array_merge($tasks, $this->payment1688Tasks());
        }

        if ($model->owner->service_id === 1 || $model->owner->service_id === 3) {
            $purchaseOrder = $model->booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->complete()->first();
            if(is_null($purchaseOrder)){
                $tasks = array_merge($tasks, $this->purchaseOrderTasks());
            }
        }

        return $tasks;
    }

    private function oneDayTransferTasks(): array
    {
        return [
//            PerfexCRMTasks::TASK_1_DAY_TRANSFER_1,
            PerfexCRMTasks::TASK_1_DAY_TRANSFER_2,
//            PerfexCRMTasks::TASK_1_DAY_TRANSFER_3,
//            PerfexCRMTasks::TASK_1_DAY_TRANSFER_3_1,
//            PerfexCRMTasks::TASK_1_DAY_TRANSFER_4,
            PerfexCRMTasks::TASK_1_DAY_TRANSFER_5,
            PerfexCRMTasks::TASK_1_DAY_TRANSFER_6
        ];
    }

    private function threeDayTransferTasks(): array
    {
        return [
//            PerfexCRMTasks::TASK_3_DAY_TRANSFER_1,
            PerfexCRMTasks::TASK_3_DAY_TRANSFER_2,
//            PerfexCRMTasks::TASK_3_DAY_TRANSFER_3,
//            PerfexCRMTasks::TASK_3_DAY_TRANSFER_3_1,
//            PerfexCRMTasks::TASK_3_DAY_TRANSFER_4,
            PerfexCRMTasks::TASK_3_DAY_TRANSFER_5,
            PerfexCRMTasks::TASK_3_DAY_TRANSFER_6
        ];
    }

    private function payment1688Tasks(): array
    {
        return [
//            PerfexCRMTasks::TASK_1688_PAYMENT_1,
            PerfexCRMTasks::TASK_1688_PAYMENT_2,
//            PerfexCRMTasks::TASK_1688_PAYMENT_3,
//            PerfexCRMTasks::TASK_1688_PAYMENT_3_1,
//            PerfexCRMTasks::TASK_1688_PAYMENT_4,
            PerfexCRMTasks::TASK_1688_PAYMENT_5,
//            PerfexCRMTasks::TASK_1688_PAYMENT_6,
            PerfexCRMTasks::TASK_1688_PAYMENT_7,
            PerfexCRMTasks::TASK_1688_PAYMENT_8,
            PerfexCRMTasks::TASK_1688_PAYMENT_9,
            PerfexCRMTasks::TASK_1688_PAYMENT_10,
            PerfexCRMTasks::TASK_1688_PAYMENT_11,
            PerfexCRMTasks::TASK_1688_PAYMENT_12,
//            PerfexCRMTasks::TASK_1688_PAYMENT_13
        ];
    }

    private function purchaseOrderTasks(): array
    {
        $potask1 = PerfexCRMTasks::TASK_PURCHASE_ORDER_1;
        $potask1['status'] = PerfexCRMTaskStatus::NOT_STARTED;

        return [
            $potask1,
//            PerfexCRMTasks::TASK_PURCHASE_ORDER_2
        ];
    }

    private function dispatchUpdateJob(Transaction $model, int $status, UpdatePerfexCRMObject $updatePerfexCRMObject)
    {
        $withInvoice = ($model->type === TransactionType::PAYMENT && $model->owner instanceof Booking && $status === ApprovalStatus::APPROVED);
        UpdatePerfexCRMPrelude::dispatch($model, $updatePerfexCRMObject, $withInvoice);
    }

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

        return [$startTask, $endTask];
    }
}
