<?php

namespace App\Http\Controllers\Owner\Calendar;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Owner\c_Passenger;
use App\Http\Controllers\Owner\Calendar\Dto\BookingCalendarExportExcelDTO;
use Illuminate\Http\Request;
use App\Modules\Shared\Domain\Bus\Query\QueryBus;
use App\Modules\Shared\Validator\Infraestructure\LaravelDTOGenerator;
use App\Providers\Calendar\ExcelCalendarPaxHotelsReport\ExcelCalendarPaxHotelsReport;
use Illuminate\Support\Facades\DB;

class BookingCalendarExportHotelsExcelController extends Controller
{

    private $domain;
    public function __construct(
        private QueryBus $queryBus,
        private LaravelDTOGenerator $dtoGenerator
    ) {
        $this->domain = "Booking";
    }

    public function __invoke(Request $request)
    {
        /** @var BookingCalendarExportExcelDTO $dto */
        $dto = $this->dtoGenerator->generate($request->all(), $this->domain, BookingCalendarExportExcelDTO::class);

        $oParam = [
            $dto->Id_CategoryTour,
            $dto->Id_TypeTour,
            $dto->Id_Package,
            $dto->Id_Tour,
            $dto->DateStart,
            $dto->DateEnd,
            config('var.PATH_PUBLIC') . config('var.USER_COUNTRY_THUMB')
        ];

        $oData  = DB::select('call sp_tour_availability_calendar_report(?,?,?,?,?,?,?)', $oParam);
        // dd($oData);

        $oData = array_map(function ($pass) {
            $pass->Passenger_ImgDocument1_Path = c_Passenger::path1_large() . $pass->Passenger_ImgDocument1;
            $pass->Passenger_ImgDocument1_Thumb = c_Passenger::path1_thumb() . $pass->Passenger_ImgDocument1;
            $pass->Passenger_ImgDocument2_Path = c_Passenger::path2_large() . $pass->Passenger_ImgDocument2;
            $pass->Passenger_ImgDocument2_Thumb = c_Passenger::path2_thumb() . $pass->Passenger_ImgDocument2;
            return $pass;
        }, $oData);

        $oData = array_map(fn($row) => $this->richRow($row), $oData);
        $oData = array_map(
            fn($passenger, $index) => $this->markRowWithSameIdRoomBelow($passenger, $oData, $index),
            $oData,
            array_keys($oData)
        );
        $oData = array_map(
            fn($passenger, $index) => $this->markRowWithSameTourAbove($passenger, $oData, $index),
            $oData,
            array_keys($oData)
        );
        // para los tours diferentes
        $oData = array_map(
            fn($passenger, $index) => $this->markTourRowsBelow($passenger, $oData, $index),
            $oData,
            array_keys($oData)
        );
        $oData = array_map(
            fn($passenger, $index) => $this->markRowWithSameBookingBelow($passenger, $oData, $index),
            $oData,
            array_keys($oData)
        );
        (new ExcelCalendarPaxHotelsReport())
            ->exportToExcel(
                $oData
            );
        // dd($oData);
    }

    private function richRow($passenger)
    {
        $passenger->groupList = [];
        if ($passenger->Group_Count > 0) {
            $passenger->groupList = json_decode($passenger->Group_List);
        }

        $passenger->groupName = implode("\n", array_map(fn($group) => $group->Group_Name, $passenger->groupList));
        $passenger->roomList = [];
        $room = json_decode($passenger->Room_List);
        if ($room[0]->Id_RoomPassenger !== null) {
            $passenger->room = $room[0];
        } else {
            $passenger->room = null;
        }
        return $passenger;
    }

    private function markRowWithSameTourAbove($row, $rowList, $index)
    {
        if ($index == 0) {
            $row->showTour = true;
            return $row;
        }

        if (
            $row->Id_Tour == $rowList[$index - 1]->Id_Tour
            && $row->BookingTour_DateStart == $rowList[$index - 1]->BookingTour_DateStart
        ) {
            $row->showTour = false;
        } else {
            $row->showTour = true;
        }

        return $row;
    }
    // funcion para marcar las filas que se deben unir de los tours
    private function markTourRowsBelow($row, $rowList, $index)
    {
        if (!$row->showTour) {
            $row->tourRowsBelow = 0;
            return $row;
        }

        $count = 0;
        $currentTourKey = $row->Id_Tour . '|' . $row->BookingTour_DateStart;

        for ($i = $index + 1; $i < count($rowList); $i++) {
            $next = $rowList[$i];
            $nextTourKey = $next->Id_Tour . '|' . $next->BookingTour_DateStart;

            if ($nextTourKey === $currentTourKey) {
                $count++;
            } else {
                break;
            }
        }

        $row->tourRowsBelow = $count;
        return $row;
    }


    private function markRowWithSameBookingBelow($row, $rowList, $index)
    {
        if (isset($row->bookingType) && $row->bookingType == 'child') {
            return $row;
        }

        $row->bookingType = 'owner';
        $row->PaxNumber = 1;
        $paxIndex = 2;
        $row->bookingRowsBelow = 0;
        for ($i = $index + 1; $i < count($rowList); $i++) {
            if ($rowList[$i]->Id_Booking === $row->Id_Booking) {
                $rowList[$i]->bookingType = 'child';
                $rowList[$i]->PaxNumber = $paxIndex;
                $paxIndex++;
                $row->bookingRowsBelow++;
            } else {
                return $row;
            }
        }

        return $row;
    }




    private function markRowWithSameIdRoomBelow($row, $rowList, $index)
    {
        if (!$row->room) {
            $row->rowsBelow = 0;
            $row->rowType = 'empty';
            return $row;
        }

        if (isset($row->rowType) && $row->rowType == 'child') {
            return $row;
        }

        $row->rowType = 'owner';
        $row->rowsBelow = 0;
        for ($i = $index + 1; $i < count($rowList); $i++) {
            if (!$rowList[$i]->room) {
                return $row;
            }
            if ($rowList[$i]->room && $rowList[$i]->room->Id_Room === $row->room->Id_Room && $rowList[$i]->Id_Tour === $row->Id_Tour) {
                $rowList[$i]->rowType = 'child';
                $row->rowsBelow++;
            } else {
                return $row;
            }
        }

        return $row;
    }
}
