<?php

namespace App\Http\Controllers\Owner\Calendar;

use App\Http\Controllers\Controller;
use App\Http\History\HistoryData;
use App\Http\History\HistoryTables;
use App\Modules\BookingCalendar\Application\List\ListBookingCalendarResponse;
use App\Modules\BookingCalendar\Application\ListPassenger\ListPassengerBookingCalendarQuery;
use App\Modules\BookingCalendar\Infrastructure\Validators\BookingCalendarValidators;
use App\Modules\BookingTourPassenger\Application\Print\PrintBookingTourPassengerQuery;
use App\Modules\BookingTourPassenger\Application\Print\PrintBookingTourPassengerResponse;
use App\Modules\Shared\Domain\Bus\Command\CommandBus;
use App\Modules\Shared\Domain\Bus\Query\QueryBus;
use App\Modules\Shared\Validator\Infraestructure\LaravelDTOGenerator;
use App\Modules\Shared\Validator\Infraestructure\LaravelValidator;
use App\Modules\Template\TourTemplate\Application\ListByTour\ListByTourTourTemplateQuery;
use App\Modules\Template\TourTemplate\Application\ListByTour\ListByTourTourTemplateResponses;
use App\Providers\Pdf\BookingTourPassengerTemplate\BookingTourPassengerTemplatePdf;
use App\Providers\Pdf\BookingTourPassengerTemplate\BookingTourPassengerTemplatePdfAll;
use App\Providers\Pdf\BookingTourPassengerTemplate\PdfDestination;
use App\Providers\StorageProvider;
use App\Providers\ZipGenerator\ZipGenerator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

final class BookingCalendarPassengerPrintController extends Controller
{
    private $domain;
    private HistoryData $history;

    public function __construct(
        private CommandBus $commandBus,
        private QueryBus $queryBus,
        private ZipGenerator $zipGenerator,
        private StorageProvider $storageProvider,
        private BookingTourPassengerTemplatePdf $bookingTourPassengerTemplatePdf,
        private BookingTourPassengerTemplatePdfAll $bookingTourPassengerTemplatePdfAll,
        private LaravelDTOGenerator $dtoGenerator
    ) {
        $this->domain = "BookingTourPassenger";
        $this->history = new HistoryData(HistoryTables::BOOKING_TOUR_PASSENGER);
    }

    private function findBooking($Id)
    {
        $found = DB::select(
            'Call sp_booking_tour_passenger_index(?, ?)',
            [$Id, config('var.PATH_PUBLIC') . config('var.USER_COUNTRY_THUMB')]
        );

        return count($found) ? $found[0]->Id_Booking : null;
    }

    public function __invoke(Request $request)
    {
        (new LaravelValidator())->validate($request->all(), $this->domain, BookingCalendarValidators::LIST_PASSENGER_PRINT);

        /** @var ListBookingCalendarResponse $response */
        $response = $this->queryBus->ask(new ListPassengerBookingCalendarQuery(
            $request->get('Id_Tour'),
            $request->get('DateStart'),
        ));

        $btpList = $response->response()['Response_Data'];
        $btpList = array_values(array_filter($btpList, fn($btp) => in_array($btp->BookingTourPassenger_Status, [2, 3])));

        $list = [];
        foreach ($btpList as $btp) {
            $value = $this->markAsPrinted($btp, $request);
            if ($value === false) {
                return 'El tour no tiene template';
            }

            $list[] = $value;
        }

        $files = $this->generatePdfFiles(
            $list,
            $request->input('Format'),
            $list[0][1]->Tour_Code . '-' . date('d-m-Y', strtotime($list[0][1]->BookingTour_DateStart))
        );

        $zipFileName = $this->zipGenerator->generateFromFiles(
            $files,
            $list[0][1]->Tour_Code . '-' . date('d-m-Y', strtotime($list[0][1]->BookingTour_DateStart))
        );

        $this->removeFiles($files);

        return response()->download($this->storageProvider->privatePath($zipFileName))->deleteFileAfterSend(true);
    }

    private function generatePdfFiles($list, $format, $title)
    {
        $files = [];
        if ($format === 'Individual') {
            return array_map(fn($listElement) => $this->bookingTourPassengerTemplatePdf->run(
                $listElement[0]->TourTemplate_Pdf,
                $listElement[0],
                $listElement[1],
                PdfDestination::FILE,
                $this->storageProvider->privatePath('files' . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR)
            ), $list);
        } else if ($format === 'All') {
            return [$this->bookingTourPassengerTemplatePdfAll->run(
                PdfDestination::FILE,
                $this->storageProvider->privatePath('files' . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR),
                $title,
                $list
            )];
        }

        return $files;
    }

    private function removeFiles($files)
    {
        foreach ($files as $file) {
            unlink($file);
        }
    }

    public function markAsPrinted($btp, $request)
    {
        $this->history->obtainOld($btp->Id_BookingTourPassenger);

        /** @var ListByTourTourTemplateResponses $templateResponse */
        $templateResponse = $this->queryBus->ask(new ListByTourTourTemplateQuery($btp->Id_Tour));

        if ($request->input('Type') === 'Id_TourTemplate') {
            $template = $templateResponse->tourTemplate;
        }
        if ($request->input('Type') === 'Id_TourTemplate_Blank') {
            $template = $templateResponse->tourTemplateBlank;
        }
        if ($template === null) {
            return false;
        }

        /** @var PrintBookingTourPassengerResponse $update */
        $update = $this->queryBus->ask(new PrintBookingTourPassengerQuery($btp->Id_BookingTourPassenger));

        $bookingTourPassenger = $update->response()[0];

        $this->history->obtainNew($bookingTourPassenger->Id_BookingTourPassenger);

        $this->history->update(
            $this->findBooking($bookingTourPassenger->Id_BookingTourPassenger),
            $this->history->oldValue,
            $this->history->newValueCache,
            $request
        );
        return [$template, $btp];
    }
}
