<?php

namespace App\Jobs;

use App\Models\ExternalBusyWindow;
use App\Models\ExternalCalendar;
use Carbon\CarbonImmutable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Sabre\VObject\Reader;

class SyncNextcloudBusyJob implements ShouldQueue
{
    use Dispatchable, Queueable, SerializesModels;

    public function handle(): void
    {
		\Log::info('SyncNextcloudBusyJob running at '.now());
        // Choose which calendars to sync (you can expand later to many).
        $calendars = ExternalCalendar::where('is_enabled', true)->get();
        if ($calendars->isEmpty()) return;

        $windowStart = now()->utc();
        $windowEnd   = now()->addWeeks(6)->utc(); // adjust horizon if needed

        foreach ($calendars as $cal) {
            try {
                $resp = Http::timeout(20)->get($cal->url);
                if (!$resp->ok()) {
                    // log and continue
                    \Log::warning("ICS fetch failed", ['cal' => $cal->id, 'status' => $resp->status()]);
                    continue;
                }

                $ics = $resp->body();
                if (!trim($ics)) continue;

                $vcal = Reader::read($ics); // VCalendar

                // Expand recurring events into single instances within window
                // Mutates the calendar to contain expanded VEVENTs
                $vcal = $vcal->expand(
                    new \DateTime($windowStart->format('Y-m-d\TH:i:s\Z')),
                    new \DateTime($windowEnd->format('Y-m-d\TH:i:s\Z'))
                );

                // Remove existing windows in this horizon (simple strategy)
                ExternalBusyWindow::where('external_calendar_id', $cal->id)
                    ->whereBetween('starts_at', [$windowStart, $windowEnd])
                    ->delete();

                $rows = [];
                $nowTs = now();

                // Iterate expanded events
                foreach ($vcal->select('VEVENT') as $ve) {
                    // Treat TRANSPARENT as free; OPAQUE as busy (default busy)
                    $transp = strtoupper((string)($ve->TRANSP ?? 'OPAQUE'));
                    if ($transp === 'TRANSPARENT') continue;

                    // Safely extract start/end in UTC
                    $startDt = $ve->DTSTART->getDateTime(new \DateTimeZone('UTC'));
                    // DTEND may be absent; if so, use DTSTART as a zero-length block (or add a default length)
                    $endDt = isset($ve->DTEND)
                        ? $ve->DTEND->getDateTime(new \DateTimeZone('UTC'))
                        : (clone $startDt);

                    // Skip malformed ranges
                    if ($endDt <= $startDt) continue;

                    // Only keep those overlapping our window
                    $startsAt = CarbonImmutable::instance($startDt);
                    $endsAt   = CarbonImmutable::instance($endDt);
                    if ($endsAt <= $windowStart || $startsAt >= $windowEnd) {
                        continue;
                    }

                    $rows[] = [
                        'external_calendar_id' => $cal->id,
                        'starts_at'   => $startsAt->toDateTimeString(),
                        'ends_at'     => $endsAt->toDateTimeString(),
                        'transparency'=> 'OPAQUE',
                        'last_seen_at'=> $nowTs->toDateTimeString(),
                        'created_at'  => $nowTs->toDateTimeString(),
                        'updated_at'  => $nowTs->toDateTimeString(),
                    ];
                }

                if (!empty($rows)) {
                    // Bulk insert
                    ExternalBusyWindow::insert($rows);
                }

            } catch (\Throwable $e) {
                \Log::error("ICS sync error", ['cal' => $cal->id, 'e' => $e->getMessage()]);
                // Continue with other calendars
            }
        }
    }
}
