<?php

namespace App\Services\Meet;

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

class TownHallService
{
    public function startGreenRoom(Room $room, User $host): Session
    {
        abort_unless($room->type === 'town_hall', 422);

        $session = Session::create([
            'owner_ref' => $room->owner_ref,
            'room_id' => $room->id,
            'media_room_name' => app(RoomService::class)->mediaRoomName($room, 'green'),
            'status' => 'live',
            'session_mode' => 'green_room',
            'presenter_refs' => [$host->ownerRef()],
            'started_at' => now(),
        ]);

        $room->update(['status' => 'live']);

        app(\App\Services\Meet\Media\MediaProviderInterface::class)->createRoom($session->media_room_name);

        app(SessionService::class)->joinParticipant($session, $host, 'host');

        return $session;
    }

    public function goLive(Session $greenRoomSession, User $host): Session
    {
        abort_unless($greenRoomSession->session_mode === 'green_room', 422);

        $room = $greenRoomSession->room;
        $presenters = $greenRoomSession->presenter_refs ?? [];

        $greenRoomSession->update(['status' => 'ended', 'ended_at' => now()]);

        $liveSession = Session::create([
            'owner_ref' => $room->owner_ref,
            'room_id' => $room->id,
            'media_room_name' => app(RoomService::class)->mediaRoomName($room),
            'status' => 'live',
            'session_mode' => 'live',
            'presenter_refs' => $presenters,
            'started_at' => now(),
        ]);

        $room->update(['status' => 'live']);

        app(\App\Services\Meet\Media\MediaProviderInterface::class)->createRoom($liveSession->media_room_name);

        app(SessionService::class)->joinParticipant($liveSession, $host, 'host');

        foreach ($greenRoomSession->participants()->where('status', 'joined')->get() as $participant) {
            if ($participant->user_ref && ! in_array($participant->user_ref, $presenters, true)) {
                continue;
            }
        }

        return $liveSession;
    }

    public function successorLiveSession(Session $greenRoomSession): ?Session
    {
        if ($greenRoomSession->session_mode !== 'green_room' || $greenRoomSession->isLive()) {
            return null;
        }

        return $greenRoomSession->room->sessions()
            ->where('status', 'live')
            ->where('session_mode', 'live')
            ->where('id', '!=', $greenRoomSession->id)
            ->latest('started_at')
            ->first();
    }

    public function handoffCoHost(Session $session, Participant $from, string $toUserRef): Participant
    {
        abort_unless(in_array($from->role, ['host', 'co_host'], true), 403);

        $target = $session->participants()
            ->where('user_ref', $toUserRef)
            ->where('status', 'joined')
            ->firstOrFail();

        $from->update(['role' => 'participant']);
        $target->update(['role' => 'co_host']);

        $presenters = collect($session->presenter_refs ?? [])
            ->reject(fn ($ref) => $ref === $from->user_ref)
            ->push($toUserRef)
            ->unique()
            ->values()
            ->all();

        $session->update(['presenter_refs' => $presenters]);

        return $target->fresh();
    }

    public function addPresenter(Session $session, string $userRef): Session
    {
        $presenters = collect($session->presenter_refs ?? [])
            ->push($userRef)
            ->unique()
            ->values()
            ->all();

        $session->update(['presenter_refs' => $presenters]);

        $session->participants()
            ->where('user_ref', $userRef)
            ->where('status', 'joined')
            ->whereNotIn('role', ['host', 'co_host'])
            ->update(['role' => 'panelist']);

        return $session->fresh();
    }
}
