<?php

namespace App\Http\Controllers;

use App\Models\CalendarInstance;
use Illuminate\Support\Facades\Response;
use Carbon\Carbon;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Reader;

class IcsController extends Controller
{
    public function download(string $calendarUri)
    {
        $instance = CalendarInstance::where('uri', $calendarUri)->firstOrFail();

        $calendar = $instance->calendar()->with(['events.meta'])->firstOrFail();
        $timezone = $instance->timezone ?? 'UTC';

        $ical = $this->generateICalendarFeed($calendar->events, $timezone);

        return Response::make($ical, 200, [
            'Content-Type' => 'text/calendar; charset=utf-8',
            'Content-Disposition' => 'inline; filename="' . $calendarUri . '.ics"',
        ]);
    }

    protected function generateICalendarFeed($events, string $tz): string
    {
        $vcalendar = new VCalendar();
        $vcalendar->add('VERSION', '2.0');
        $vcalendar->add('PRODID', '-//Kithkin Calendar//EN');
        $vcalendar->add('CALSCALE', 'GREGORIAN');
        $vcalendar->add('METHOD', 'PUBLISH');

        foreach ($events as $event) {
            $ical = $event->calendardata ?? null;

            if ($ical) {
                try {
                    $parsed = Reader::read($ical);
                    foreach ($parsed->select('VEVENT') as $vevent) {
                        $vcalendar->add(clone $vevent);
                    }
                    continue;
                } catch (\Throwable $e) {
                    // fall through to meta-based output
                }
            }

            $meta = $event->meta;
            if (!$meta || !$meta->start_at || !$meta->end_at) {
                continue;
            }

            $start = Carbon::parse($meta->start_at)->timezone($tz);
            $end = Carbon::parse($meta->end_at)->timezone($tz);

            $vevent = $vcalendar->add('VEVENT', []);
            $vevent->add('UID', $event->uid);
            $vevent->add('SUMMARY', $meta->title ?? '(Untitled)');
            $vevent->add('DESCRIPTION', $meta->description ?? '');
            $vevent->add('DTSTART', $start, ['TZID' => $tz]);
            $vevent->add('DTEND', $end, ['TZID' => $tz]);
            $vevent->add('DTSTAMP', Carbon::parse($event->lastmodified)->utc());
            if ($meta->location) {
                $vevent->add('LOCATION', $meta->location);
            }
        }

        return $vcalendar->serialize();
    }

    protected function escape(?string $text): string
    {
        return str_replace(['\\', ';', ',', "\n"], ['\\\\', '\;', '\,', '\n'], $text ?? '');
    }
}
