"""Billing recipient resolution - shared resolver for all billing emails."""
from __future__ import annotations
from typing import List
from uuid import UUID

import structlog
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from src.domain.auth.models import User
from src.domain.workspaces.models import Workspace
from src.domain.workspaces.repository import MembershipRepository

logger = structlog.get_logger()

BILLING_PERMISSION = "billing.manage"
INVOICES_READ_PERMISSION = "invoices.read"


class BillingRecipientResolver:
    """
    Resolves workspace billing recipients: owner + members with billing permissions.
    Dedupes, excludes null/empty emails.
    """

    def __init__(self, db: AsyncSession):
        self._db = db
        self._memb_repo = MembershipRepository(db)

    async def get_recipients(
        self,
        workspace_id: UUID,
        *,
        include_invoices_read: bool = False,
    ) -> List[str]:
        """
        Return deduped list of emails for billing notifications.
        Owner is always included; members with billing.manage (and optionally invoices.read) are included.
        """
        emails: set[str] = set()

        ws_result = await self._db.execute(select(Workspace).where(Workspace.id == workspace_id))
        ws = ws_result.scalar_one_or_none()
        if not ws:
            logger.warning(
                "billing_recipients_workspace_not_found",
                workspace_id=str(workspace_id),
            )
            return []

        if ws.owner_id:
            u_result = await self._db.execute(select(User).where(User.id == ws.owner_id))
            u = u_result.scalar_one_or_none()
            if u and u.email and u.email.strip():
                emails.add(u.email.lower())

        members = await self._memb_repo.list_members(workspace_id)
        for m, role, u in members:
            if role:
                perms = role.permissions or []
                has_billing = BILLING_PERMISSION in perms
                has_invoices = include_invoices_read and INVOICES_READ_PERMISSION in perms
                if has_billing or has_invoices:
                    if u.email and u.email.strip():
                        emails.add(u.email.lower().strip())

        return sorted(emails)

    async def get_recipients_with_diagnostics(
        self,
        workspace_id: UUID,
        notification_type: str,
        source_object_id: str,
        *,
        include_invoices_read: bool = False,
    ) -> List[str]:
        """
        Get recipients and log diagnostic when none found.
        """
        recipients = await self.get_recipients(workspace_id, include_invoices_read=include_invoices_read)
        if not recipients:
            logger.warning(
                "billing_notification_zero_recipients",
                workspace_id=str(workspace_id),
                notification_type=notification_type,
                source_object_id=source_object_id,
            )
        return recipients
