<?php
namespace Components\Data\Live;

use Components\Data\Contracts\CalendarEventProvider;
use Components\Data\DataRegistry;
use Components\Data\Mock\MockCalendarEventProvider;
use Components\Models\NewsletterItem;
use DateTimeImmutable;
use DateTimeZone;

class LiveCalendarEventProvider implements CalendarEventProvider
{
    /**
     * @param array<string,mixed> $state
     * @return array<int,array<string,mixed>>
     */
    public function events(array $state = []): array
    {
        if (DataRegistry::isDev()) {
            return (new MockCalendarEventProvider())->events($state);
        }

        $tz = $state['tz'] instanceof DateTimeZone
            ? $state['tz']
            : new DateTimeZone((string)date_default_timezone_get());
        $now = $state['now'] instanceof DateTimeImmutable
            ? $state['now']
            : new DateTimeImmutable('now', $tz);

        $rangeStart = $state['range_start'] instanceof DateTimeImmutable ? $state['range_start'] : null;
        $rangeEnd = $state['range_end'] instanceof DateTimeImmutable ? $state['range_end'] : null;
        $filter = $state['filter'] ?? 'all';

        // Use the Model to retrieve data
        $items = NewsletterItem::findForCalendar();
        if ($items === []) {
            return [];
        }

        $events = [];
        foreach ($items as $item) {
            $type = $item->getPageMode(); // Unified via PageConfig in the model
            if ($filter === 'newsletter' && $type !== \Components\Newsletter\PageConfig::MODE_NEWSLETTER) {
                continue;
            }
            if ($filter === 'automations' && $type !== \Components\Newsletter\PageConfig::MODE_AUTOMATION) {
                continue;
            }

            $start = $this->parseDate($item->newsletter_item_start, $tz);
            $end = $this->parseDate($item->newsletter_item_end, $tz);
            $completedAt = $this->parseDate($item->completed_at, $tz);

            // Fallback for "start now" / "end never" automations
            if ($item->scheduleTypeCode() === 'automation') {
                if ($start === null) {
                    // Use last_modified or date_added as the start time for "start now" automations
                    $start = $this->parseDate($item->last_modified ?: $item->date_added, $tz);
                }
                if ($end === null && $completedAt === null) {
                    // "End never" automations are shown as ongoing.
                    // For calendar display, we cap them to a reasonable future date or the current range end.
                    $end = $rangeEnd ?: $now->modify('+1 year');
                }
            }

            // If an item was explicitly completed, use that as the end date
            if ($completedAt !== null) {
                $end = $completedAt;
            }

            if (!$start && !$end) {
                continue;
            }

            if (!$start) {
                $start = $end;
            }
            if (!$end) {
                $end = $start;
            }
            if (!$start || !$end) {
                continue;
            }

            if ($start > $end) {
                [$start, $end] = [$end, $start];
            }

            if (!$this->overlaps($start, $end, $rangeStart, $rangeEnd)) {
                continue;
            }

            $id = (int)$item->newsletter_item_id;
            if ($id <= 0) {
                continue;
            }

            $rootId = $id;
            try {
                $rootId = (int)$item->resolveFlowRootId();
            } catch (\Throwable $e) {}

            $campaignId = (int)$item->newsletter_campaign_id;
            $editUrl = $campaignId > 0
                ? \Components\Router::url('newsletter', ['group' => 'campaign-' . $campaignId])
                : \Components\Router::url('newsletter');

            $pageMode = $item->getPageMode();
            $active = ($pageMode === 'automation') ? 'trigger' : 'newsletter';

            $events[] = [
                'id' => $id,
                'newsletter_campaign_id' => $campaignId,
                'title' => (string)($item->newsletter_item_name ?? ('Item #' . $id)),
                'start' => $start,
                'end' => $end,
                'status' => $this->resolveStatus($start, $end, $now),
                'type' => $pageMode,
                'active' => $active,
                'open_key' => $pageMode . '-flow:' . $rootId,
                'schedule_type_ui' => $item->scheduleTypeUi(),
                'edit_url' => $editUrl,
            ];
        }

        return $events;
    }

    private function parseDate($raw, DateTimeZone $tz): ?DateTimeImmutable
    {
        if (!is_scalar($raw)) {
            return null;
        }

        $value = trim((string)$raw);
        if ($value === '' || $value === '0000-00-00' || strpos($value, '1000-01-01') === 0 || strpos($value, '9999-12-31') === 0) {
            return null;
        }

        $ymd = substr($value, 0, 10);
        $dt = DateTimeImmutable::createFromFormat('Y-m-d', $ymd, $tz);
        if ($dt instanceof DateTimeImmutable) {
            return $dt->setTime(0, 0, 0);
        }

        $ts = @strtotime($value);
        if ($ts === false || $ts <= 0) {
            return null;
        }

        return (new DateTimeImmutable('@' . $ts))->setTimezone($tz)->setTime(0, 0, 0);
    }

    private function resolveStatus(DateTimeImmutable $start, DateTimeImmutable $end, DateTimeImmutable $now): string
    {
        $today = $now->setTime(0, 0, 0);

        if ($end < $today) {
            return 'previous';
        }
        if ($start > $today) {
            return 'scheduled';
        }

        return 'active';
    }

    private function overlaps(DateTimeImmutable $start, DateTimeImmutable $end, ?DateTimeImmutable $rangeStart, ?DateTimeImmutable $rangeEnd): bool
    {
        if ($rangeStart === null || $rangeEnd === null) {
            return true;
        }

        return !($end < $rangeStart || $start > $rangeEnd);
    }
}
