import uuid
from livekit import api
from livekit.api.twirp_client import TwirpError
from sqlalchemy.ext.asyncio import AsyncSession
from core.logger import get_logger
from integrations.livekit.client import get_livekit_api
from db.redis import (
    acquire_speaker,
    release_speaker,
    get_active_speaker
)

logger = get_logger(__name__)


async def request_speak(
    group_id: str | uuid.UUID,
    user_id: str | uuid.UUID,
) -> bool:
    group_id_str = str(group_id)
    user_id_str = str(user_id)

    granted = await acquire_speaker(group_id_str, user_id_str)
    if not granted:
        return False

    await grant_publish_permission(group_id_str, user_id_str, True)
    return True


async def stop_speaking(
    group_id: str | uuid.UUID,
    user_id: str | uuid.UUID,
):
    group_id_str = str(group_id)
    user_id_str = str(user_id)

    released = await release_speaker(group_id_str, user_id_str)
    if released:
        await grant_publish_permission(group_id_str, user_id_str, False)
    return released

async def current_speaker(group_id: str | uuid.UUID):
    group_id_str = str(group_id)
    return await get_active_speaker(group_id_str)

async def grant_publish_permission(room_name: str, identity: str, can_publish: bool):
    lk_api = get_livekit_api()
    try:
        await lk_api.room.update_participant(
            api.UpdateParticipantRequest(
                room=room_name,
                identity=identity,
                permission=api.ParticipantPermission(
                    can_publish=can_publish,
                    can_subscribe=True
                )
            )
        )
    except TwirpError as e:
        if "not_found" in str(e).lower() or "exist" in str(e).lower():
            logger.warning(f"Participant {identity} already left the room.")
        else:
            logger.error(f"Error updating participant: {e}")
    except Exception as e:
        logger.error(f"Unexpected error in grant_permission: {e}")
