<?php

declare(strict_types=1);

/*
* This file is part of newsmailer bundle for Contao.
*
* (c) Benjamin Roth
*
* @license LGPL-3.0-or-later
*/

namespace vonRotenberg\WeinanlieferungBundle\Cron;

use Contao\Config;
use Contao\CoreBundle\Monolog\ContaoContext;
use Contao\CoreBundle\ServiceAnnotation\CronJob;
use Contao\Date;
use Contao\MemberModel;
use Contao\StringUtil;
use Contao\System;
use Doctrine\DBAL\Connection;
use NotificationCenter\Model\Notification;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLageModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungStandortModel;

/**
 * @CronJob("*\/10 * * * *")
 */
class SendBookingChangeNotificationJob
{
    /** @var LoggerInterface  */
    private $logger;

    /** @var Connection */
    private $db;

    public function __construct(Connection $db, LoggerInterface $logger)
    {
        $this->logger = $logger;
        $this->db = $db;
    }

    public function __invoke(string $scope)
    {
        System::loadLanguageFile('default','de');
        list($admin_name,$admin_email) = StringUtil::splitFriendlyEmail(Config::get('adminEmail'));
        $intNotificationsCount = 0;

        // Get locations
        $Locations = WeinanlieferungStandortModel::findBy('nc_enable','1');

        if ($Locations !== null)
        {
            while ($Locations->next())
            {
                $Location = $Locations->current();
                $time = Date::floorToMinute();

                // Do we have updateable items
                $Bookings = $this->db->executeQuery("SELECT r.id, r.pid, r.uid, r.behaelter, r.sorten, r.lage, r.ernteart, r.upload, r.nc_sent, s.date as 'slot_date', s.time as 'slot_time', s.behaelter as 'slot_behaelter', s.sorten as 'slot_sorten', s.ernteart as 'slot_ernteart', s.lage as 'slot_lage', s.anmerkungen as 'slot_anmerkungen', r.approved, r.approved_on FROM tl_vr_wa_reservation r INNER JOIN tl_vr_wa_slot s ON s.id = r.pid WHERE s.pid = ? AND r.nc_sent < r.tstamp AND s.published='1'",[$Location->id]);

                // Load groups and notification models if we have news to share
                if ($Bookings->rowCount() && ($Notification = Notification::findByPk($Location->nc_notification)) !== null)
                {
                    foreach ($Bookings->iterateAssociative() as $Booking)
                    {
                        // Get group members
                        $Member = MemberModel::findOneBy(array("id = ?", "login='1' AND (start='' OR start<='$time') AND (stop='' OR stop>'" . ($time + 60) . "') AND disable=''"), [$Booking['uid']]);

                        // Send notification to member
                        if ($Member !== null)
                        {
                            $arrSortenAvailable = [];
                            $arrErnteartAvailable = [];
                            $arrLageAvailable = [];
                            $arrSortenBooked = [];
                            $arrErnteartBooked = [];
                            $arrLageBooked = [];

                            $SortenLeseart = StringUtil::deserialize($Booking['slot_sorten'],true);
                            foreach($SortenLeseart as $sorteLeseart)
                            {
                                $objSorte = WeinanlieferungRebsorteModel::findByPk($sorteLeseart['sorte']);
                                $objLeseart = WeinanlieferungLeseartModel::findByPk($sorteLeseart['leseart']);
                                $arrSortenAvailable[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null  ? $objSorte->title : '') . ' ' . ($objLeseart !== null  ? $objLeseart->title : '');
                            }
                            $SortenLeseart = explode(';',$Booking['sorten']);
                            foreach($SortenLeseart as $sorteLeseart)
                            {
                                list($sorte,$leseart) = explode(',',$sorteLeseart);
                                $objSorte = WeinanlieferungRebsorteModel::findByPk($sorte);
                                $objLeseart = WeinanlieferungLeseartModel::findByPk($leseart);
                                $arrSortenBooked[$objSorte->id.','.$objLeseart->id] = ($objSorte !== null  ? $objSorte->title : '') . ' ' . ($objLeseart !== null  ? $objLeseart->title : '');
                            }
                            foreach (explode(',', $Booking['ernteart']) as $ernteart)
                            {
                                $arrErnteartBooked[$ernteart] = $GLOBALS['TL_LANG']['REF']['wa_ernteart'][$ernteart] ?? $ernteart;
                            }
                            foreach (explode(',', $Booking['slot_ernteart']) as $ernteart)
                            {
                                $arrErnteartAvailable[$ernteart] = $GLOBALS['TL_LANG']['REF']['wa_ernteart'][$ernteart] ?? $ernteart;
                            }
                            foreach (explode(',', $Booking['slot_lage']) as $lage)
                            {
                                if (($Lage = WeinanlieferungLageModel::findByPk($lage)) !== null)
                                {
                                    $arrLageAvailable[$Lage->id] = $Lage->title;
                                }
                            }
                            foreach (explode(',', $Booking['lage']) as $lage)
                            {
                                if (($Lage = WeinanlieferungLageModel::findByPk($lage)) !== null)
                                {
                                    $arrLageBooked[$Lage->id] = $Lage->title;
                                }
                            }

                            $Notification->send(array
                            (
                                'member_email'       => $Member->email . ($Member->nc_news_additionalEmail ? ',' . $Member->nc_news_additionalEmail : ''),
                                'member_firstname'   => $Member->firstname,
                                'member_lastname'    => $Member->lastname,
                                'member_memberno'    => $Member->memberno,
                                'slot_date'          => Date::parse(Date::getNumericDateFormat(),$Booking['slot_date']),
                                'slot_time'          => Date::parse(Date::getNumericTimeFormat(),$Booking['slot_time']),
                                'slot_standort'      => $Location->title,
                                'slot_behaelter'     => $Booking['slot_behaelter'],
                                'slot_sorten'        => implode(', ',$arrSortenAvailable),
                                'slot_ernteart'      => implode(', ',$arrErnteartAvailable),
                                'slot_lage'          => implode(', ',$arrLageAvailable),
                                'slot_anmerkungen'   => $Booking['slot_anmerkungen'],
                                'booking_ncsent'     => $Booking['nc_sent'],
                                'booking_behaelter'  => $Booking['behaelter'],
                                'booking_sorten'     => implode(', ',$arrSortenBooked),
                                'booking_ernteart'   => implode(', ',$arrErnteartBooked),
                                'booking_lage'       => implode(', ',$arrLageBooked),
                                'booking_approved'   => $Booking['approved'],
                                'booking_approved_on'=> $Booking['approved_on'],
                                'admin_email'        => $admin_email,
                            ),
                                $GLOBALS['TL_LANGUAGE']);

                            $intNotificationsCount++;
                            $this->db->executeStatement("UPDATE tl_vr_wa_reservation SET nc_sent = ? WHERE id = ?",[$time,$Booking['id']]);
                        }
                    }
                }
            }

            // Flag news as sent
            if ($intNotificationsCount)
            {
                $this->logger->log(LogLevel::INFO, sprintf('WA notifications(%s) has been sent',$intNotificationsCount), array('contao' => new ContaoContext(__METHOD__, 'CRON')));
            }
        }
    }
}