"""
Admin Customer Management API
Read-only customer list and detail views for admin dashboard.

Phase 1: View-only (no mutations yet)
- List customers with filtering/pagination
- View customer details (subscription, usage, credits)
- Audit trail logging

Future phases will add mutation endpoints (credit adjustments, tier overrides).
"""

from fastapi import APIRouter, Depends, HTTPException, Query, Body
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_
from typing import Dict, Any, List, Optional, Literal
from datetime import datetime
import logging
import httpx
from pydantic import BaseModel
import asyncio

from ...db import get_session
from ...models import Account, AccountUsage, User, APIKey, UsageQuotaModel
from ...auth_security import require_admin, AdminContext
from ...services.admin_audit import log_admin_action
from ...services.admin_surface_signals import (
    add_keyword_surface_reasons,
    classify_account_identity,
    collect_account_surface_signals,
    SurfaceSignals,
)
from ...services.usage_gateway import UsageGateway
from ...middleware.quota_checker import get_quota, TIER_LIMITS
from ... import settings as saas_settings

log = logging.getLogger(__name__)

router = APIRouter(prefix="/admin/customers", tags=["Admin"])


def _normalize_accepted_at(value: Any) -> Optional[str]:
    """Normalize Clerk legal acceptance timestamps to ISO strings."""
    if value is None:
        return None
    if isinstance(value, str):
        return value
    if isinstance(value, (int, float)):
        # Detect ms vs seconds
        ts = float(value)
        if ts > 1e12:
            ts = ts / 1000.0
        return datetime.utcfromtimestamp(ts).isoformat() + "Z"
    return None


async def _fetch_clerk_legal_acceptance(
    clerk_user_ids: List[str],
) -> Dict[str, Dict[str, Any]]:
    """Fetch legal acceptance metadata from Clerk for a list of user IDs."""
    clerk_secret = saas_settings.CLERK_SECRET_KEY
    if not clerk_secret or not clerk_user_ids:
        return {}

    headers = {"Authorization": f"Bearer {clerk_secret}"}
    results: Dict[str, Dict[str, Any]] = {}
    semaphore = asyncio.Semaphore(10)

    async def fetch_one(user_id: str) -> None:
        if not user_id:
            return
        async with semaphore:
            try:
                resp = await client.get(
                    f"https://api.clerk.com/v1/users/{user_id}", headers=headers
                )
                if not resp.is_success:
                    return
                data = resp.json()
                meta = data.get("private_metadata", {}) or {}
                legal = meta.get("legalAcceptance") or meta.get("legal_acceptance") or {}
                accepted_at_raw = legal.get("acceptedAt") or legal.get("accepted_at")
                accepted_at = _normalize_accepted_at(accepted_at_raw)
                results[user_id] = {
                    "accepted": bool(legal.get("accepted", True) if accepted_at else False)
                    if legal
                    else False,
                    "accepted_at": accepted_at,
                    "terms_version": legal.get("termsVersion")
                    or legal.get("terms_version"),
                    "privacy_version": legal.get("privacyVersion")
                    or legal.get("privacy_version"),
                    "source": "clerk",
                }
            except Exception as exc:  # noqa: BLE001
                log.debug("Failed Clerk legal fetch for %s: %s", user_id, exc)

    async with httpx.AsyncClient(timeout=10.0) as client:
        await asyncio.gather(*(fetch_one(uid) for uid in set(clerk_user_ids) if uid))
    return results


class AdminTierUpdatePayload(BaseModel):
    """Manual tier update payload submitted from the admin UI."""

    tier: Literal["free", "pro", "scale", "unleashed"]
    status: str = "active"
    monthly_enrichments: Optional[int] = None
    monthly_match_limit: Optional[int] = None
    source: Optional[str] = "admin_manual"
    addons: Optional[List[str]] = None


class AdminClerkSyncResult(BaseModel):
    """Response shape for Clerk sync operations."""

    ok: bool
    tier: str
    status: str
    monthly_enrichments: Optional[int] = None
    monthly_match_limit: Optional[int] = None
    message: Optional[str] = None
    sync_source: Optional[str] = None
    synced_at: Optional[str] = None


class DoNotContactPayload(BaseModel):
    value: bool


async def _apply_tier_update(
    account_id: str,
    tier: str,
    status: str,
    monthly_rows: int,
    monthly_enrichments: int,
    source: str,
    addons: Optional[List[str]],
    db: AsyncSession,
) -> UsageQuotaModel:
    """Upsert UsageQuotaModel with the supplied tier metadata."""

    stmt = select(UsageQuotaModel).where(UsageQuotaModel.account_id == account_id)
    result = await db.execute(stmt)
    quota = result.scalar_one_or_none()
    now = datetime.utcnow()

    if not quota:
        quota = UsageQuotaModel(
            account_id=account_id,
            tier=tier,
            monthly_rows_used=0,
            enrichment_credits_used=0,
            subscription_status=status or "unknown",
            tier_synced_at=now,
            tier_sync_source=source,
            monthly_enrichment_entitlement=monthly_enrichments,
            monthly_match_entitlement=monthly_rows,
        )
        db.add(quota)
        await db.commit()
        await db.refresh(quota)
        return quota

    quota.tier = tier
    quota.subscription_status = status or quota.subscription_status or "unknown"
    quota.tier_synced_at = now
    quota.tier_sync_source = source or quota.tier_sync_source or "admin_manual"
    quota.monthly_enrichment_entitlement = monthly_enrichments
    quota.monthly_match_entitlement = monthly_rows

    await db.commit()
    await db.refresh(quota)

    try:
        gateway = UsageGateway(db)
        await gateway.sync_from_stripe(
            account_id=account_id,
            tier=tier,
            addons=addons or [],
            source=source or "admin_manual",
            monthly_row_limit=monthly_rows,
        )
    except Exception as exc:  # noqa: BLE001 - best effort
        log.warning("Failed to sync usage gateway for %s: %s", account_id, exc)

    return quota


def _resolve_entitlements_from_limits(
    tier: str,
    monthly_rows_override: Optional[int],
    monthly_enrichments_override: Optional[int],
) -> tuple[int, int]:
    limits = TIER_LIMITS.get(tier, TIER_LIMITS["free"])
    return (
        monthly_rows_override or limits["monthly_rows"],
        monthly_enrichments_override or limits["enrichment_credits"],
    )


def _primary_user_subquery(column_name: str):
    return (
        select(getattr(User, column_name))
        .where(User.account_id == Account.id)
        .order_by(User.created_at.asc(), User.id.asc())
        .limit(1)
        .scalar_subquery()
    )


def _user_count_subquery():
    return (
        select(func.count(User.id))
        .where(User.account_id == Account.id)
        .scalar_subquery()
    )


@router.get("")
async def list_customers(
    admin_ctx: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
    search: Optional[str] = Query(None, description="Search by account name or email"),
    tier: Optional[str] = Query(None, description="Filter by tier (free/pro/scale)"),
    status: Optional[str] = Query(
        None, description="Filter by status (active/inactive)"
    ),
    page: int = Query(1, ge=1, description="Page number"),
    limit: int = Query(50, ge=1, le=100, description="Items per page"),
) -> Dict[str, Any]:
    """
    List all customer accounts with filtering and pagination.

    Query Parameters:
        - search: Search by account name or user email
        - tier: Filter by subscription tier (free/pro/scale)
        - status: Filter by account status
        - page: Page number (starts at 1)
        - limit: Items per page (max 100)

    Returns:
        - customers: List of customer objects
        - pagination: Page info (page, limit, total, pages)
    """
    try:
        primary_user_id = _primary_user_subquery("id").label("primary_user_id")
        primary_email = _primary_user_subquery("email").label("primary_email")
        primary_clerk_user_id = _primary_user_subquery("clerk_user_id").label(
            "primary_clerk_user_id"
        )
        user_count = _user_count_subquery().label("user_count")

        # Build base query
        query = (
            select(
                Account.id,
                Account.name,
                Account.clerk_org_id,
                Account.stripe_customer_id,
                Account.stripe_subscription_id,
                Account.purchased_credits,
                Account.data_region,
                primary_user_id,
                primary_email,
                primary_clerk_user_id,
                user_count,
                UsageQuotaModel.tier,
                UsageQuotaModel.subscription_status,
                UsageQuotaModel.monthly_rows_used,
                UsageQuotaModel.enrichment_credits_used,
                UsageQuotaModel.reset_at,
                UsageQuotaModel.tier_synced_at,
                UsageQuotaModel.tier_sync_source,
                UsageQuotaModel.monthly_match_entitlement,
                UsageQuotaModel.monthly_enrichment_entitlement,
                AccountUsage.gremlin_messages_used,
                AccountUsage.webhook_rows_used,
            )
            .select_from(Account)
            .outerjoin(UsageQuotaModel, Account.id == UsageQuotaModel.account_id)
            .outerjoin(AccountUsage, Account.id == AccountUsage.account_id)
        )

        # Apply filters
        if search:
            search_term = f"%{search}%"
            query = query.where(
                or_(
                    Account.name.ilike(search_term),
                    primary_email.ilike(search_term),
                    Account.id.ilike(search_term),
                    Account.clerk_org_id.ilike(search_term),
                )
            )

        if tier:
            query = query.where(UsageQuotaModel.tier == tier)

        # Get total count
        count_query = select(func.count()).select_from(Account)
        if search:
            count_query = count_query.where(
                or_(
                    Account.name.ilike(search_term),
                    primary_email.ilike(search_term),
                    Account.id.ilike(search_term),
                    Account.clerk_org_id.ilike(search_term),
                )
            )
        if tier:
            count_query = count_query.outerjoin(
                UsageQuotaModel, Account.id == UsageQuotaModel.account_id
            ).where(UsageQuotaModel.tier == tier)

        total_result = await db.execute(count_query)
        total = total_result.scalar() or 0

        # Apply pagination
        offset = (page - 1) * limit
        query = query.offset(offset).limit(limit)

        # Execute query
        result = await db.execute(query)
        rows = result.all()
        clerk_ids = [
            row.primary_clerk_user_id for row in rows if row.primary_clerk_user_id
        ]
        clerk_legal_map = await _fetch_clerk_legal_acceptance(clerk_ids)
        surface_signals_map = await collect_account_surface_signals(
            db,
            account_ids=[row.id for row in rows],
            primary_emails_by_account={row.id: row.primary_email for row in rows},
        )

        # Format results
        customers: List[Dict[str, Any]] = []
        for row in rows:
            tier_name = row.tier or "free"
            limits = TIER_LIMITS.get(tier_name, TIER_LIMITS["free"])
            subscription_status = row.subscription_status or (
                "active" if row.stripe_subscription_id else "free"
            )
            monthly_rows_limit = row.monthly_match_entitlement or limits["monthly_rows"]
            monthly_enrichment_limit = (
                row.monthly_enrichment_entitlement or limits["enrichment_credits"]
            )
            identity = classify_account_identity(
                account_id=row.id,
                account_name=row.name,
                clerk_org_id=row.clerk_org_id,
                primary_user_id=row.primary_user_id,
                primary_clerk_user_id=row.primary_clerk_user_id,
                user_count=row.user_count or 0,
            )
            surface_signals = surface_signals_map.get(row.id) or SurfaceSignals()
            if int(row.gremlin_messages_used or 0) > 0:
                surface_signals.add(
                    "gremlin",
                    f"account_usage.gremlin_messages_used:{int(row.gremlin_messages_used)}",
                )
            if int(row.webhook_rows_used or 0) > 0:
                surface_signals.add(
                    "sheets",
                    f"account_usage.webhook_rows_used:{int(row.webhook_rows_used)}",
                )
            add_keyword_surface_reasons(
                surface_signals,
                reason_prefix="sync_source",
                values=(row.tier_sync_source,),
            )

            customers.append(
                {
                    "account_id": row.id,
                    "name": row.name,
                    "email": row.primary_email,
                    "primary_email": row.primary_email,
                    "identity": identity,
                    "surfaces": {
                        "flags": surface_signals.flags(),
                        "reasons": surface_signals.reasons,
                    },
                    "tier": tier_name,
                    "status": subscription_status,
                    "stripe_customer_id": row.stripe_customer_id,
                    "usage": {
                        "monthly_rows_used": row.monthly_rows_used or 0,
                        "monthly_rows_limit": monthly_rows_limit,
                        "credits_used": row.enrichment_credits_used or 0,
                        "credits_limit": monthly_enrichment_limit,
                        "row_usage_pct": round(
                            ((row.monthly_rows_used or 0) / monthly_rows_limit * 100)
                            if monthly_rows_limit
                            else 0,
                            1,
                        ),
                        "credit_usage_pct": round(
                            (
                                (row.enrichment_credits_used or 0)
                                / monthly_enrichment_limit
                                * 100
                                if monthly_enrichment_limit
                                else 0
                            ),
                            1,
                        ),
                    },
                    "entitlements": {
                        "monthly_rows_limit": monthly_rows_limit,
                        "monthly_enrichment_credits": monthly_enrichment_limit,
                        "default_monthly_rows": limits["monthly_rows"],
                        "default_monthly_enrichment_credits": limits[
                            "enrichment_credits"
                        ],
                        "rows_drift": monthly_rows_limit != limits["monthly_rows"],
                        "enrichment_drift": monthly_enrichment_limit
                        != limits["enrichment_credits"],
                    },
                    "sync": {
                        "last_synced_at": row.tier_synced_at.isoformat()
                        if row.tier_synced_at
                        else None,
                        "source": row.tier_sync_source or "unknown",
                    },
                    "purchased_credits": row.purchased_credits or 0,
                    "reset_at": row.reset_at.isoformat() if row.reset_at else None,
                    "data_region": row.data_region,
                    "legal": clerk_legal_map.get(row.primary_clerk_user_id)
                    if row.primary_clerk_user_id
                    else None,
                }
            )

        # Log admin action
        await log_admin_action(
            admin_user_id=admin_ctx.user_id,
            admin_email=admin_ctx.email,
            action="list_customers",
            db=db,
            details={"page": page, "search": search, "tier": tier},
        )

        return {
            "ok": True,
            "data": {
                "customers": customers,
                "pagination": {
                    "page": page,
                    "limit": limit,
                    "total": total,
                    "pages": (total + limit - 1) // limit,  # Ceiling division
                },
            },
        }

    except Exception as e:
        log.error(f"Failed to list customers: {e}", exc_info=True)
        raise HTTPException(500, f"Failed to list customers: {e}")


@router.get("/{account_id}")
async def get_customer_detail(
    account_id: str,
    admin_ctx: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """
    Get detailed information about a specific customer account.

    Includes:
        - Account info
        - Users associated with account
        - Subscription details
        - Usage history (last 6 months)
        - Credit purchase history (if any)
        - Active API keys

    Returns detailed customer object with nested data.
    """
    try:
        # Get account
        account_result = await db.execute(
            select(Account).where(Account.id == account_id)
        )
        account = account_result.scalar_one_or_none()

        if not account:
            raise HTTPException(404, f"Account {account_id} not found")

        # Get users
        users_result = await db.execute(
            select(User).where(User.account_id == account_id)
        )
        users = users_result.scalars().all()
        clerk_ids = [user.clerk_user_id for user in users if user.clerk_user_id]
        clerk_legal_map = await _fetch_clerk_legal_acceptance(clerk_ids)

        # Get quota/usage
        quota = await get_quota(account_id, db)
        limits = quota.get_limits()

        quota_model_result = await db.execute(
            select(UsageQuotaModel).where(UsageQuotaModel.account_id == account_id)
        )
        quota_model = quota_model_result.scalar_one_or_none()

        subscription_status = (
            quota_model.subscription_status
            if quota_model and quota_model.subscription_status
            else "unknown"
        )
        monthly_rows_limit = (
            quota_model.monthly_match_entitlement
            if quota_model and quota_model.monthly_match_entitlement is not None
            else limits["monthly_rows"]
        )
        monthly_enrichment_limit = (
            quota_model.monthly_enrichment_entitlement
            if quota_model and quota_model.monthly_enrichment_entitlement is not None
            else limits["enrichment_credits"]
        )

        # Get usage history (last 6 months)
        from ..services.usage_history_service import UsageHistoryService

        usage_history_service = UsageHistoryService(db)
        usage_history_records = await usage_history_service.get_history(
            account_id=account_id,
            months=6,
            ensure_snapshots=True,  # Auto-create missing snapshots for recent months
        )

        # Format usage history for response
        usage_history = [
            {
                "period": record.period,
                "rows_processed": record.rows_processed,
                "matches_found": record.matches_found,
                "dedupes_run": record.dedupes_run,
                "enrichments_performed": record.enrichments_performed,
                "enrichment_credits_consumed": record.enrichment_credits_consumed,
                "records_enriched": record.records_enriched,
                "api_calls": record.api_calls,
                "jobs_completed": record.jobs_completed,
                "cost_usd": float(record.cost_usd) if record.cost_usd else None,
                "price_usd": float(record.price_usd) if record.price_usd else None,
                "margin_usd": float(record.margin_usd) if record.margin_usd else None,
                "operation_breakdown": record.operation_breakdown,
                "tier": record.tier_at_snapshot,
                "subscription_status": record.subscription_status,
            }
            for record in usage_history_records
        ]

        # Get webhook usage from AccountUsage
        account_usage_result = await db.execute(
            select(AccountUsage).where(AccountUsage.account_id == account_id)
        )
        account_usage = account_usage_result.scalar_one_or_none()

        # Get API keys
        api_keys_result = await db.execute(
            select(APIKey).where(APIKey.account_id == account_id)
        )
        api_keys = api_keys_result.scalars().all()

        # Format response
        customer_data = {
            "account": {
                "id": account.id,
                "name": account.name,
                "stripe_customer_id": account.stripe_customer_id,
                "stripe_subscription_id": account.stripe_subscription_id,
                "purchased_credits": account.purchased_credits or 0,
                "data_region": account.data_region,
                "do_not_contact": account.do_not_contact,
                "do_not_contact_since": account.do_not_contact_since.isoformat()
                if account.do_not_contact_since
                else None,
            },
            "subscription": {
                "tier": quota.tier,
                "status": subscription_status,
                "monthly_rows_limit": monthly_rows_limit,
                "monthly_credits_limit": monthly_enrichment_limit,
                "default_monthly_rows_limit": limits["monthly_rows"],
                "default_monthly_credits_limit": limits["enrichment_credits"],
                "max_schedules": limits["max_schedules"],
                "salesforce_orgs_limit": limits["salesforce_orgs"],
                "users_limit": limits["users"],
                "reset_at": quota.reset_at.isoformat() if quota.reset_at else None,
                "last_synced_at": quota_model.tier_synced_at.isoformat()
                if quota_model and quota_model.tier_synced_at
                else None,
                "sync_source": quota_model.tier_sync_source
                if quota_model and quota_model.tier_sync_source
                else None,
                "drift": {
                    "rows_drift": monthly_rows_limit != limits["monthly_rows"],
                    "credits_drift": monthly_enrichment_limit
                    != limits["enrichment_credits"],
                },
            },
            "usage": {
                "monthly_rows_used": quota.monthly_rows_used,
                "monthly_rows_remaining": max(
                    0, monthly_rows_limit - quota.monthly_rows_used
                ),
                "enrichment_credits_used": quota.enrichment_credits_used,
                "enrichment_credits_remaining": max(
                    0, monthly_enrichment_limit - quota.enrichment_credits_used
                ),
                "usage_pct_rows": round(
                    (quota.monthly_rows_used / monthly_rows_limit * 100)
                    if monthly_rows_limit
                    else 0,
                    1,
                ),
                "usage_pct_enrichments": round(
                    (quota.enrichment_credits_used / monthly_enrichment_limit * 100)
                    if monthly_enrichment_limit
                    else 0,
                    1,
                ),
                "purchased_credits": account.purchased_credits or 0,
                "total_credits_available": (account.purchased_credits or 0)
                + max(0, monthly_enrichment_limit - quota.enrichment_credits_used),
                "webhook_rows_used": int(
                    getattr(account_usage, "webhook_rows_used", 0) or 0
                ),
                "webhook_rows_limit": int(limits.get("webhook_rows_per_month", 0) or 0),
            },
            "users": [
                {
                    "id": user.id,
                    "email": user.email,
                    "role": user.role,
                    "created_at": user.created_at.isoformat()
                    if user.created_at
                    else None,
                    "last_login": user.last_login.isoformat()
                    if user.last_login
                    else None,
                    "legal": clerk_legal_map.get(user.clerk_user_id)
                    if user.clerk_user_id
                    else None,
                }
                for user in users
            ],
            "api_keys": [
                {
                    "id": key.id,
                    "name": key.name,
                    "description": key.description,
                    "is_active": key.is_active,
                    "created_at": key.created_at.isoformat()
                    if key.created_at
                    else None,
                }
                for key in api_keys
            ],
            "usage_history": usage_history,  # TODO: Implement when usage table available
        }

        # Log admin action
        await log_admin_action(
            admin_user_id=admin_ctx.user_id,
            admin_email=admin_ctx.email,
            action="view_customer_detail",
            db=db,
            target_account_id=account_id,
            details={"account_name": account.name},
        )

        return {"ok": True, "data": customer_data}

    except HTTPException:
        raise
    except Exception as e:
        log.error(f"Failed to get customer detail for {account_id}: {e}", exc_info=True)
        raise HTTPException(500, f"Failed to get customer detail: {e}")


@router.post("/{account_id}/tier")
async def update_customer_tier(
    account_id: str,
    payload: AdminTierUpdatePayload = Body(...),
    admin_ctx: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """Manually override a customer's tier/entitlements from the admin UI."""

    try:
        account_exists = await db.scalar(
            select(Account.id).where(Account.id == account_id)
        )
        if not account_exists:
            raise HTTPException(404, f"Account {account_id} not found")

        monthly_rows, monthly_enrichments = _resolve_entitlements_from_limits(
            payload.tier, payload.monthly_match_limit, payload.monthly_enrichments
        )
        quota = await _apply_tier_update(
            account_id=account_id,
            tier=payload.tier,
            status=payload.status,
            monthly_rows=monthly_rows,
            monthly_enrichments=monthly_enrichments,
            source=payload.source or "admin_manual",
            addons=payload.addons,
            db=db,
        )

        await log_admin_action(
            admin_user_id=admin_ctx.user_id,
            admin_email=admin_ctx.email,
            action="admin_update_tier",
            db=db,
            target_account_id=account_id,
            details={
                "tier": payload.tier,
                "status": payload.status,
                "monthly_rows": monthly_rows,
                "monthly_enrichments": monthly_enrichments,
                "source": payload.source or "admin_manual",
            },
        )

        return {
            "ok": True,
            "tier": quota.tier,
            "status": quota.subscription_status,
            "monthly_rows_limit": quota.monthly_match_entitlement,
            "monthly_enrichment_credits": quota.monthly_enrichment_entitlement,
            "synced_at": quota.tier_synced_at.isoformat()
            if quota.tier_synced_at
            else None,
            "source": quota.tier_sync_source,
        }

    except HTTPException:
        raise
    except Exception as exc:
        log.error(
            "Failed to manually update tier for %s: %s", account_id, exc, exc_info=True
        )
        raise HTTPException(500, f"Failed to update tier: {exc}")


@router.post("/{account_id}/sync-from-clerk")
async def sync_customer_from_clerk(
    account_id: str,
    admin_ctx: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """Pull subscription data from Clerk and update the backend to match."""

    account_exists = await db.scalar(select(Account.id).where(Account.id == account_id))
    if not account_exists:
        raise HTTPException(404, f"Account {account_id} not found")

    clerk_secret = saas_settings.CLERK_SECRET_KEY
    if not clerk_secret:
        raise HTTPException(
            500,
            "CLERK_SECRET_KEY not configured. Cannot sync from Clerk.",
        )

    clerk_url = f"https://api.clerk.com/v1/users/{account_id}"

    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            resp = await client.get(
                clerk_url, headers={"Authorization": f"Bearer {clerk_secret}"}
            )
    except httpx.RequestError as exc:
        log.error("Failed to contact Clerk for %s: %s", account_id, exc, exc_info=True)
        raise HTTPException(502, f"Failed to reach Clerk: {exc}")

    if resp.status_code == 404:
        raise HTTPException(404, f"Clerk user {account_id} not found")
    if not resp.is_success:
        raise HTTPException(resp.status_code, f"Clerk error: {resp.text}")

    clerk_data = resp.json()
    subscription = clerk_data.get("public_metadata", {}).get("subscription", {}) or {}

    tier = subscription.get("tier") or "free"
    status = subscription.get("status") or "unknown"

    raw_match_limit = subscription.get("monthlyMatchLimit")
    raw_enrichment_limit = subscription.get("monthlyEnrichmentCredits")

    try:
        monthly_rows_override = (
            int(raw_match_limit) if raw_match_limit is not None else None
        )
    except (TypeError, ValueError):
        monthly_rows_override = None
    try:
        monthly_enrichments_override = (
            int(raw_enrichment_limit) if raw_enrichment_limit is not None else None
        )
    except (TypeError, ValueError):
        monthly_enrichments_override = None

    monthly_rows, monthly_enrichments = _resolve_entitlements_from_limits(
        tier, monthly_rows_override, monthly_enrichments_override
    )

    quota = await _apply_tier_update(
        account_id=account_id,
        tier=tier,
        status=status,
        monthly_rows=monthly_rows,
        monthly_enrichments=monthly_enrichments,
        source="clerk_manual_sync",
        addons=None,
        db=db,
    )

    await log_admin_action(
        admin_user_id=admin_ctx.user_id,
        admin_email=admin_ctx.email,
        action="sync_customer_from_clerk",
        db=db,
        target_account_id=account_id,
        details={
            "tier": tier,
            "status": status,
            "monthly_rows": monthly_rows,
            "monthly_enrichments": monthly_enrichments,
        },
    )

    return {
        "ok": True,
        "tier": quota.tier,
        "status": quota.subscription_status,
        "monthly_rows_limit": quota.monthly_match_entitlement,
        "monthly_enrichment_credits": quota.monthly_enrichment_entitlement,
        "synced_at": quota.tier_synced_at.isoformat() if quota.tier_synced_at else None,
        "source": quota.tier_sync_source,
        "clerk_subscription": subscription,
    }


@router.patch("/{account_id}/do-not-contact")
async def set_do_not_contact(
    account_id: str,
    payload: DoNotContactPayload,
    admin_ctx: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    account = await db.get(Account, account_id)
    if not account:
        raise HTTPException(status_code=404, detail="Account not found")

    account.do_not_contact = bool(payload.value)
    account.do_not_contact_since = datetime.utcnow() if account.do_not_contact else None
    db.add(account)
    await db.commit()
    await db.refresh(account)

    await log_admin_action(
        admin_user_id=admin_ctx.user_id,
        admin_email=admin_ctx.email,
        action="set_do_not_contact",
        db=db,
        target_account_id=account_id,
        details={"value": account.do_not_contact},
    )

    return {
        "ok": True,
        "data": {
            "account_id": account.id,
            "do_not_contact": account.do_not_contact,
            "do_not_contact_since": account.do_not_contact_since.isoformat()
            if account.do_not_contact_since
            else None,
        },
    }
