<?php

namespace App\Modules\HtlCampLock\Application\CreateByTour;

use App\Modules\HtlCampLock\Application\Create\CreateHtlCampLockQuery;
use App\Modules\HtlCampLock\Application\Create\HtlCampLockCreator;
use App\Modules\HtlCampLock\Domain\HtlCampLock;
use App\Modules\HtlCampLock\Domain\HtlCampLockAmount;
use App\Modules\HtlCampLock\Domain\HtlCampLockDate;
use App\Modules\HtlCampLock\Domain\HtlCampLockDateStart;
use App\Modules\HtlCampLock\Domain\HtlCampLockStatus;
use App\Modules\HtlCampLock\Domain\IdHtlCampLock;
use App\Modules\HtlCampSchedule\Application\Availability\AvailabilityHtlCampScheduleQuery;
use App\Modules\HtlCampSchedule\Application\HtlCampScheduleResponse;
use App\Modules\HtlCampSchedule\Domain\IdHtlCampSchedule;
use App\Modules\Shared\Domain\Bus\Query\QueryBus;
use App\Modules\Shared\Domain\DateStart;
use App\Modules\TourHtlCamp\Application\TourHtlCampFinder;
use App\Modules\TourHtlCamp\Domain\THCIdTour;

class GenerateLockFromTour
{

    private function __construct(
        private TourHtlCampFinder $finder,
        private HtlCampLockCreator $creator,
        private QueryBus $queryBus
    ) {
    }
    public function __invoke(
        $idTour,
        $dateStart,
        $passengerAmount
    ) {
        $camps = $this->findTourHtlCampList($idTour);
        $responses = [];
        foreach ($camps as $camp) {
            $campDate = $this->generateDateFromCamp($dateStart, $camp);
            $lock = $this->createLock($camp, $campDate->value() . ' 00:00:00', $passengerAmount);
            $responses[] = $this->queryBus->ask(new CreateHtlCampLockQuery(
                $lock->date()->value(),
                $lock->dateStart()->value(),
                $lock->amount()->value(),
                $lock->status()->value(),
                $camp->Id_HtlCamp
            ));
        }
        return $responses;
    }

    private function findTourHtlCampList($idTour)
    {
        return $this->finder->__invoke(new THCIdTour($idTour), 'active')['Response_Data'];
    }

    public function generateDateFromCamp(string $dateStart, $camp)
    {
        $date = (new DateStart($dateStart));
        $date->addInterval('P' . ($camp->TourHtlCamp_Day - 1) . 'D');
        return $date;
    }

    private function createLock($camp, $dateStart, $passengerAmount)
    {
        /** @var HtlCampScheduleResponse $availability */
        $availability = $this->queryBus->ask(new AvailabilityHtlCampScheduleQuery($camp->Id_Camp, $dateStart, $passengerAmount));
        return new HtlCampLock(
            new IdHtlCampLock(0),
            HtlCampLockDate::now(),
            new HtlCampLockDateStart($dateStart),
            new HtlCampLockAmount($passengerAmount),
            new HtlCampLockStatus(HtlCampLockStatus::PENDING),
            new IdHtlCampSchedule($availability->Id_HtlCampSchedule),
        );
    }
}
