<?php

namespace App\Http\Controllers\Owner\Info;

use App\Modules\BookingTourPassenger\Domain\BookingTourPassenger;
use App\Modules\HtlCampBooking\Domain\HtlCampBookingLock;
use App\Modules\HtlCampBookingPassenger\Domain\HtlCampBookingPassengerStatus;
use App\Modules\HtlCampSchedule\Application\ReloadAmount\ReloadAmountHtlCampScheduleQuery;
use App\Modules\Shared\Domain\Bus\Query\QueryBus;
use Illuminate\Support\Facades\DB;

class Migration83Controller
{
    private $tourHtlCamp = [];
    private $htlCampSchedule = [];
    public function __construct(
        private QueryBus $queryBus
    ) {
    }

    private function generateQuery($idHtlCamp, $availability)
    {
        $query = "INSERT INTO `t_htl_camp_schedule`(
            `HtlCampSchedule_Date`,
            `HtlCampSchedule_DateSchedule`,
            `HtlCampSchedule_FromCamp`,
            `HtlCampSchedule_Availability`,
            `HtlCampSchedule_AmountUsage`,
            `HtlCampSchedule_Lock`,
            `Id_HtlCamp`
        )
        VALUES";
        $now = date('Y-m-d H:i:s');
        $firstDate = strtotime('2020-03-20 00:00:00');
        $lastDate = strtotime('2025-11-03 00:00:00');
        $dayInSeconds = 86400;
        $newDay = $firstDate;
        $value = '';
        while ($newDay <= $lastDate) {
            $value .= "\n('$now', '" . date('Y-m-d H:i:s', $newDay) . "', 2, $availability, 0, 1, $idHtlCamp)"
                . ($newDay == $lastDate ? "" : ",");
            $newDay = $newDay + $dayInSeconds;
        }

        echo $query . $value . ";";
    }

    private function getBookings()
    {
        return DB::select('SELECT `Id_Booking`, `Booking_Status`, `Booking_ManuallyConfirmed` FROM `t_booking` WHERE `Booking_Status` IN (1, 2, 3) ORDER BY `Id_Booking` LIMIT 0, 20000');
    }

    private function getBookingTours($Id_Booking)
    {
        return DB::select('SELECT `Id_BookingTour`, `BookingTour_DateStart`, `BookingTour_Status`, `Id_Tour` FROM `t_booking_tour` WHERE `Id_Booking`=?', [$Id_Booking]);
    }

    private function getBookingTourPassengers($Id_BookingTour)
    {
        return DB::select('SELECT `Id_BookingTourPassenger`, `BookingTourPassenger_Status`, `BookingTourPassenger_PaymentStatus` FROM `t_booking_tour_passenger` WHERE `Id_BookingTour`=?', [$Id_BookingTour]);
    }

    private function getTourHtlCamp($Id_Tour)
    {
        if ($this->isTourHtlCampInCache($Id_Tour)) {
            return $this->tourHtlCamp[$Id_Tour];
        } else {
            return $this->saveTourHtlCampInCache($Id_Tour, DB::select('SELECT `Id_HtlCamp`, `TourHtlCamp_Day` FROM `t_tour_htl_camp` WHERE `Id_Tour`=? AND `TourHtlCamp_Status` = 2', [$Id_Tour]));
        }
    }

    private function saveTourHtlCampInCache($Id_Tour, $value)
    {
        $this->tourHtlCamp[$Id_Tour] = $value;
        return $value;
    }

    private function isTourHtlCampInCache($Id_Tour)
    {
        return isset($this->tourHtlCamp[$Id_Tour]);
    }

    private function getHtlCampSchedule($Id_HtlCamp, $HtlCampSchedule_DateSchedule)
    {
        if ($this->isHtlCampScheduleInCache($Id_HtlCamp, $HtlCampSchedule_DateSchedule)) {
            return $this->htlCampSchedule[$Id_HtlCamp][$HtlCampSchedule_DateSchedule];
        } else {
            return $this->saveHtlCampScheduleInCache(
                $Id_HtlCamp,
                $HtlCampSchedule_DateSchedule,
                DB::select(
                    'SELECT `Id_HtlCampSchedule`
                    FROM `t_htl_camp_schedule`
                    WHERE `Id_HtlCamp`=?
                    AND `HtlCampSchedule_DateSchedule`=?',
                    [$Id_HtlCamp, $HtlCampSchedule_DateSchedule]
                )[0]
            );
        }
    }

    private function saveHtlCampScheduleInCache($Id_HtlCamp, $HtlCampSchedule_DateSchedule, $value)
    {
        $this->htlCampSchedule[$Id_HtlCamp][$HtlCampSchedule_DateSchedule] = $value;
        return $value;
    }

    private function isHtlCampScheduleInCache($Id_HtlCamp, $HtlCampSchedule_DateSchedule)
    {
        if (!isset($this->htlCampSchedule[$Id_HtlCamp])) {
            $this->htlCampSchedule[$Id_HtlCamp] = [];
        }
        return isset($this->htlCampSchedule[$Id_HtlCamp][$HtlCampSchedule_DateSchedule]);
    }

    public function __invoke()
    {
        // $this->generateQuery(1, 60);
        // echo "\n\n";
        // $this->generateQuery(2, 60);
        // echo "\n\n";
        // $this->generateQuery(3, 50);
        // return;
        $bookings = $this->getBookings();
        foreach ($bookings as $booking) {
            $bookingTours = $this->getBookingTours($booking->Id_Booking);
            foreach ($bookingTours as $bookingTour) {
                $bookingTourPassengers = $this->getBookingTourPassengers($bookingTour->Id_BookingTour);
                $tourHtlCamps = $this->getTourHtlCamp($bookingTour->Id_Tour);
                foreach ($tourHtlCamps as $tourHtlCamp) {
                    $htlCampBooking = $this->generateHtlCampBooking(
                        $booking,
                        $bookingTour,
                        $tourHtlCamp,
                        $bookingTourPassengers
                    );
                    foreach ($bookingTourPassengers as $bookingTourPassenger) {
                        $this->generateHtlCampBookingPassenger($booking, $htlCampBooking, $bookingTourPassenger);
                    }
                }
            }
        }

        foreach ($this->htlCampSchedule as $htlCamp) {
            foreach ($htlCamp as $htlCampSchedule) {
                $this->queryBus->ask(new ReloadAmountHtlCampScheduleQuery($htlCampSchedule->Id_HtlCampSchedule));
            }
        }
    }

    private function generateHtlCampBooking($booking, $bookingTour, $tourHtlCamp, $bookingTourPassengers)
    {
        $amount = $this->getPassengersAmount($booking, $bookingTourPassengers);
        $amountTotal = $this->getPassengersAmountTotal($booking, $bookingTourPassengers);
        $date = date('Y-m-d H:i:s');
        $dateStart = date(
            'Y-m-d 00:00:00',
            strtotime(
                $bookingTour->BookingTour_DateStart . ' + ' . ($tourHtlCamp->TourHtlCamp_Day - 1) . ' days'
            )
        );

        $htlCampSchedule = $this->getHtlCampSchedule($tourHtlCamp->Id_HtlCamp, $dateStart);

        $query = 'INSERT INTO `t_htl_camp_booking` (
            `Id_HtlCampBooking`,
            `HtlCampBooking_Date`,
            `HtlCampBooking_DateStart`,
            `HtlCampBooking_Amount`,
            `HtlCampBooking_AmountTotal`,
            `HtlCampBooking_Status`,
            `HtlCampBooking_Lock`,
            `HtlCampBooking_Remark`,
            `Id_HtlCampSchedule`,
            `Id_BookingTour`
        )
        VALUES(
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )';
        $value = [
            NULL,
            $date,
            $dateStart,
            $amount,
            $amountTotal,
            $bookingTour->BookingTour_Status,
            HtlCampBookingLock::VALUE_TRUE,
            '',
            $htlCampSchedule->Id_HtlCampSchedule,
            $bookingTour->Id_BookingTour
        ];
        DB::insert($query, $value);
        return DB::select('SELECT LAST_INSERT_ID() as `Id_HtlCampBooking`, ? AS `Id_HtlCampSchedule`', [$htlCampSchedule->Id_HtlCampSchedule])[0];
    }

    private function getPassengersAmount($booking, array $passengers): int
    {
        return count(
            array_filter(
                $passengers,
                fn ($passenger) => BookingTourPassenger::isInCalendar($booking, $passenger)
            )
        );
    }

    private function getPassengersAmountTotal($booking, array $passengers): int
    {
        return count($passengers);
    }

    private function generateHtlCampBookingPassenger($booking, $htlCampBooking, $bookingTourPassenger)
    {
        $isInCalendar = BookingTourPassenger::isInCalendar($booking, $bookingTourPassenger);
        $status = $isInCalendar ? HtlCampBookingPassengerStatus::ACTIVE : HtlCampBookingPassengerStatus::INACTIVE;

        $query = 'INSERT INTO `t_htl_camp_booking_passenger` (
            `Id_HtlCampBookingPassenger`,
            `HtlCampBookingPassenger_Weight`,
            `HtlCampBookingPassenger_Status`,
            `Id_HtlCampBooking`,
            `Id_BookingTourPassenger`
        )
        VALUES (?,?,?,?,?)';
        $value = [
            NULL,
            1,
            $status,
            $htlCampBooking->Id_HtlCampBooking,
            $bookingTourPassenger->Id_BookingTourPassenger
        ];
        DB::insert($query, $value);
        return [$query, $value];
    }
}
