"""Map authoritative workspace principals onto generated-app auth roles.

Only workspace ``owner`` and ``admin`` principals inherit staff authority.  All
other workspace roles are application members (or have no inherited identity at
all); generated-app code must not turn a viewer/billing/editor membership into
an administrative grant.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Optional
from uuid import UUID

SUPER_ADMIN_ROLE = "super_admin"
STAFF_ADMIN_ROLE = "admin"
CUSTOMER_MEMBER_ROLE = "member"


@dataclass(frozen=True)
class WorkspaceAppIdentity:
    email: str
    name: str
    workspace_role: str
    app_role: str
    is_owner: bool


def app_role_for_workspace_member(*, workspace_role: str | None, is_owner: bool) -> str | None:
    """Return the inherited app role for a Core workspace principal.

    This is deliberately fail-closed for unknown and non-administrative roles.
    The owner relationship is authoritative even if the membership row has a
    stale role name.
    """
    if is_owner:
        return SUPER_ADMIN_ROLE
    if (workspace_role or "").strip().lower() == "admin":
        return STAFF_ADMIN_ROLE
    return None


def remap_legacy_app_role(
    email: str,
    role: str,
    owner_email: Optional[str],
) -> str:
    """Git seed tables often mark a workspace admin as super_admin. Cap that."""
    normalized_email = (email or "").strip().lower()
    owner = (owner_email or "").strip().lower()
    if owner and normalized_email == owner:
        return SUPER_ADMIN_ROLE
    if owner and (role or "").strip().lower() == SUPER_ADMIN_ROLE:
        return STAFF_ADMIN_ROLE
    return role or CUSTOMER_MEMBER_ROLE


def _display_name(user) -> str:
    parts = [getattr(user, "first_name", None) or "", getattr(user, "last_name", None) or ""]
    joined = " ".join(part for part in parts if part).strip()
    return (getattr(user, "display_name", None) or joined or "").strip()


async def identities_for_workspace(
    db,
    workspace_id: UUID,
    owner_id: Optional[UUID],
) -> list[WorkspaceAppIdentity]:
    from src.domain.workspaces.repository import MembershipRepository

    found: list[WorkspaceAppIdentity] = []
    seen: set[str] = set()
    for _membership, role, user in await MembershipRepository(db).list_members(workspace_id):
        email = str(getattr(user, "email", "") or "").strip().lower()
        if not email or "@" not in email or email in seen:
            continue
        seen.add(email)
        is_owner = bool(owner_id) and user.id == owner_id
        workspace_role = str(getattr(role, "name", None) or "member").strip().lower()
        app_role = app_role_for_workspace_member(
            workspace_role=workspace_role,
            is_owner=is_owner,
        )
        if app_role is None:
            continue
        found.append(
            WorkspaceAppIdentity(
                email=email,
                name=_display_name(user),
                workspace_role=workspace_role,
                app_role=app_role,
                is_owner=is_owner,
            )
        )
    if owner_id and not any(item.is_owner for item in found):
        from src.domain.auth.models import User
        from sqlalchemy import select

        owner = (
            await db.execute(select(User).where(User.id == owner_id))
        ).scalar_one_or_none()
        email = str(getattr(owner, "email", "") or "").strip().lower() if owner else ""
        if email and "@" in email and email not in seen:
            found.insert(
                0,
                WorkspaceAppIdentity(
                    email=email,
                    name=_display_name(owner),
                    workspace_role="owner",
                    app_role=SUPER_ADMIN_ROLE,
                    is_owner=True,
                ),
            )
    return found
