<?php
require_once(MH_DIR_CONFIG . 'config_api/classes/apibeez.php');
require_once MH_DIR_APP . '/components/Autoload.php';


class api_public_calendar_feed extends apibeez
{
    public function __construct()
    {
        parent::__construct();
        $this->has_get = true;
        $this->app_cache_time = 300; // Match Cache-Control max-age
    }

    public function _get($request_data, $payload_data)
    {
        $token = (string)($payload_data['token'] ?? ($_GET['token'] ?? ''));
        if ($token === '') {
            header("HTTP/1.1 400 Bad Request");
            echo "Missing token";
            mh_exit();
        }

        // Validate token against stored user-scoped tokens
        $isValid = false;

        // Ensure TABLE_MAILBEEZ_MODULE_CONFIGURATION is defined
        if (!defined('TABLE_MAILBEEZ_MODULE_CONFIGURATION')) {
            mh_define('TABLE_MAILBEEZ_MODULE_CONFIGURATION', DB_PREFIX . 'mailbeez_module_configuration');
        }

        $sql = "select cfg_key from " . TABLE_MAILBEEZ_MODULE_CONFIGURATION . " 
                where cfg_key like 'BEEZUI_CALENDAR_FEED_TOKEN_U_%' 
                and cfg_value = '" . mh_db_input($token) . "' 
                limit 1";

        $q = mh_db_query($sql);
        if ($q && mh_db_num_rows($q) > 0) {
            $isValid = true;
        }

        if (!$isValid) {
            header("HTTP/1.1 403 Forbidden");
            echo "Invalid token";
            mh_exit();
        }

        $filterRaw = strtolower((string)($payload_data['filter'] ?? ($_GET['filter'] ?? 'all')));
        $filter = in_array($filterRaw, ['all', 'newsletter', 'automations'], true) ? $filterRaw : 'all';

        // Cache the ICS generation
        $this->set_cache_id($token . '_' . $filter, 'calendar_feed');
        $cache = $this->read_cache('app');
        if ($cache) {
            $ics = $cache['value'];
            $lastModified = $cache['timestamp'];
        } else {
            $ics = $this->generateIcs($filter);
            $this->set_cache($ics, 'app');
            $lastModified = time();
        }

        $etag = '"' . md5($ics) . '"';

        $ifNoneMatch = $_SERVER['HTTP_IF_NONE_MATCH'] ?? '';
        $ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? '';

        if ($ifNoneMatch === $etag || ($ifModifiedSince !== '' && strtotime($ifModifiedSince) >= $lastModified)) {
            header('ETag: ' . $etag);
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
            header("HTTP/1.1 304 Not Modified");
            mh_exit();
        }

        header('Content-Type: text/calendar; charset=utf-8');
        header('Cache-Control: public, max-age=300');
        header('ETag: ' . $etag);
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
        header('Content-Disposition: inline; filename="mailbeez_calendar.ics"');

        echo $ics;
        mh_exit();
    }

    private function generateIcs($filter = 'all')
    {
        // Use DataRegistry to get events.
        // We might need to ensure the environment is ready for Components.
        $events = \Components\Data\DataRegistry::calendarEvents()->events(['filter' => $filter]);

        $calName = 'MailBeez Marketing Calendar';
        if ($filter === 'newsletter') {
            $calName .= ' - Newsletter';
        } elseif ($filter === 'automations') {
            $calName .= ' - Automations';
        }

        $ics = "BEGIN:VCALENDAR\r\n";
        $ics .= "VERSION:2.0\r\n";
        $ics .= "PRODID:-//MailBeez//Marketing Calendar//EN\r\n";
        $ics .= "X-WR-CALNAME:" . $this->escapeIcs($calName) . "\r\n";
        $ics .= "X-WR-TIMEZONE:" . date_default_timezone_get() . "\r\n";
        $ics .= "CALSCALE:GREGORIAN\r\n";

        $host = $_SERVER['HTTP_HOST'] ?? 'mailbeez.internal';
        $dtStamp = gmdate('Ymd\THis\Z');

        foreach ($events as $event) {
            $ics .= "BEGIN:VEVENT\r\n";
            $ics .= "UID:mb-item-" . $event['id'] . "@" . $host . "\r\n";
            $ics .= "DTSTAMP:" . $dtStamp . "\r\n";

            /** @var \DateTimeImmutable $start */
            $start = $event['start'];
            /** @var \DateTimeImmutable $end */
            $end = $event['end'];

            // For all-day events in ICS, DTEND is the day AFTER the last day of the event
            $dtStart = $start->format('Ymd');
            $dtEnd = $end->modify('+1 day')->format('Ymd');

            $ics .= "DTSTART;VALUE=DATE:" . $dtStart . "\r\n";
            $ics .= "DTEND;VALUE=DATE:" . $dtEnd . "\r\n";
            $ics .= "SUMMARY:" . $this->escapeIcs($event['title']) . "\r\n";

            $description = "Type: " . $event['type'] . "\nStatus: " . $event['status'];
            if (!empty($event['edit_url'])) {
                $description .= "\nEdit: " . $event['edit_url'];
            }
            $ics .= "DESCRIPTION:" . $this->escapeIcs($description) . "\r\n";

            if (!empty($event['edit_url'])) {
                $ics .= "URL:" . $this->escapeIcs($event['edit_url']) . "\r\n";
            }

            $ics .= "END:VEVENT\r\n";
        }

        $ics .= "END:VCALENDAR\r\n";
        return $ics;
    }

    private function escapeIcs($string)
    {
        $string = (string)$string;
        $string = str_replace('\\', '\\\\', $string);
        $string = str_replace(',', '\\,', $string);
        $string = str_replace(';', '\\;', $string);
        $string = str_replace("\n", '\\n', $string);
        $string = str_replace("\r", '', $string);
        return $string;
    }
}
