<?php

namespace App\Classes\Modules\ControllersLogic\Orders\Attachments;

use App\Classes\Constants;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Services\CreatesContact;
use App\Classes\Modules\ControllerLogic\Exceptions\InternalServerErrorException;
use App\Classes\Modules\Orders\DataTransferObjects\DeliveryArrangementObject;
use App\Classes\Modules\Orders\DataTransferObjects\ScheduleObject;
use App\Classes\Modules\Orders\DataTransferObjects\TrackingNumberObject;
use App\Classes\Modules\Orders\Services\Attachments\UpdatesDeliveryArrangement;
use App\Classes\Modules\Orders\Services\Attachments\UpdatesSchedule;
use App\Classes\Modules\Orders\Services\Attachments\UpdatesTrackingNumber;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Models\Contact;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class UpdateDeliveryArrangementLogic
{

    /** @var UpdatesDeliveryArrangement */
    private $updatesDeliveryArrangement;

    /** @var UpdatesSchedule */
    private $updatesSchedule;

    /** @var CreatesContact */
    private $createsContact;

    /** @var UpdatesTrackingNumber */
    private $updatesTrackingNumber;

    /**
     * UpdateDeliveryArrangementLogic constructor.
     * @param UpdatesDeliveryArrangement $updatesDeliveryArrangement
     * @param UpdatesSchedule $updatesSchedule
     * @param CreatesContact $createsContact
     * @param UpdatesTrackingNumber $updatesTrackingNumber
     */
    public function __construct(UpdatesDeliveryArrangement $updatesDeliveryArrangement, UpdatesSchedule $updatesSchedule, CreatesContact $createsContact, UpdatesTrackingNumber $updatesTrackingNumber)
    {
        $this->updatesDeliveryArrangement = $updatesDeliveryArrangement;
        $this->updatesSchedule = $updatesSchedule;
        $this->createsContact = $createsContact;
        $this->updatesTrackingNumber = $updatesTrackingNumber;
    }


    /**
     * @param String $orderId
     * @param Request $request
     * @return JsonResponse
     * @throws InternalServerErrorException
     */
    public function execute(String $orderId, Request $request){

        try {

            $deliveryArrangementObject = new DeliveryArrangementObject($request->input('type'), $request->input('vehicle_no'));
            $arrangementId = $this->updatesDeliveryArrangement->execute($orderId, $deliveryArrangementObject);

            $scheduleObject = new ScheduleObject($request->input('schedule')['ETA'], $request->input('schedule')['ETD'], 1, $request->input('schedule')['remark']);

            $this->updatesSchedule->execute($arrangementId, $scheduleObject);

            if($deliveryArrangementObject->getType() === 0){
                $contactObject = new ContactObject(Constants::MODULE_TYPES['driver'], $arrangementId, $request->input('name'), $request->input('contact'));
                Contact::updateOrCreate(['type' => $contactObject->getType(), 'reference_id' => $contactObject->getReferenceId()],
                    ['name' => $contactObject->getName(), 'contact' => $contactObject->getContact()]);

                $this->createsContact->execute($contactObject, Constants::MODULE_TYPES['driver'], $arrangementId);
            }

            if($deliveryArrangementObject->getType() === 1){
                $trackingNumberObject = new TrackingNumberObject(1, $request->input('tracking_number'), $request->input('courier'));
                $this->updatesTrackingNumber->execute($orderId, $trackingNumberObject);
            }

            return new JsonResponse(null, HttpStatus::RESOURCE_CREATED);

        } catch (\Exception $exception){
            throw new InternalServerErrorException("Failed to update order's shipping arrangement because {$exception->getMessage()}");
        }



    }
}