<?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\NewsmailerBundle\Cron;

use Contao\Config;
use Contao\CoreBundle\Monolog\ContaoContext;
use Contao\CoreBundle\ServiceAnnotation\CronJob;
use Contao\Date;
use Contao\MemberGroupModel;
use Contao\MemberModel;
use Contao\NewsArchiveModel;
use Contao\StringUtil;
use Doctrine\DBAL\Connection;
use NotificationCenter\Model\Notification;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;

/**
 * @CronJob("minutely")
 */
class SendNewsNotificationJob
{
    /** @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)
    {
        list($admin_name,$admin_email) = StringUtil::splitFriendlyEmail(Config::get('adminEmail'));

        // Get archives with notifications enabled
        $Archives = NewsArchiveModel::findBy('nc_enable','1');

        if ($Archives !== null)
        {
            while ($Archives->next())
            {
                $Archive = $Archives->current();
                $arrGroupIds = StringUtil::deserialize($Archive->nc_notification_groups,true);
                $time = Date::floorToMinute();

                // Do we have new news items
                $News = $this->db->executeQuery("SELECT id, alias, headline, `date`, teaser FROM tl_news WHERE pid = ? AND nc_sent != '1' AND date <='$time' AND (start='' OR start<='$time') AND (stop='' OR stop>'" . ($time + 60) . "') AND published='1' ORDER BY `date` DESC, `time` DESC",[$Archive->id]);

                // Load groups and notification models if we have news to share
                if ($News->rowCount() && ($Notification = Notification::findByPk($Archive->nc_notification)) !== null && ($Groups = MemberGroupModel::findMultipleByIds($arrGroupIds)) !== null)
                {

                    while ($Groups->next())
                    {
                        // Skip disabled groups
                        if ($Groups->disable)
                        {
                            continue;
                        }

                        // Get group members
                        $Members = MemberModel::findBy(array("`groups` LIKE '%\"".$Groups->id."\"%'","login='1' AND (start='' OR start<='$time') AND (stop='' OR stop>'" . ($time + 60) . "') AND disable=''"),null);

                        // Send notification to each member
                        if ($Members !== null)
                        {
                            $arrNews = array();
                            $arrNewsPlain = array();
                            $arrNewsIds = array();
                            foreach ($News->iterateAssociative() as $item)
                            {
                                $arrRow = array(
                                    'date' => date('d.m.Y',$item['date']),
                                    'headline' => $item['headline'],
                                    'teaser' => StringUtil::substr(strip_tags(str_ireplace(array('<br />','<br>','<br/>','</p>','<p>'),' ',$item['teaser'])),128)
                                );

                                if (($objJumpTo = $Archive->getRelated('jumpTo')) !== null)
                                {
//                                    $arrRow['url'] = $objJumpTo->getAbsoluteUrl(sprintf((Config::get('useAutoItem') ? '/%s' : '/items/%s'),$item['alias'])).'?ltoken=%%_TOKEN_%%';
                                    $arrRow['url'] = $objJumpTo->getAbsoluteUrl(sprintf((Config::get('useAutoItem') ? '/%s' : '/items/%s'),$item['alias']));
                                }

                                $arrNews[] = $arrRow;

                                $arrNewsPlain[] = date('d.m.Y',$item['date']).' - '.$item['headline'];
                                $arrNewsHtml[] = '<div style="margin-bottom: 15px;"><h3>'.$arrRow['date'].' '.$arrRow['headline'].'</h3><p>'.$arrRow['teaser'].'</p>'. ($arrRow['url'] ? '<p><a href="'.$arrRow['url'].'">&raquo; Ganze Nachricht lesen...</a></p>' : '') .'</div>';

                                $arrNewsIds[] = $item['id'];
                            }
                            while ($Members->next())
                            {
                                if (!$Members->nc_news_subscribe)
                                {
                                    continue;
                                }

                                //$strToken = \TokenLogin::getOrRenewUserToken($Members->current());
                                $strToken = '';

                                $Notification->send(array
                                (
                                    'member_email'      => $Members->email.($Members->nc_news_additionalEmail ? ','.$Members->nc_news_additionalEmail : ''),
                                    'member_firstname' => $Members->firstname,
                                    'member_lastname' => $Members->lastname,
                                    'news_topics'       => implode("\n",$arrNewsPlain),
                                    'news_topics_html'  => "<ul>\n<li>".str_replace('%%_TOKEN_%%',$strToken,implode("</li>\n<li>",$arrNewsHtml))."</li>\n</ul>",
                                    'member_login_token'  => $strToken
                                ),
                                    $GLOBALS['TL_LANGUAGE']);
                            }
                        }
                    }

                    // Flag news as sent
                    if (count($arrNewsIds))
                    {
                        $strNewsIds = implode(',',$arrNewsIds);
                        $this->db->executeStatement("UPDATE tl_news SET nc_sent = '1' WHERE id IN ($strNewsIds)");
                    }
                }
            }
        }
        $this->logger->log(LogLevel::INFO, 'News notification has been executed', array('contao' => new ContaoContext(__METHOD__, 'CRON')));

    }
}