import uuid

from sqlalchemy.ext.asyncio import AsyncSession

from domains.users.repo import get_user_by_id
from domains.groups.models import Group, GroupMember, GroupType, GroupMemberRole
from domains.groups.repo import (
    create_group,
    get_group_by_id,
    add_group_member,
    get_user_groups,
    get_group_members_with_details,
    delete_group_member,
    delete_group,
    get_group_member,
    get_all_groups as repo_get_all_groups
)
from domains.realtime.presence_service import list_online_users
from domains.users.repo import get_user_by_username
from domains.notifications.service import send_join_request


async def create_user_group(
    db: AsyncSession,
    name: str,
    owner_id: uuid.UUID,
):
    group = Group(
        name=name,
        type=GroupType.PRIVATE,
        owner_id=owner_id
    )

    await create_group(db, group)

    # Owner becomes Manager
    membership = GroupMember(
        group_id=group.id,
        user_id=owner_id,
        role=GroupMemberRole.MANAGER
    )
    await add_group_member(db, membership)
    
    return group


async def create_admin_group(
    db: AsyncSession,
    name: str,
    owner_id: uuid.UUID,
):
    group = Group(
        name=name,
        type=GroupType.PUBLIC,
        owner_id=owner_id
    )

    await create_group(db, group)
    return group


async def invite_member_to_group(
    db: AsyncSession,
    group_id: str | uuid.UUID,
    sender_id: uuid.UUID,
    target_username: str
):
    

    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)

    # 1. Check if group exists
    group = await get_group_by_id(db, group_id_uuid)
    if not group:
        raise ValueError("گروهی یافت نشد")

    sender = await get_user_by_id(db, sender_id)
    if not sender:
        raise ValueError("فرستنده یافت نشد")

    if not sender.is_admin:
        membership = await get_group_member(db, group_id_uuid, sender_id)
        if not membership:
            raise ValueError("شما عضو این گروه نیستید")

    # 2. Check if target user exists
    target_user = await get_user_by_username(db, target_username)
    if not target_user:
        raise ValueError("کاربری یافت نشد")

    # 3. Send notification (Req 12)
    return await send_join_request(
        db,
        sender_id=sender_id,
        receiver_id=target_user.id,
        group_id=group.id,
        title="دعوت به گروه",
        description=f"شما به گروه {group.name} دعوت شده‌اید"
    )


async def add_member_to_group(
    db: AsyncSession,
    group_id: str | uuid.UUID,
    user_id: str | uuid.UUID,
    role: GroupMemberRole = GroupMemberRole.MEMBER
):
    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
    user_id_uuid = user_id if isinstance(user_id, uuid.UUID) else uuid.UUID(user_id)

    existing = await get_group_member(db, group_id_uuid, user_id_uuid)
    if existing:
        raise ValueError("کاربر از قبل عضو گروه است")

    membership = GroupMember(
        group_id=group_id_uuid,
        user_id=user_id_uuid,
        role=role
    )
    return await add_group_member(db, membership)


async def list_user_groups(
    db: AsyncSession,
    user_id: uuid.UUID
):
    return await get_user_groups(db, user_id)


async def list_all_groups_admin(db: AsyncSession):
    return await repo_get_all_groups(db)


async def list_group_members_api(db: AsyncSession, group_id: str | uuid.UUID):
    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
    members_data = await get_group_members_with_details(db, group_id_uuid)
    online_users = await list_online_users(str(group_id_uuid))
    
    result = []
    for member_info in members_data:
        member, username = member_info
        result.append({
            "user_id": member.user_id,
            "username": username,
            "role": member.role,
            "is_online": str(member.user_id) in online_users
        })
    return result


async def remove_member_from_group(
    db: AsyncSession,
    group_id: str | uuid.UUID,
    target_user_id: str | uuid.UUID,
    requesting_user
):
    group_id_uuid = group_id if isinstance(group_id, uuid.UUID) else uuid.UUID(group_id)
    target_user_id_uuid = target_user_id if isinstance(target_user_id, uuid.UUID) else uuid.UUID(target_user_id)

    group = await get_group_by_id(db, group_id_uuid)
    if not group:
        raise ValueError("گروهی یافت نشد")

    # Admin can remove anyone
    if not requesting_user.is_admin:
        membership = await get_group_member(db, group_id_uuid, requesting_user.id)
        if not membership or membership.role != GroupMemberRole.MANAGER:
            raise PermissionError("دسترسی لازم را ندارید")

    if group.owner_id == target_user_id_uuid:
        raise ValueError("حذف سازنده گروه مجاز نیست")

    target_membership = await get_group_member(db, group_id_uuid, target_user_id_uuid)
    if not target_membership:
        raise ValueError("کاربر عضو این گروه نیست")

    if not requesting_user.is_admin and target_membership.role != GroupMemberRole.MEMBER:
        raise ValueError("حذف مدیر گروه مجاز نیست")

    await delete_group_member(db, group_id_uuid, target_user_id_uuid)


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

    group = await get_group_by_id(db, group_id_uuid)
    if not group:
        raise ValueError("گروهی یافت نشد")

    # Permission check: System Admin or Group Owner
    if not requesting_user.is_admin and group.owner_id != requesting_user.id:
        raise ValueError("شما دسترسی لازم برای حذف گروه را ندارید (فقط سازنده گروه یا ادمین سیستم)")

    await delete_group(db, group_id_uuid)
