<?php

namespace App\Services\Meet;

use App\Models\Organization;
use App\Models\Room;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Str;

class RecurringMeetingService
{
    public function __construct(
        protected RoomService $rooms,
    ) {}

    /**
     * @param  array<string, mixed>  $data
     */
    public function createSeries(User $user, Organization $organization, array $data): Room
    {
        $seriesId = (string) Str::uuid();

        $room = $this->rooms->createScheduled($user, $organization, array_merge($data, [
            'recurring_series_id' => $seriesId,
            'recurrence_rule' => $data['recurrence_rule'],
            'recurrence_interval' => $data['recurrence_interval'] ?? 1,
            'recurrence_until' => $data['recurrence_until'] ?? null,
        ]));

        $this->spawnNextOccurrences($room, 5);

        return $room;
    }

    public function spawnNextOccurrences(Room $parent, int $count = 1): void
    {
        if (! $parent->isRecurring()) {
            return;
        }

        $last = Room::where('recurring_series_id', $parent->recurring_series_id)
            ->orderByDesc('scheduled_at')
            ->first();

        $cursor = Carbon::parse($last?->scheduled_at ?? $parent->scheduled_at);

        for ($i = 0; $i < $count; $i++) {
            $cursor = $this->nextOccurrence($cursor, $parent->recurrence_rule, (int) $parent->recurrence_interval);

            if ($parent->recurrence_until && $cursor->toDateString() > $parent->recurrence_until) {
                break;
            }

            if (Room::where('recurring_series_id', $parent->recurring_series_id)
                ->whereDate('scheduled_at', $cursor->toDateString())
                ->exists()) {
                continue;
            }

            Room::create([
                'owner_ref' => $parent->owner_ref,
                'organization_id' => $parent->organization_id,
                'branch_id' => $parent->branch_id,
                'host_user_ref' => $parent->host_user_ref,
                'title' => $parent->title,
                'description' => $parent->description,
                'type' => 'scheduled',
                'status' => 'scheduled',
                'scheduled_at' => $cursor,
                'duration_minutes' => $parent->duration_minutes,
                'timezone' => $parent->timezone,
                'passcode' => $parent->passcode,
                'settings' => $parent->settings,
                'recurring_series_id' => $parent->recurring_series_id,
                'recurrence_rule' => $parent->recurrence_rule,
                'recurrence_interval' => $parent->recurrence_interval,
                'recurrence_until' => $parent->recurrence_until,
            ]);
        }
    }

    protected function nextOccurrence(Carbon $from, string $rule, int $interval): Carbon
    {
        return match ($rule) {
            'daily' => $from->copy()->addDays($interval),
            'weekly' => $from->copy()->addWeeks($interval),
            'monthly' => $from->copy()->addMonths($interval),
            default => $from->copy()->addWeeks($interval),
        };
    }
}
