<?php
namespace AppBundle\Controller;

//TODO bereinigen
use AppBundle\Entity\BookingRequest;
use AppBundle\Entity\BreadcrumbEntry;
use AppBundle\Entity\FewoLodging;
use AppBundle\Entity\FewoPrice;
use AppBundle\Entity\Page;
use AppBundle\Entity\TravelDate;
use AppBundle\Entity\Traveler;
use AppBundle\Entity\TravelPeriodPrice;
use AppBundle\Entity\TravelPeriodPriceType;
use AppBundle\Form\BookingRequestType;
use AppBundle\Util;


use AppBundle\Entity\FewoSeason;
use AppBundle\Entity\FewoBookingRequest;
use AppBundle\Form\FewoBookingRequestType;
use AppBundle\Entity\FewoReservation;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class FewoBookingController extends Controller
{
    public function getEntityManager()
    {
        return $this->getDoctrine()->getManager();
    }

    /**
     * The routing for this action is entirely controlled by KernelControllerListener!
     *
     * @param Page $fewoTravelProgramPage
     * @param Request $request
     * @param $action
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function indexAction(Page $fewoTravelProgramPage, $action, Request $request)
    {
        $calendarService = $this->container->get('app.lodging_calendar_util');
        $em = $this->getEntityManager();
        //$fewoLodgingRepo = $em->getRepository('AppBundle:FewoLodging');
        $fewoPriceRepo = $em->getRepository('AppBundle:FewoPrice');

        if (!$request->query->has('pnr') || !$request->query->has('fd'))
        {
            return $this->redirect($fewoTravelProgramPage->getUrlPath());
        }

        $priceId = $request->query->get('pnr');
        $fromDate = $request->query->get('fd');

        $lodging = $fewoTravelProgramPage->getFewoLodging();
        /** @var FewoPrice $price */
        $price = $fewoPriceRepo->find($priceId);

        /** @var FewoSeason $season */
        $season = $price->getSeason();
        $minimumStay = $season->getMinimumStay();

        $fromDate = $calendarService->convertDate($fromDate);
        $fromDateTime = new \DateTime($fromDate);
        $toDate = '';

        $maxPersons = $lodging->getMaximumPersons();


        $fewoBookingRequest = new FewoBookingRequest();
        $reservation = new FewoReservation();

        $fewoBookingRequest->setFromDate($fromDateTime);
        //$fewoBookingRequest->setToDate($toDate);
        $fewoBookingRequest->setNumberDays($minimumStay);
        $fewoBookingRequest->setLodging($lodging);
        $fewoBookingRequest->setPrice($price);

        $allowedToDateStrs = [];
        if (!$lodging->getPrices()->isEmpty())
        {
            $nightsSinceFromDate = 0;
            $calendar = $calendarService->createCalendarAndFillDayStates($lodging);
            $areAllowedToDatesCollected = false;
            foreach ($calendar as $calendarMonth)
            {
                if ($calendarMonth['year'] < $fromDateTime->format('Y') ||
                    $calendarMonth['monthNumber'] < $fromDateTime->format('n'))
                {
                    continue;
                }
                /** @var Util\CalendarDayState[] $dayStates */
                $dayStates = $calendarMonth['data'];
                $i = 0;
                if ($calendarMonth['year'] == $fromDateTime->format('Y') &&
                    $calendarMonth['monthNumber'] == $fromDateTime->format('n'))
                {
                    $i = intval($fromDateTime->format('j')) - 1;
                }
                for (; $i < count($dayStates); ++$i)
                {
                    if ($nightsSinceFromDate >= $season->getMinimumStay())
                    {
                        $dayState = $dayStates[$i];
                        if ($dayState->getIsInSeason() && (!$dayState->getIsReserved() ||
                            ($dayState->getIsReservationBegin() && !$dayState->getIsReservationEnd())))
                        {
                            $allowedToDateStrs[] = $dayState->getDate()->format('Y-m-d');
                        }
                        else
                        {
                            $areAllowedToDatesCollected = true;
                            break;
                        }
                    }
                    ++$nightsSinceFromDate;
                }
                if ($areAllowedToDatesCollected)
                {
                    break;
                }
            }
            if (!empty($allowedToDateStrs))
            {
                $toDate = $allowedToDateStrs[0];
            }
        }


        if ($request->getMethod() != 'POST')
        {
            $fewoBookingRequest->setFromDate($fromDate);
            $fewoBookingRequest->setToDate($toDate);
            $fewoBookingRequest->setNumberDays($minimumStay);
            $fewoBookingRequest->setLodging($lodging);
            $fewoBookingRequest->setPrice($price);
        }

        $form = $this->createForm(FewoBookingRequestType::class, $fewoBookingRequest, [
            'lodging' => $lodging,
            'maxPersons' => $maxPersons,
            'toDate' => $toDate
        ]);

        if ($request->getMethod() == 'POST')
        {
            $form->handleRequest($request);

            /** @var FewoBookingRequest $fewoBookingRequest */
            $fewoBookingRequest = $form->getData();
            $fewoBookingRequest->setFromDate($fromDateTime);

            $finalFromDate = $fewoBookingRequest->getFromDate();
            $finalToDate = $fewoBookingRequest->getToDate();

            $timeDiff = date_diff($finalFromDate, $finalToDate);

            $numberDays = $timeDiff->days; // todo: evtl umbenennen, damit es eindeutig für Nächte und nicht mehr für Tage verwendet wird

            $fewoBookingRequest->setNumberDays($numberDays);
            $fewoBookingRequest->setLodging($lodging);
            $fewoBookingRequest->setPrice($price);
        }

        $totalPrice = $this->calculatePrice($fewoBookingRequest, $lodging, $price);
        $perDayTotalPrice = $this->calculatePerDayTotalPrice($fewoBookingRequest, $price);
        $fewoBookingRequest->setTotalPrice($totalPrice);

        if($action == '/buchen')
        {

            if ($request->getMethod() == 'POST' && $form->isValid())
            {
                $reservation->setFromDate($fewoBookingRequest->getFromDate());
                $reservation->setToDate($fewoBookingRequest->getToDate());
                $reservation->setStatus(0); // 0 = belegt; 1 = nicht verfügbar
                $reservation->setType(0); // 0 = Buchung; 1 = Händisch

                $reservation->setLodging($lodging);
                $em->persist($reservation);
                $em->flush();

                $crmBookingUrl = $this->get('app.fewo_booking_exporter')->process($fewoBookingRequest, $lodging, $price);//, $travelDate, $bookingPriceInfo);
                if (!$crmBookingUrl)
                {
                    $crmBookingUrl = '[CRM-EXPORT FEHLGESCHLAGEN]';
                }
                else
                {
                    $crmBookingUrl = preg_replace('/\\/api/', '', $crmBookingUrl) . '/edit';
                }

                $this->get('mailer')->send(\Swift_Message::newInstance()
                    ->setSubject('Ihr FeWo-Buchungsauftrag bei STERN TOURS')
                    ->setFrom('stern@stern-tours.de', 'STERN TOURS')
                    ->setTo($fewoBookingRequest->getEmail())
                    ->setBody(
                        $this->renderView('default/email/fewoBookingConfirmationEmail.txt.twig', [
                            'base_dir' => realpath($this->getParameter('kernel.root_dir') . '/..') . DIRECTORY_SEPARATOR,
                            'fewo_booking_request' => $fewoBookingRequest,
                            'fewo_lodging' => $lodging,
                            'fewo_price' => $price,
                            //'booking_price_info' => $bookingPriceInfo,
                            //'travel_date' => $travelDate,
                            //'breadcrumb_entries' => $breadcrumbEntries,
                        ]),
                        'text/plain', 'utf-8'
                    )
                );


                $this->get('mailer')->send(\Swift_Message::newInstance()
                    ->setSubject('FEWO-BUCHUNG: ' . $lodging->getName())
                    ->setFrom('stern@stern-tours.de', 'STERN TOURS')
                    ->setTo('stern@stern-tours.de')
                    ->setBody(
                        $this->renderView('default/email/fewoBookingServiceEmail.txt.twig', [
                            'base_dir' => realpath($this->getParameter('kernel.root_dir') . '/..') . DIRECTORY_SEPARATOR,
                            'crm_url' => $crmBookingUrl,
                            'lodging_url' => Util::getBaseUrl() . $fewoTravelProgramPage->getUrlPath(),
                            'fewo_booking_request' => $fewoBookingRequest,
                            'fewo_lodging' => $lodging,
                            'fewo_price' => $price,
                            //'booking_price_info' => $bookingPriceInfo,
                            //'travel_date' => $travelDate,
                            //'breadcrumb_entries' => $breadcrumbEntries,
                        ]),
                        'text/plain', 'utf-8'
                    )
                );


                return $this->render('default/pages/fewoBookingConfirmation.html.twig', [
                    'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
                    'page' => $fewoTravelProgramPage,
                    'fewo_booking_request' => $fewoBookingRequest,
                    'fewo_lodging' => $lodging,
                    'fewo_price' => $price,
                    'total_price' => $totalPrice,
                    'total_price_per_night' => $perDayTotalPrice,
                    'show_search_sidebar_widget' => false,
                ]);
            }

            // GET
            return $this->render('default/pages/fewoBooking.html.twig', [
                'form' => $form->createView(),
                'fewo_booking_request' => $fewoBookingRequest,
                'lodging' => $lodging,
                'fromDate' => $fromDate,
                'toDate' => $toDate,
                'fewo_lodging' => $lodging,
                'fewo_price' => $price,
                'total_price' => $totalPrice,
                'total_price_per_night' => $perDayTotalPrice,
                'allowed_to_dates' => implode(';', $allowedToDateStrs),
                'page' => $fewoTravelProgramPage,
                'show_search_sidebar_widget' => false,
                'terms_filename' => $this->getDoctrine()->getRepository('AppBundle:TravelOrganizer')->find(1)->getFileName(),
            ]);

        }
        elseif($action == '/berechne-gesamtpreis')
        {
            return $this->render('default/components/booking/fewoSummary.html.twig', [
                'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
                'fewo_booking_request' => $fewoBookingRequest,
                'fewo_lodging' => $lodging,
                'fewo_price' => $price,
                'total_price' => $totalPrice,
                'total_price_per_night' => $perDayTotalPrice,
            ]);

        }
        throw new \Exception('Unknown FewoBookingController action: '. $action);
    }

    public function calculatePrice(FewoBookingRequest $fewoBookingRequest, FewoLodging $fewoLodging, FewoPrice $fewoPrice)
    {
        $result = $fewoLodging->getDeposit();
        $result = $result + $fewoPrice->getFlatPrice();

        for($i = 0; $i < $fewoBookingRequest->getNumberDays(); $i++)
        {
            $result = $result + $fewoPrice->getPerNight();
        }

        return $result;
    }

    public function calculatePerDayTotalPrice(FewoBookingRequest $fewoBookingRequest, FewoPrice $fewoPrice)
    {
        $result = 0;
        for($i = 0; $i < $fewoBookingRequest->getNumberDays(); $i++)
        {
            $result = $result + $fewoPrice->getPerNight();
        }
        return $result;
    }
}