import uuid

from sqlalchemy.ext.asyncio import AsyncSession

from db.redis import (
    acquire_speaker,
    release_speaker,
    get_active_speaker
)

from domains.groups.repo import get_group_by_id

from integrations.livekit.token_service import generate_join_token


async def request_speak(
    db: AsyncSession,
    group_id: str | uuid.UUID,
    user_id: str | uuid.UUID
):
    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
    group_id_str = str(group_id_uuid)
    user_id_str = str(user_id)

    group = await get_group_by_id(db, group_id_uuid)

    if not group:
        return None

    # private chat → no speaker lock
    if str(group.type) == "private":

        token = generate_join_token(
            user_id=user_id_str,
            group_id=group_id_str,
            can_publish=True
        )

        return token

    # group chat → push-to-talk
    granted = await acquire_speaker(group_id_str, user_id_str)

    if not granted:
        return None

    token = generate_join_token(
        user_id=user_id_str,
        group_id=group_id_str,
        can_publish=True
    )

    return token


async def stop_speaking(
    db: AsyncSession,
    group_id: str | uuid.UUID,
    user_id: str | uuid.UUID
):
    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
    group_id_str = str(group_id_uuid)
    user_id_str = str(user_id)

    group = await get_group_by_id(db, group_id_uuid)

    if not group:
        return False

    # private chat → nothing to release
    if str(group.type) == "private":
        return True

    return await release_speaker(group_id_str, user_id_str)


async def current_speaker(
    db: AsyncSession,
    group_id: str | uuid.UUID
):
    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
    group_id_str = str(group_id_uuid)

    group = await get_group_by_id(db, group_id_uuid)

    if not group:
        return None

    if str(group.type) == "private":
        return None

    return await get_active_speaker(group_id_str)
