<?php

namespace App\Services\Meet;

use App\Models\Invitation;
use App\Models\Participant;
use App\Models\Room;
use App\Models\Session;
use App\Models\User;

class ConferenceService
{
    /**
     * @param  list<string>  $presenterRefs
     */
    public function syncPresenterRefs(Room $room, array $presenterRefs): Room
    {
        $presenterRefs = array_values(array_unique(array_filter($presenterRefs)));
        $settings = array_merge($room->settings ?? [], ['presenter_refs' => $presenterRefs]);
        $room->update(['settings' => $settings]);

        $session = $room->activeSession();
        if ($session) {
            $merged = collect($session->presenter_refs ?? [])
                ->merge($presenterRefs)
                ->unique()
                ->values()
                ->all();
            $session->update(['presenter_refs' => $merged]);
        }

        return $room->fresh();
    }

    /**
     * @return list<string>
     */
    public function presenterRefs(Room $room): array
    {
        return array_values(array_unique(array_filter(
            (array) $room->setting('presenter_refs', []),
        )));
    }

    public function resolveJoinRole(Room $room, ?User $user, ?string $email, string $fallbackRole = 'guest'): string
    {
        if ($user && $user->ownerRef() === $room->host_user_ref) {
            return 'host';
        }

        $presenterRefs = $this->presenterRefs($room);

        if ($user && in_array($user->ownerRef(), $presenterRefs, true)) {
            return 'panelist';
        }

        if ($email && $this->invitationRole($room, $email) === 'panelist') {
            return 'panelist';
        }

        if ($room->isTownHall()) {
            return 'attendee';
        }

        return $fallbackRole;
    }

    public function canJoinSession(Room $room, Session $session, string $role): bool
    {
        if ($session->session_mode !== 'green_room') {
            return true;
        }

        return in_array($role, ['host', 'co_host', 'panelist'], true);
    }

    public function isPresenter(Session $session, Participant $participant): bool
    {
        if (in_array($participant->role, ['host', 'co_host', 'panelist'], true)) {
            return true;
        }

        $refs = (array) $session->presenter_refs;

        return $participant->user_ref && in_array($participant->user_ref, $refs, true);
    }

    public function canPublish(Room $room, Participant $participant): bool
    {
        if (in_array($participant->role, ['host', 'co_host', 'panelist'], true)) {
            return true;
        }

        if ($room->isTownHall() || $room->isWebinar()) {
            return (bool) $participant->speak_granted;
        }

        return in_array($participant->role, ['host', 'co_host', 'panelist'], true);
    }

    public function registerPresenter(Session $session, ?User $user, string $role): void
    {
        if (! $user || ! in_array($role, ['host', 'co_host', 'panelist'], true)) {
            return;
        }

        app(TownHallService::class)->addPresenter($session, $user->ownerRef());
    }

    protected function invitationRole(Room $room, string $email): ?string
    {
        return Invitation::query()
            ->where('room_id', $room->id)
            ->where('email', strtolower(trim($email)))
            ->value('role');
    }
}
