"""Workspace billing + access snapshot for bootstrap and policy reuse."""
from __future__ import annotations

from typing import Any, Optional
from uuid import UUID

import structlog

from src.domain.billing.enums import AccessReason, BillingStatus, RoutingNextStep, RoutingReason
from src.domain.billing.normalization import (
    is_paid_billing_status,
    is_payable_plan,
    normalized_billing_status_from_row,
    requires_payment_flag,
    requires_plan_selection_flag,
)

logger = structlog.get_logger()


def build_workspace_billing_and_access(
    *,
    workspace_id: UUID,
    selected_plan_slug: Optional[str],
    security_policy_require_mfa_for_paid_users: bool,
    billing_last_checkout_return: Optional[str],
    sub: Optional[Any],
    user_has_mfa: bool,
) -> dict:
    """Build ``billing`` and ``access`` objects for one workspace (bootstrap / introspection)."""
    billing_status = normalized_billing_status_from_row(sub, selected_plan_slug)
    is_paid = is_paid_billing_status(billing_status)
    requires_payment = requires_payment_flag(billing_status, selected_plan_slug)
    requires_plan_selection = requires_plan_selection_flag(billing_status, selected_plan_slug)
    verifying = (
        not is_paid
        and (billing_last_checkout_return or "") == "success_return"
    )

    # MFA is required for any user who has completed plan selection (free, staff, or paid).
    # Exception: users still mid-onboarding (no plan selected, or plan selected but checkout not yet done).
    has_selected_plan = bool(selected_plan_slug) and not requires_plan_selection
    access_reason: Optional[str] = None
    if security_policy_require_mfa_for_paid_users and has_selected_plan and not user_has_mfa:
        access_reason = AccessReason.MFA_REQUIRED.value
    elif requires_payment:
        access_reason = AccessReason.BILLING_REQUIRED.value

    allowed = access_reason is None

    plan_slug = (getattr(sub, "plan_slug", None) if sub else None) or selected_plan_slug

    price_id = None
    if sub:
        price_id = getattr(sub, "stripe_price_id", None) or getattr(sub, "plan_id", None)
    if not price_id and plan_slug:
        price_id = plan_slug

    display_status = billing_status
    if verifying:
        display_status = BillingStatus.VERIFYING.value

    return {
        "billing": {
            "status": display_status,
            "raw_subscription_status": billing_status,
            "requires_payment": requires_payment,
            "requires_plan_selection": requires_plan_selection,
            "is_paid": is_paid,
            "is_payable": is_payable_plan(plan_slug),
            "is_verifying_checkout": verifying,
            "subscription_id": str(sub.id) if sub else None,
            "plan_id": price_id,
            "plan_slug": plan_slug,
        },
        "access": {
            "allowed": allowed,
            "reason": access_reason,
        },
    }


def compute_bootstrap_routing(
    *,
    workspaces_payloads: list[dict],
    requires_mfa_challenge: bool,
    pending_invites: Optional[list[dict]] = None,
) -> dict:
    """
    Global routing hints for /auth/me.

    Precedence: mfa_challenge → accept_invite (no workspaces, pending invites) → setup_mfa → ...
    """
    invites = pending_invites or []
    if requires_mfa_challenge:
        out = {
            "recommended_workspace_id": (workspaces_payloads[0]["id"] if workspaces_payloads else None),
            "next_step": RoutingNextStep.MFA_CHALLENGE.value,
            "next_path": "/auth/mfa",
            "reason": RoutingReason.MFA_REQUIRED.value,
        }
        logger.info("bootstrap_routing_decision", next_step=out["next_step"], reason=out["reason"])
        return out

    if not workspaces_payloads and invites:
        wid = invites[0].get("workspace_id")
        out = {
            "recommended_workspace_id": wid,
            "next_step": RoutingNextStep.ACCEPT_INVITE.value,
            "next_path": "/invite",
            "reason": RoutingReason.PENDING_WORKSPACE_INVITES.value,
        }
        logger.info(
            "bootstrap_routing_decision",
            next_step=out["next_step"],
            reason=out["reason"],
            workspace_id=wid,
            invite_count=len(invites),
        )
        return out

    recommended = workspaces_payloads[0] if workspaces_payloads else None
    recommended_id = recommended["id"] if recommended else None

    any_mfa_required = any(
        w["access"].get("reason") == AccessReason.MFA_REQUIRED.value for w in workspaces_payloads
    )
    if any_mfa_required:
        # Prefer first workspace that needs MFA (usually same as paid-first ordering)
        target = next(
            (w for w in workspaces_payloads if w["access"].get("reason") == AccessReason.MFA_REQUIRED.value),
            recommended,
        )
        wid = target["id"] if target else recommended_id
        out = {
            "recommended_workspace_id": recommended_id,
            "next_step": RoutingNextStep.SETUP_MFA.value,
            "next_path": f"/setup/mfa?workspace_id={wid}",
            "reason": RoutingReason.MFA_REQUIRED.value,
        }
        logger.info("bootstrap_routing_decision", next_step=out["next_step"], reason=out["reason"], workspace_id=wid)
        return out

    if recommended and recommended["billing"].get("status") == BillingStatus.VERIFYING.value:
        out = {
            "recommended_workspace_id": recommended_id,
            "next_step": RoutingNextStep.VERIFY_PAYMENT.value,
            "next_path": f"/setup/verify-payment?workspace_id={recommended_id}",
            "reason": RoutingReason.PAYMENT_PENDING.value,
        }
        logger.info("bootstrap_routing_decision", next_step=out["next_step"], reason=out["reason"])
        return out

    if recommended:
        st = recommended["billing"].get("subscription_status") or recommended["billing"].get("status")
        reason = recommended["access"].get("reason")
        if reason == AccessReason.BILLING_REQUIRED.value and st not in (
            BillingStatus.NONE.value,
            BillingStatus.VERIFYING.value,
        ):
            out = {
                "recommended_workspace_id": recommended_id,
                "next_step": RoutingNextStep.FROZEN_WORKSPACE.value,
                "next_path": f"/billing?workspace_id={recommended_id}",
                "reason": RoutingReason.WORKSPACE_BILLING_LAPSED.value,
            }
            logger.info("bootstrap_routing_decision", next_step=out["next_step"], reason=out["reason"])
            return out

    if recommended and (
        recommended["billing"].get("requires_payment")
        or recommended["billing"].get("requires_plan_selection")
    ):
        out = {
            "recommended_workspace_id": recommended_id,
            "next_step": RoutingNextStep.SELECT_PLAN.value,
            "next_path": f"/setup/plan?workspace_id={recommended_id}",
            "reason": RoutingReason.WORKSPACE_REQUIRES_PLAN.value,
        }
        logger.info("bootstrap_routing_decision", next_step=out["next_step"], reason=out["reason"])
        return out

    out = {
        "recommended_workspace_id": recommended_id,
        "next_step": RoutingNextStep.DASHBOARD.value,
        "next_path": "/dashboard",
        "reason": RoutingReason.AUTHENTICATED_READY.value,
    }
    logger.info("bootstrap_routing_decision", next_step=out["next_step"], reason=out["reason"])
    return out
