<?php

namespace App\Services\Meet\Calendar;

use App\Models\CalendarConnection;
use App\Models\Room;
use App\Models\User;
use App\Services\Meet\IcalService;
use Illuminate\Support\Facades\Http;

class GoogleCalendarProvider
{
    public function authorizeUrl(): ?string
    {
        $clientId = config('meet.calendar.google.client_id');
        $redirect = config('meet.calendar.google.redirect');

        if (! $clientId || ! $redirect) {
            return null;
        }

        $params = http_build_query([
            'client_id' => $clientId,
            'redirect_uri' => $redirect,
            'response_type' => 'code',
            'scope' => 'https://www.googleapis.com/auth/calendar.events',
            'access_type' => 'offline',
            'prompt' => 'consent',
        ]);

        return 'https://accounts.google.com/o/oauth2/v2/auth?'.$params;
    }

    /**
     * @return array<string, mixed>|null
     */
    public function exchangeCode(string $code): ?array
    {
        $response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
            'code' => $code,
            'client_id' => config('meet.calendar.google.client_id'),
            'client_secret' => config('meet.calendar.google.client_secret'),
            'redirect_uri' => config('meet.calendar.google.redirect'),
            'grant_type' => 'authorization_code',
        ]);

        return $response->successful() ? $response->json() : null;
    }

    public function createEvent(CalendarConnection $connection, Room $room, User $host): ?string
    {
        if (! $connection->access_token) {
            return null;
        }

        $response = Http::withToken($connection->access_token)->post(
            'https://www.googleapis.com/calendar/v3/calendars/'.urlencode($connection->calendar_id ?? 'primary').'/events',
            $this->eventPayload($room, $host),
        );

        return $response->successful() ? $response->json('id') : null;
    }

    public function updateEvent(CalendarConnection $connection, Room $room, User $host): bool
    {
        if (! $connection->access_token || ! $room->calendar_event_id) {
            return false;
        }

        $calendar = urlencode($connection->calendar_id ?? 'primary');
        $event = urlencode($room->calendar_event_id);

        return Http::withToken($connection->access_token)->put(
            "https://www.googleapis.com/calendar/v3/calendars/{$calendar}/events/{$event}",
            $this->eventPayload($room, $host),
        )->successful();
    }

    public function deleteEvent(CalendarConnection $connection, Room $room): bool
    {
        if (! $connection->access_token || ! $room->calendar_event_id) {
            return false;
        }

        $calendar = urlencode($connection->calendar_id ?? 'primary');
        $event = urlencode($room->calendar_event_id);

        return Http::withToken($connection->access_token)->delete(
            "https://www.googleapis.com/calendar/v3/calendars/{$calendar}/events/{$event}",
        )->successful();
    }

    /** @return array<string, mixed> */
    protected function eventPayload(Room $room, User $host): array
    {
        $start = ($room->scheduled_at ?? now())->toIso8601String();
        $end = ($room->scheduled_at ?? now())->addMinutes($room->duration_minutes ?? 60)->toIso8601String();

        return [
            'summary' => $room->title,
            'description' => trim(($room->description ?? '')."\n\nJoin: ".$room->joinUrl()),
            'location' => $room->joinUrl(),
            'start' => ['dateTime' => $start, 'timeZone' => $room->timezone],
            'end' => ['dateTime' => $end, 'timeZone' => $room->timezone],
            'organizer' => ['email' => $host->email, 'displayName' => $host->name],
        ];
    }
}
