<?php

namespace App\Modules\Booking\Application\Update;

use App\Modules\Admin\Domain\IdAdmin;
use App\Modules\Booking\Application\Index\BookingIndexer;
use App\Modules\Booking\Domain\BookingAssigned;
use App\Modules\Booking\Domain\BookingCheckedInPassengers;
use App\Modules\Booking\Domain\BookingCode;
use App\Modules\Booking\Domain\BookingDate;
use App\Modules\Booking\Domain\BookingDateBriefing;
use App\Modules\Booking\Domain\BookingDateConfirm;
use App\Modules\Booking\Domain\BookingDateStart;
use App\Modules\Booking\Domain\BookingHistoryChanges;
use App\Modules\Booking\Domain\BookingHotel;
use App\Modules\Booking\Domain\BookingInPerson;
use App\Modules\Booking\Domain\BookingInternalRemark;
use App\Modules\Booking\Domain\BookingLastMinute;
use App\Modules\Booking\Domain\BookingLastPassenger;
use App\Modules\Booking\Domain\BookingManuallyConfirmed;
use App\Modules\Booking\Domain\BookingModel;
use App\Modules\Booking\Domain\BookingNotValidRoomAmount;
use App\Modules\Booking\Domain\BookingObservation;
use App\Modules\Booking\Domain\BookingPassengerAmount;
use App\Modules\Booking\Domain\BookingPlaceBriefing;
use App\Modules\Booking\Domain\BookingReceipt;
use App\Modules\Booking\Domain\BookingStatus;
use App\Modules\Booking\Domain\BookingToken;
use App\Modules\Booking\Domain\BookingType;
use App\Modules\Booking\Domain\IdBooking;
use App\Modules\Booking\Domain\IdBookingReplace;
use App\Modules\Booking\Domain\IdGuideLanguage;
use App\Modules\Booking\Domain\IdUserAdditional;
use App\Modules\BookingReferredFrom\Domain\IdBookingReferredFrom;
use App\Modules\BookingRelationship\Domain\IdBookingRelationship;
use App\Modules\Language\Domain\IdLanguage;
use App\Modules\LodgingPlace\Domain\IdLodgingPlace;
use App\Modules\Shared\Domain\Aggregate\AggregateRoot;
use App\Modules\Shared\Domain\Bus\Query\QueryHandler;
use App\Modules\User\Domain\IdUser;
use DateTime;

final class UpdateBookingQueryHandler implements QueryHandler
{
    public function __construct(
        private BookingUpdater $updater,
        private BookingIndexer $indexer,
    ) {}

    private function conditionalSet($condition, AggregateRoot &$aggregateRoot, $setter, $object)
    {
        if (isset($condition)) {
            $aggregateRoot->$setter(new $object($condition));
        }
    }

    public function __invoke(UpdateBookingQuery $query): UpdateBookingQueryResponse
    {
        /** @var BookingModel $model */
        // $model = $this->indexer->__invoke(new IdBookingTour($query->id));
        /** @var IndexBookingResponse $response */
        $response = $this->indexer->__invoke(new IdBooking($query->id));
        // $model = BookingTourUpdateDTO::validateData($response);
        // $model = new BookingTourModel();
        // $model->fill($response);
        // $model = new BookingTourModel([
        //     // ...
        // ]); 
        $responseData = $response->response()[0];
        // dd($responseData);
        $model = new BookingModel(

            new  IdBooking($responseData->Id_Booking),
            new  BookingDate(new DateTime($responseData->Booking_Date)),
            new  BookingDateConfirm($responseData->Booking_DateConfirm),
            new  BookingDateStart(new DateTime($responseData->Booking_DateStart)),
            new  BookingDateBriefing($responseData->Booking_DateBriefing),
            new  BookingPlaceBriefing($responseData->Booking_PlaceBriefing),
            new  BookingCode($responseData->Booking_Code),
            new  BookingHistoryChanges($responseData->Booking_HistoryChanges),
            new  BookingHotel($responseData->Booking_Hotel),
            new  BookingObservation($responseData->Booking_Observation),
            new  BookingInternalRemark($responseData->Booking_InternalRemark),
            new  BookingReceipt($responseData->Booking_Receipt),
            new  BookingType($responseData->Booking_Type),
            new  BookingLastMinute($responseData->Booking_LastMinute),
            new  BookingAssigned($responseData->Booking_Assigned),
            new  BookingStatus($responseData->Booking_Status),
            new  BookingManuallyConfirmed($responseData->Booking_ManuallyConfirmed),
            new  BookingInPerson($responseData->Booking_InPerson),
            new  BookingPassengerAmount($responseData->Booking_PassengerAmount),
            new  BookingCheckedInPassengers($responseData->Booking_CheckedInPassengers),
            new  BookingLastPassenger($responseData->Booking_LastPassenger),
            new  BookingNotValidRoomAmount($responseData->Booking_NotValidRoomAmount),
            new  BookingToken($responseData->Booking_Token),
            new  IdBookingReplace($responseData->Id_Booking_Replace),
            new  IdAdmin($responseData->Id_Admin ?? 0),
            new  IdGuideLanguage($responseData->Id_GuideLanguage),
            new  IdLanguage($responseData->Id_Language),
            new  IdUser($responseData->Id_User),
            new  IdUserAdditional($responseData->Id_User_Additional),
            new  IdBookingRelationship($responseData->Id_BookingRelationship),
            new  IdBookingReferredFrom($responseData->Id_BookingReferredFrom),
            new  IdLodgingPlace($responseData->Id_LodgingPlace_PickUp),
            new  IdLodgingPlace($responseData->Id_LodgingPlace_DropOff),
        );

        // dd($model);

        // ---------aquí todos los campos que se van a llenar con el response
        // --------------------------------------------------------------------------
        // $model = new FactTypeDocument(
        //     new IdFactTypeDocument($query->getId()),
        //     new FactTypeDocumentName($query->getName()),
        //     new FactTypeDocumentAbrv($query->getAbrv()),
        //     new FactTypeDocumentStatus($query->getStatus()),
        // );
        $set = [
            [$query->idLodgingPlacePickUp, $model, 'setIdLodgingPlacePickUp', IdLodgingPlace::class],
            [$query->idLodgingPlaceDropOff, $model, 'setIdLodgingPlaceDropOff', IdLodgingPlace::class],
            // [$query->idAdmin, $model, 'setIdAdmin', IdAdmin::class],
        ];
        foreach ($set as $value) {
            $this->conditionalSet($value[0], $value[1], $value[2], $value[3]);
        }

        return $this->updater->__invoke(
            $model,
        );
    }
}
