"""Project membership operations for ProjectService."""

from __future__ import annotations

from typing import TYPE_CHECKING
from uuid import UUID

from noteflow.domain.identity import ProjectMembership, ProjectRole
from noteflow.infrastructure.logging import get_logger

from ._types import ProjectMembershipRepositoryProvider

if TYPE_CHECKING:
    from collections.abc import Sequence

logger = get_logger(__name__)


class ProjectMembershipMixin:
    """Membership CRUD operations for projects."""

    async def add_project_member(
        self,
        uow: ProjectMembershipRepositoryProvider,
        project_id: UUID,
        user_id: UUID,
        role: ProjectRole,
    ) -> ProjectMembership | None:
        """Add a member to a project.

        Args:
            uow: Unit of work for database access.
            project_id: Project UUID.
            user_id: User UUID.
            role: Role to assign.

        Returns:
            Created membership, or None if projects not supported.
        """
        if not uow.supports_projects:
            return None

        membership = await uow.project_memberships.add(project_id, user_id, role)
        await uow.commit()

        logger.info("Added user %s to project %s as %s", user_id, project_id, role.value)
        return membership

    async def update_project_member_role(
        self,
        uow: ProjectMembershipRepositoryProvider,
        project_id: UUID,
        user_id: UUID,
        role: ProjectRole,
    ) -> ProjectMembership | None:
        """Update a project member's role.

        Args:
            uow: Unit of work for database access.
            project_id: Project UUID.
            user_id: User UUID.
            role: New role.

        Returns:
            Updated membership if found, None otherwise.
        """
        if not uow.supports_projects:
            return None

        membership = await uow.project_memberships.update_role(project_id, user_id, role)
        if membership:
            await uow.commit()
            logger.info("Updated role for user %s in project %s to %s", user_id, project_id, role.value)

        return membership

    async def remove_project_member(
        self,
        uow: ProjectMembershipRepositoryProvider,
        project_id: UUID,
        user_id: UUID,
    ) -> bool:
        """Remove a member from a project.

        Args:
            uow: Unit of work for database access.
            project_id: Project UUID.
            user_id: User UUID.

        Returns:
            True if removed, False if not found.
        """
        if not uow.supports_projects:
            return False

        removed = await uow.project_memberships.remove(project_id, user_id)
        if removed:
            await uow.commit()
            logger.info("Removed user %s from project %s", user_id, project_id)

        return removed

    async def list_project_members(
        self,
        uow: ProjectMembershipRepositoryProvider,
        project_id: UUID,
        limit: int = 100,
        offset: int = 0,
    ) -> Sequence[ProjectMembership]:
        """List members of a project.

        Args:
            uow: Unit of work for database access.
            project_id: Project UUID.
            limit: Maximum members to return.
            offset: Pagination offset.

        Returns:
            List of memberships.
        """
        if not uow.supports_projects:
            return []

        return await uow.project_memberships.list_for_project(project_id, limit, offset)

    async def get_project_membership(
        self,
        uow: ProjectMembershipRepositoryProvider,
        project_id: UUID,
        user_id: UUID,
    ) -> ProjectMembership | None:
        """Get a user's membership in a project.

        Args:
            uow: Unit of work for database access.
            project_id: Project UUID.
            user_id: User UUID.

        Returns:
            Membership if user is a member, None otherwise.
        """
        if not uow.supports_projects:
            return None

        return await uow.project_memberships.get(project_id, user_id)

    async def count_project_members(
        self,
        uow: ProjectMembershipRepositoryProvider,
        project_id: UUID,
    ) -> int:
        """Count members in a project.

        Args:
            uow: Unit of work for database access.
            project_id: Project UUID.

        Returns:
            Member count.
        """
        if not uow.supports_projects:
            return 0

        return await uow.project_memberships.count_for_project(project_id)
