"""Auth bootstrap - canonical /auth/me response for frontend routing."""
from __future__ import annotations
from typing import Optional
from uuid import UUID

from src.domain.admin.repository import AdminRepository
from src.domain.auth.mfa_repository import TotpSecretRepository, WebAuthnCredentialRepository
from src.domain.auth.models import User
from src.domain.auth.totp_service import TotpService
from src.domain.billing.repository import SubscriptionRepository
from src.domain.billing.workspace_access import (
    build_workspace_billing_and_access,
    compute_bootstrap_routing,
)
from src.domain.workspaces.repository import (
    MembershipRepository,
    RoleRepository,
    WorkspaceInviteRepository,
    WorkspaceRepository,
)

_VALID_UI_THEMES = frozenset({"light", "dark", "system"})


def _coerce_ui_theme(user: User) -> str:
    v = getattr(user, "ui_theme", None)
    if isinstance(v, str) and v in _VALID_UI_THEMES:
        return v
    return "system"


class AuthBootstrapService:
    """Build auth/me bootstrap payload from DB only (no Stripe calls)."""

    def __init__(
        self,
        workspace_repo: WorkspaceRepository,
        membership_repo: MembershipRepository,
        role_repo: RoleRepository,
        subscription_repo: SubscriptionRepository,
        totp_repo: TotpSecretRepository,
        webauthn_repo: WebAuthnCredentialRepository,
        admin_repo: AdminRepository,
        invite_repo: WorkspaceInviteRepository,
    ):
        self._workspace_repo = workspace_repo
        self._membership_repo = membership_repo
        self._role_repo = role_repo
        self._subscription_repo = subscription_repo
        self._totp_repo = totp_repo
        self._webauthn_repo = webauthn_repo
        self._admin_repo = admin_repo
        self._invite_repo = invite_repo

    async def build_bootstrap(
        self,
        user: User,
        session_id: Optional[UUID] = None,
        *,
        requires_mfa_challenge: bool = False,
    ) -> dict:
        totp_svc = TotpService(self._totp_repo)
        has_totp = await totp_svc.is_enabled(user.id)
        webauthn_count = len(await self._webauthn_repo.list_for_user(user.id))
        has_webauthn = webauthn_count > 0
        mfa_enabled = has_totp or has_webauthn

        workspaces = await self._workspace_repo.list_for_user(user.id)
        workspace_payloads: list[dict] = []

        for idx, ws in enumerate(workspaces):
            if ws.deleted_at:
                continue
            memb = await self._membership_repo.get(ws.id, user.id)
            role_name = "viewer"
            if memb and memb.role_id:
                role_obj = await self._role_repo.get_by_id(memb.role_id)
                role_name = role_obj.name if role_obj else "viewer"

            sub = await self._subscription_repo.get_latest_for_workspace(ws.id)
            row = build_workspace_billing_and_access(
                workspace_id=ws.id,
                selected_plan_slug=getattr(ws, "selected_plan_slug", None),
                security_policy_require_mfa_for_paid_users=getattr(
                    ws, "security_policy_require_mfa_for_paid_users", True
                ),
                billing_last_checkout_return=getattr(ws, "billing_last_checkout_return", None),
                sub=sub,
                user_has_mfa=mfa_enabled,
            )
            billing = row["billing"]
            access = row["access"]
            # Public billing shape (authoritative for guards)
            billing_out = {
                "status": billing["status"],
                "subscription_status": billing["raw_subscription_status"],
                "requires_payment": billing["requires_payment"],
                "requires_plan_selection": billing["requires_plan_selection"],
                "subscription_id": billing["subscription_id"],
                "plan_id": billing["plan_id"],
                "plan_slug": billing["plan_slug"],
                "is_paid": billing["is_paid"],
                "is_payable": billing["is_payable"],
            }
            wp = {
                "id": str(ws.id),
                "name": ws.name,
                "role": role_name,
                "is_default": idx == 0,
                "billing": billing_out,
                "access": access,
            }
            workspace_payloads.append(wp)

        pending_invites: list[dict] = []
        if not workspace_payloads:
            rows = await self._invite_repo.list_pending_invites_for_email(user.email)
            for inv, ws, role in rows:
                pending_invites.append(
                    {
                        "id": str(inv.id),
                        "workspace_id": str(ws.id),
                        "workspace_name": ws.name,
                        "email": inv.email,
                        "role_name": role.name if role else None,
                        "expires_at": inv.expires_at.isoformat() if inv.expires_at else None,
                    }
                )

        any_requires_mfa_setup = any(
            w["access"].get("reason") == "mfa_required" for w in workspace_payloads
        )
        routing = compute_bootstrap_routing(
            workspaces_payloads=workspace_payloads,
            requires_mfa_challenge=requires_mfa_challenge,
            pending_invites=pending_invites,
        )
        # Backward-compatible alias for older frontends
        routing["next_step_alias"] = (
            "billing_checkout"
            if routing["next_step"] == "select_plan"
            else ("mfa_setup" if routing["next_step"] == "setup_mfa" else routing["next_step"])
        )

        is_platform_admin = await self._admin_repo.is_admin(user.id)

        return {
            "user": {
                "id": str(user.id),
                "email": user.email,
                "first_name": getattr(user, "first_name", None),
                "last_name": getattr(user, "last_name", None),
                "display_name": user.display_name,
                "phone": getattr(user, "phone", None),
                "company": getattr(user, "company", None),
                "ui_theme": _coerce_ui_theme(user),
                "email_verified": user.email_verified_at is not None,
                "has_totp": has_totp,
                "has_webauthn": has_webauthn,
                "mfa_enabled": mfa_enabled,
                "is_platform_admin": is_platform_admin,
                "discord_user_id": getattr(user, "discord_user_id", None),
                "discord_username": getattr(user, "discord_username", None),
                "discord_connected": bool(getattr(user, "discord_user_id", None)),
            },
            "session": {
                "authenticated": True,
                "requires_mfa_challenge": requires_mfa_challenge,
                "requires_mfa_setup": any_requires_mfa_setup,
            },
            "workspaces": workspace_payloads,
            "pending_invites": pending_invites,
            "routing": routing,
        }
