<?php

namespace App\Services\Meet;

use App\Models\Participant;
use App\Models\Room;

class SpeakAccessService
{
    public function usesSpeakAccess(Room $room): bool
    {
        return $room->isWebinar() || $room->isConference();
    }

    public function canManageSpeakAccess(Participant $participant): bool
    {
        $room = $participant->session->room;

        if (! $this->usesSpeakAccess($room)) {
            return false;
        }

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

    public function requestSpeak(Participant $participant): Participant
    {
        $room = $participant->session->room;
        abort_unless($this->usesSpeakAccess($room), 422);
        abort_unless($participant->role === 'attendee', 422);
        abort_unless(! $participant->speak_granted, 422, 'You already have speak access.');

        $participant->update(['speak_requested' => true]);

        return $participant->fresh();
    }

    public function cancelSpeakRequest(Participant $participant): Participant
    {
        $participant->update(['speak_requested' => false]);

        return $participant->fresh();
    }

    public function grantSpeak(Participant $target, Participant $actor): Participant
    {
        abort_unless($this->canManageSpeakAccess($actor), 403);
        abort_unless($target->session_id === $actor->session_id, 404);
        abort_unless($target->status === 'joined', 422);
        abort_unless($this->usesSpeakAccess($target->session->room), 422);

        $target->update([
            'speak_granted' => true,
            'speak_requested' => false,
        ]);

        return $target->fresh();
    }

    public function revokeSpeak(Participant $target, Participant $actor): Participant
    {
        abort_unless($this->canManageSpeakAccess($actor), 403);
        abort_unless($target->session_id === $actor->session_id, 404);

        $target->update([
            'speak_granted' => false,
            'speak_requested' => false,
            'is_muted' => true,
        ]);

        return $target->fresh();
    }

    public function dismissSpeakRequest(Participant $target, Participant $actor): Participant
    {
        abort_unless($this->canManageSpeakAccess($actor), 403);
        abort_unless($target->session_id === $actor->session_id, 404);

        $target->update(['speak_requested' => false]);

        return $target->fresh();
    }
}
