<?php

namespace Ig\IgReservations\Controller;

use DateTime;
use Ig\IgReservations\Domain\Repository\CalendarRepository;
use Ig\IgReservations\Domain\Repository\EventRepository;
use Ig\IgReservations\Domain\Repository\FeUserRepository;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Http\PropagateResponseException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

/**
 * EventController
 */
class StatisticController extends ActionController
{
    public function __construct(protected CalendarRepository $calendarRepository, protected EventRepository $eventRepository, protected FeUserRepository $feUserRepository)
    {
    }

    public function showAction(array $search = []): ResponseInterface
    {
        //$calendarUid = $this->settings['calendarUid'];
        //$calendar = $this->calendarRepository->findByUid($calendarUid);
        $calendars = $this->calendarRepository->findAllIgnoreStoragePid();
        $feUsers = $this->feUserRepository->findAll();
        $statsReservationsPerPerson = $this->eventRepository->findAmountOfEventsPerUser($this->settings, $search);
        $statsReservationsPerBookingType = $this->eventRepository->findAmountOfEventsPerBookingType($this->settings, $search);
        $statsReservationsPerReservationType = $this->eventRepository->findAmountOfEventsPerReservationType($this->settings, $search);
        $statsReservationsPerLocation = $this->eventRepository->findAmountOfEventsPerLocation($this->settings, $search);
        $statsReservationsPerMonth = $this->eventRepository->findAmountOfEventsPerDateFormat('%Y-%m', $this->settings, $search);
        $statsReservationsPerYear = $this->eventRepository->findAmountOfEventsPerDateFormat('%Y', $this->settings, $search);
        $this->view->assign('calendars', $calendars);
        $this->view->assign('feUsers', $feUsers);
        $this->view->assign('search', $search);
        $this->view->assign('statsReservationsPerPerson', $statsReservationsPerPerson);
        $this->view->assign('statsReservationsPerBookingType', $statsReservationsPerBookingType);
        $this->view->assign('statsReservationsPerReservationType', $statsReservationsPerReservationType);
        $this->view->assign('statsReservationsPerLocation', $statsReservationsPerLocation);
        $this->view->assign('statsReservationsPerMonth', $statsReservationsPerMonth);
        $this->view->assign('statsReservationsPerYear', $statsReservationsPerYear);

        return $this->htmlResponse();
    }

    public function exportAction(array $search = []): ResponseInterface
    {
        $spreadsheet = GeneralUtility::makeInstance(Spreadsheet::class);
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle(LocalizationUtility::translate('statistics.export.sheet.general', 'IgReservations'));
        $statsReservationsPerPerson = $this->eventRepository->findAmountOfEventsPerUser($this->settings, $search);
        $statsReservationsPerBookingType = $this->eventRepository->findAmountOfEventsPerBookingType($this->settings, $search);
        $statsReservationsPerReservationType = $this->eventRepository->findAmountOfEventsPerReservationType($this->settings, $search);
        $statsReservationsPerLocation = $this->eventRepository->findAmountOfEventsPerLocation($this->settings, $search);
        $users = $this->eventRepository->findUsersWithReservations($this->settings, $search);

        $row = 1;
        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('tx_igreservations_domain_model_calendar', 'IgReservations'));
        if (isset($search['calendar']) && $search['calendar'] !== '') {
            $calendar = $this->calendarRepository->findByUid((int)$search['calendar']);
            $dateTime = new DateTime($search['startDate']['date']);
            $sheet->setCellValue('B' . $row, $calendar->getName());
        }
        $row++;

        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('search.start_date', 'IgReservations'));
        if (isset($search['startDate']) && is_array($search['startDate']) && $search['startDate']['date'] !== '') {
            $dateTime = new DateTime($search['startDate']['date']);
            $sheet->setCellValue('B' . $row, $dateTime->format('d.m.Y'));
        }
        $row++;

        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('search.end_date', 'IgReservations'));
        if (isset($search['endDate']) && is_array($search['endDate']) && $search['endDate']['date'] !== '') {
            $dateTime = new DateTime($search['endDate']['date']);
            $sheet->setCellValue('B' . $row, $dateTime->format('d.m.Y'));
        }
        $row += 2;

        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('statistics.labels.statsReservationsPerPerson', 'IgReservations'));
        $sheet->setCellValue('B' . $row, LocalizationUtility::translate('statistics.export.reservations_count', 'IgReservations'));
        $sheet->getStyle('A' . $row)->getFont()->setBold(true);
        $sheet->getStyle('B' . $row)->getFont()->setBold(true);

        $row++;
        foreach($statsReservationsPerPerson as $stat) {
            $sheet->setCellValue('A' . $row, $stat['x']);
            $sheet->setCellValue('B' . $row, $stat['y']);
            $row++;
        }

        $row += 2;

        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('statistics.labels.statsReservationsPerBookingType', 'IgReservations'));
        $sheet->setCellValue('B' . $row, LocalizationUtility::translate('statistics.export.reservations_count', 'IgReservations'));
        $sheet->getStyle('A' . $row)->getFont()->setBold(true);
        $sheet->getStyle('B' . $row)->getFont()->setBold(true);

        $row++;
        foreach ($statsReservationsPerBookingType as $stat) {
            $sheet->setCellValue('A' . $row, $stat['x']);
            $sheet->setCellValue('B' . $row, $stat['y']);
            $row++;
        }

        $row += 2;

        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('statistics.labels.statsReservationsPerReservationType', 'IgReservations'));
        $sheet->setCellValue('B' . $row, LocalizationUtility::translate('statistics.export.reservations_count', 'IgReservations'));
        $sheet->getStyle('A' . $row)->getFont()->setBold(true);
        $sheet->getStyle('B' . $row)->getFont()->setBold(true);

        $row++;
        foreach ($statsReservationsPerReservationType as $stat) {
            $sheet->setCellValue('A' . $row, $stat['x']);
            $sheet->setCellValue('B' . $row, $stat['y']);
            $row++;
        }

        $row += 2;

        $sheet->setCellValue('A' . $row, LocalizationUtility::translate('statistics.labels.statsReservationsPerLocation', 'IgReservations'));
        $sheet->setCellValue('B' . $row, LocalizationUtility::translate('statistics.export.reservations_count', 'IgReservations'));
        $sheet->getStyle('A' . $row)->getFont()->setBold(true);
        $sheet->getStyle('B' . $row)->getFont()->setBold(true);

        $row++;
        foreach ($statsReservationsPerLocation as $stat) {
            $sheet->setCellValue('A' . $row, $stat['x']);
            $sheet->setCellValue('B' . $row, $stat['y']);
            $row++;
        }

        $sheet->getStyle('A1')->getFont()->setBold(true);
        $sheet->getStyle('A2')->getFont()->setBold(true);
        $sheet->getStyle('A3')->getFont()->setBold(true);

        foreach($users as $user) {
            $row = 1;

            $sheetTitle = $user['username'];
            $currentSheet = $spreadsheet->createSheet();
            $currentSheet->setTitle($sheetTitle);
            $currentSheet->setCellValue('A' . $row, LocalizationUtility::translate('tx_igreservations_domain_model_event.owner', 'IgReservations'));
            $currentSheet->setCellValue('B' . $row, trim($user['first_name'] . ' ' . $user['last_name'] . ' (' . $user['username'] . ')'));
            $currentSheet->getStyle('A1')->getFont()->setBold(true); 
            $row += 2;

            $col = 1;
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.start_date', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.start_time', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.end_date', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.end_time', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.duration', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_address.salutation', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_address.first_name', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_address.last_name', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.num_participants', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.status', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.location', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_event.booking_type', 'IgReservations'));
            $currentSheet->setCellValue([$col++, $row], LocalizationUtility::translate('tx_igreservations_domain_model_reservationtype', 'IgReservations'));
            $row++;

            foreach($user['reservations'] as $reservation) {
                $startDate = new DateTime($reservation['event']['start_date']);
                $startTime = substr((string) $reservation['event']['start_time'], 0, 5);
                $endDate = new DateTime($reservation['event']['end_date']);
                $endTime = substr((string) $reservation['event']['end_time'], 0, 5);
                $startDateTime = new DateTime($reservation['event']['start_date'] . 'T' . $reservation['event']['start_time']);
                $endDateTime = new DateTime($reservation['event']['end_date'] . 'T' . $reservation['event']['end_time']);

                $startTimeStamp = $startDateTime->getTimestamp();
                $endTimeStamp = $endDateTime->getTimestamp();

                $differenceInHours = ($endTimeStamp - $startTimeStamp) / 3600;
                $col = 1;
                $currentSheet->setCellValue([$col++, $row], $startDate->format('d.m.Y'));
                $currentSheet->setCellValue([$col++, $row], $startTime);
                $currentSheet->setCellValue([$col++, $row], $endDate->format('d.m.Y'));
                $currentSheet->setCellValue([$col++, $row], $endTime);
                $currentSheet->setCellValue([$col++, $row], $differenceInHours);
                $currentSheet->setCellValue(
                    [$col++, $row],
                    LocalizationUtility::translate('tx_igreservations_domain_model_address.salutation.' . $reservation['salutation'], 'IgReservations')
                );
                $currentSheet->setCellValue([$col++, $row], $reservation['first_name']);
                $currentSheet->setCellValue([$col++, $row], $reservation['last_name']);
                if($reservation['num_participants'] > 1) {
                    $currentSheet->setCellValue([$col++, $row], $reservation['num_participants']);
                } else if ($reservation['event']['num_participants'] > 1) {
                    $currentSheet->setCellValue([$col++, $row], $reservation['event']['num_participants']);
                } {
                    $currentSheet->setCellValue([$col++, $row], '1');
                }
                if(is_array($reservation['event']['status'])) {
                    $currentSheet->setCellValue([$col++, $row], $reservation['event']['status']['name']);
                } else {
                    $col++;
                }
                if (is_array($reservation['event']['location'])) {
                    $currentSheet->setCellValue([$col++, $row], $reservation['event']['location']['name']);
                } else {
                    $col++;
                }
                if (is_array($reservation['event']['booking_type'])) {
                    $currentSheet->setCellValue([$col++, $row], $reservation['event']['booking_type']['name']);
                } else {
                    $col++;
                }
                if (is_array($reservation['reservation_type'])) {
                    $currentSheet->setCellValue([$col++, $row], $reservation['reservation_type']['name']);
                }
                $row++;
            }
            $currentSheet->getStyle('A3:' . $currentSheet->getHighestDataColumn() . '3')->getFont()->setBold(true);
        }


        foreach($spreadsheet->getAllSheets() as $s) {
            foreach ($s->getColumnIterator() as $column) {
                $s->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
            }
        }

        $spreadsheet->setActiveSheetIndex(0);

        $now = new DateTime();

        $writer = new Xlsx($spreadsheet);
        $response = $this->responseFactory->createResponse()
            ->withHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
            ->withHeader('Expires', '0')
            ->withHeader('Cache-Control', 'private')
            ->withHeader('Content-Disposition', 'attachment; filename="ig_reservations-statistics-' . $now->format('Y-m-d-His') . '.xlsx"');

        $tempFilename = tempnam('', 'tempfile');
        $writer->save($tempFilename);
        $response->withHeader('Content-Length', (string)filesize($tempFilename));
        $excelOutput = file_get_contents($tempFilename);
        unlink($tempFilename);
        $response->getBody()->write($excelOutput);

        throw new PropagateResponseException($response, 200);
    }
}