<?php

declare(strict_types=1);

/*
 * This file is part of contao-weinanlieferung-bundle.
 *
 * (c) vonRotenberg
 *
 * @license commercial
 */

namespace vonRotenberg\WeinanlieferungBundle\Controller\Backend;

use Contao\Backend;
use Contao\CoreBundle\Controller\AbstractController;
use Contao\CoreBundle\Csrf\ContaoCsrfTokenManager;
use Contao\Date;
use Contao\Environment;
use Contao\FrontendUser;
use Contao\Input;
use Contao\MemberModel;
use Contao\StringUtil;
use Contao\System;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Environment as TwigEnvironment;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel;

/**
 * @Route("contao/weinanlieferung/buchungsliste", name=WeinanlieferungBookingsController::class, defaults={"_scope" = "backend"})
 */
class WeinanlieferungBookingsController extends AbstractController
{
    private $twig;
    private $tokenManager;
    private $request;
    private $db;

    public function __construct(TwigEnvironment $twig, ContaoCsrfTokenManager $tokenManager, RequestStack $requestStack, Connection $db)
    {
        $this->twig = $twig;
        $this->tokenManager = $tokenManager;
        $this->request = $requestStack->getCurrentRequest();
        $this->db = $db;

        $container = System::getContainer();
        $objSession = $container->get('session');


        $strKey = Input::get('popup') ? 'popupReferer' : 'referer';
        $strRefererId = $this->request->attributes->get('_contao_referer_id');

        $session = $objSession->get($strKey);
        $session[$strRefererId]['current'] = substr(Environment::get('requestUri'), \strlen(Environment::get('path')) + 1);
        $objSession->set($strKey, $session);
    }
    public function __invoke(): Response
    {
        $GLOBALS['TL_CSS']['cirrus'] = 'bundles/vonrotenbergweinanlieferung/css/backend.css|static';
        $arrData = [
            'request_token' => $this->tokenManager->getDefaultTokenValue(),
            'ref' => $this->request->attributes->get('_contao_referer_id')
        ];
        System::loadLanguageFile('default');

        // Filter
        /** @var SessionInterface $objSession */
        $objSession = \System::getContainer()->get('session');

        $session = $objSession->get('filter');

        if (Input::post('FORM_SUBMIT') === 'tl_filters')
        {
            $arrFilterFields = ['tl_day', 'tl_standort', 'tl_status'];

            foreach ($arrFilterFields as $v)
            {
                if ($v == Input::post($v) || Input::post('filter_reset') == '1')
                {
                    unset($session['tl_vr_wa_reservation'][$v]);
                } // Apply the filter
                else
                {
                    $session['tl_vr_wa_reservation'][$v] = Input::post($v);
                }
            }
            $objSession->set('filter', $session);

            Backend::reload();
        }

        $queryBuilder = $this->db->createQueryBuilder()
            ->select('id')
            ->from(WeinanlieferungSlotsModel::getTable());

        if (!empty($session['tl_vr_wa_reservation']['tl_day']) && is_numeric($session['tl_vr_wa_reservation']['tl_day']))
        {
            $Day = new Date($session['tl_vr_wa_reservation']['tl_day']);
            $arrData['filter']['day']['selected'] = $session['tl_vr_wa_reservation']['tl_day'];
            $queryBuilder->andWhere('date BETWEEN :day_start AND :day_end')
                ->setParameter('day_start', $Day->dayBegin)
                ->setParameter('day_end', $Day->dayEnd);
        } else {
            $Today = new Date();
            $queryBuilder->andWhere("time >= :today")
                ->setParameter('today',$Today->dayBegin);
        }

        /*if (!empty(Input::post('tl_month')) && is_numeric(Input::post('tl_month')))
        {
            $Month = new Date(Input::post('tl_month'));
            $arrData['filter']['month']['selected'] = Input::post('tl_month');
            $queryBuilder->andWhere('date BETWEEN :month_start AND :month_end')
                ->setParameter('month_start', $Month->monthBegin)
                ->setParameter('month_end', $Month->monthEnd);
        } else {
            $Today = new Date();
            $queryBuilder->andWhere("time >= :today")
                ->setParameter('today',$Today->dayBegin);
        }*/

        if (!empty($session['tl_vr_wa_reservation']['tl_standort']) && is_numeric($session['tl_vr_wa_reservation']['tl_standort']))
        {
            $Month = new Date($session['tl_vr_wa_reservation']['tl_standort']);
            $arrData['filter']['standort']['selected'] = $session['tl_vr_wa_reservation']['tl_standort'];
            $queryBuilder->andWhere('pid = :pid')
                ->setParameter('pid', (int) $session['tl_vr_wa_reservation']['tl_standort']);
        }

        $arrSlots = $queryBuilder->fetchFirstColumn();


        $arrDayOptions = [];
        $DayRequest = $this->db->executeQuery("SELECT s.date, DATE_FORMAT(FROM_UNIXTIME(s.date),'%d.%m.%Y') as 'day_label' FROM tl_vr_wa_reservation r INNER JOIN tl_vr_wa_slot s ON s.id = r.pid GROUP BY day_label ORDER BY s.date DESC");

        foreach ($DayRequest->iterateAssociative() as $day)
        {
            $arrDayOptions[$day['date']] = Date::parse(Date::getNumericDateFormat(), $day['date']);
        }

        /*$arrMonthOptions = [];
        $MonthRequest = $this->db->executeQuery("SELECT s.date, DATE_FORMAT(FROM_UNIXTIME(s.date),'%m/%Y') as 'month_label' FROM tl_vr_wa_reservation r INNER JOIN tl_vr_wa_slot s ON s.id = r.pid GROUP BY month_label ORDER BY s.date ASC");

        foreach ($MonthRequest->iterateAssociative() as $month)
        {
            $arrMonthOptions[$month['date']] = $month['month_label'];
        }*/

        $arrStandortOptions = [];
        $StandortRequest = $this->db->executeQuery("SELECT l.id, l.title FROM tl_vr_wa_reservation r INNER JOIN tl_vr_wa_slot s ON s.id = r.pid INNER JOIN tl_vr_wa_standort l ON l.id = s.pid GROUP BY l.id ORDER BY l.title ASC");
        foreach ($StandortRequest->iterateAssociative() as $standort)
        {
            $arrStandortOptions[$standort['id']] = $standort['title'];
        }

        $arrData['filter']['day']['options'] = $arrDayOptions;
//        $arrData['filter']['month']['options'] = $arrMonthOptions;
        $arrData['filter']['standort']['options'] = $arrStandortOptions;


        // Get bookings
        if (isset($queryBuilder))
        {
            $arrColumns = null;
            if (count($arrSlots))
            {
                $arrColumns[] = "pid IN (".implode(',',$arrSlots).")";
            }
            if (!empty($session['tl_vr_wa_reservation']['tl_status']))
            {
                $arrData['filter']['status']['selected'] = $session['tl_vr_wa_reservation']['tl_status'];
                switch ($session['tl_vr_wa_reservation']['tl_status'])
                {
                    case 'pending':
                        $arrColumns[] = "approved = ''";
                        break;

                    case 'approved':
                        $arrColumns[] = "approved = '1'";
                        break;

                    case 'canceled':
                        $arrColumns[] = "approved = '0'";
                        break;
                }
            }
            if (!$arrColumns)
            {
                $bookings = WeinanlieferungReservationModel::findAllFuture(['order' => "(SELECT tl_vr_wa_slot.time FROM tl_vr_wa_slot WHERE tl_vr_wa_slot.id=tl_vr_wa_reservation.pid) ASC"]);
            } else {
                $bookings = WeinanlieferungReservationModel::findBy($arrColumns,null,['order' => "(SELECT tl_vr_wa_slot.time FROM tl_vr_wa_slot WHERE tl_vr_wa_slot.id=tl_vr_wa_reservation.pid) ASC"]);
            }

        } else {
            $bookings = WeinanlieferungReservationModel::findAllFuture(['order' => "(SELECT tl_vr_wa_slot.time FROM tl_vr_wa_slot WHERE tl_vr_wa_slot.id=tl_vr_wa_reservation.pid) ASC"]);
        }
        if ($bookings !== null)
        {
            /** @var WeinanlieferungReservationModel $booking */
            foreach ($bookings as $booking)
            {
                /** @var WeinanlieferungSlotsModel $Slot */
                if (($Slot = $booking->getRelated('pid')) !== null)
                {
                    $day = new Date($Slot->date);
                    $arrSorten = [];
                    $arrErnteart = [];
                    $arrLagen = [];

                    if (!isset($arrData['days'][$day->dayBegin][$Slot->pid]))
                    {
                        $Standort = $Slot->getRelated('pid');

                        $arrData['days'][$day->dayBegin][$Slot->pid] = [
                            'standort' => $Standort !== null ? $Standort->title : ''
                        ];

                    }

                    if (!isset($arrData['days'][$day->dayBegin][$Slot->pid]['times'][$Slot->time]))
                    {
                        $arrSortenAvailable = [];
                        $Sorten = StringUtil::deserialize($Slot->sorten,true);
                        foreach($Sorten as $sorte)
                        {
                            $objSorte = WeinanlieferungRebsorteModel::findByPk($sorte['sorte']);
                            $objLeseart = WeinanlieferungLeseartModel::findByPk($sorte['leseart']);
                            $arrSortenAvailable[] = ($objSorte !== null  ? $objSorte->title : '') . ' ' . ($objLeseart !== null  ? $objLeseart->title : '');
                        }
                        $arrData['days'][$day->dayBegin][$Slot->pid]['times'][$Slot->time] = array_merge($Slot->row(),[
                            'sorten' => $arrSortenAvailable,
                            'behaelterAvailable' => $Slot->getAvailableBehaelter(),
                        ]);
                    }

                    if ($booking->sorten !== null)
                    {
                        $SortenLeseart = explode(';', $booking->sorten);
                        foreach ($SortenLeseart as $sorteLeseart)
                        {
                            list($sorte, $leseart) = explode(',', $sorteLeseart);
                            $objSorte = WeinanlieferungRebsorteModel::findByPk($sorte);
                            $objLeseart = WeinanlieferungLeseartModel::findByPk($leseart);
                            $arrSorten[$objSorte->id . ',' . $objLeseart->id] = ($objSorte !== null ? $objSorte->title : '') . ' ' . ($objLeseart !== null ? $objLeseart->title : '');
                        }
                    }

                    if ($booking->ernteart !== null)
                    {
                        foreach (explode(',', $booking->ernteart) as $ernteart)
                        {
                            $arrErnteart[$ernteart] = $GLOBALS['TL_LANG']['REF']['wa_ernteart'][$ernteart] ?? $ernteart;
                        }
                    }

                    if (($Lagen = $booking->getRelated('lage')) !== null)
                    {
                        foreach ($Lagen as $lage)
                        {
                            $arrLagen[$lage->id] = $lage->title;
                        }
                    }

                    $strStandort = '';
                    if (($Standort = $Slot->getRelated('pid')) !== null)
                    {
                        $strStandort = $Standort->title;
                    }

                    $behaelterNumbers = json_decode($booking->behaelter_numbers ?? '[]', true);
                    $isNewFormat = isset($behaelterNumbers[0]) && is_array($behaelterNumbers[0]) && isset($behaelterNumbers[0]['behaelter']);

                    // If it's the old format, convert it to the new format for compatibility
                    if (!$isNewFormat) {
                        $oldFormat = $behaelterNumbers;
                        $memberModel = MemberModel::findById($booking->uid);

                        $behaelterNumbers = [];
                        foreach ($oldFormat as $number) {
                            $behaelterNumbers[] = [
                                'behaelter' => $number,
                                'member' => $memberModel->memberno
                            ];
                        }
                    }

                    $arrData['days'][$day->dayBegin][$Slot->pid]['times'][$Slot->time]['items'][] = array_merge($booking->row(), [
                        'sorte'              => $arrSorten,
                        'ernteart' => $arrErnteart,
                        'lage' => $arrLagen,
                        'slot'  => $Slot->row(),
                        'standort' => $strStandort,
                        'member' => $booking->getRelated('uid') !== null ? $booking->getRelated('uid')->row() : null,
                        'behaelter_numbers' => $behaelterNumbers
                    ]);
                }
            }
        }

        return new Response(
            $this->twig->render(
                '@Contao_VonrotenbergWeinanlieferungBundle/be_wa_buchungsliste.html.twig',
                $arrData
            )
        );
    }
}