# app/modules/tenancy/routes/api/admin_platform_users.py
"""
User management endpoints for admin.

All endpoints use the admin_service for business logic.
Domain exceptions are raised by the service and converted to HTTP responses
by the global exception handler.
"""

import logging

from fastapi import APIRouter, Body, Depends, Path, Query, Request
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.modules.core.services.stats_aggregator import stats_aggregator
from app.modules.tenancy.schemas.auth import (
    OwnedMerchantSummary,
    StoreMembershipSummary,
    UserContext,
    UserCreate,
    UserDeleteResponse,
    UserDetailResponse,
    UserListResponse,
    UserResponse,
    UserSearchResponse,
    UserStatusToggleResponse,
    UserUpdate,
)
from app.modules.tenancy.services.admin_service import admin_service

admin_platform_users_router = APIRouter(prefix="/users")
logger = logging.getLogger(__name__)


@admin_platform_users_router.get("", response_model=UserListResponse)
def get_all_users(
    page: int = Query(1, ge=1),
    per_page: int = Query(10, ge=1, le=100),
    search: str = Query("", description="Search by username or email"),
    role: str = Query("", description="Filter by role"),
    scope: str = Query("", description="Filter scope: 'merchant' for merchant owners and team members"),
    is_active: str = Query("", description="Filter by active status"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get paginated list of all users (Admin only)."""
    # Convert string params to proper types
    is_active_bool = None
    if is_active:
        is_active_bool = is_active.lower() == "true"

    users, total, pages = admin_service.list_users(
        db=db,
        page=page,
        per_page=per_page,
        search=search if search else None,
        role=role if role else None,
        scope=scope if scope else None,
        is_active=is_active_bool,
    )

    if scope == "merchant":
        items = [
            UserDetailResponse(
                id=user.id,
                email=user.email,
                username=user.username,
                role=user.role,
                is_active=user.is_active,
                last_login=user.last_login,
                created_at=user.created_at,
                updated_at=user.updated_at,
                first_name=user.first_name,
                last_name=user.last_name,
                full_name=user.full_name,
                is_email_verified=user.is_email_verified,
                owned_merchants_count=len(user.owned_merchants) if user.owned_merchants else 0,
                store_memberships_count=len(user.store_memberships) if user.store_memberships else 0,
                owned_merchants=[
                    OwnedMerchantSummary(
                        id=m.id,
                        name=m.name,
                        is_active=m.is_active,
                        store_count=len(m.stores) if m.stores else 0,
                    )
                    for m in (user.owned_merchants or [])
                ],
                store_memberships=[
                    StoreMembershipSummary(
                        store_id=su.store_id,
                        store_code=su.store.store_code,
                        store_name=su.store.name,
                        role=su.user.role,
                        is_active=su.is_active,
                    )
                    for su in (user.store_memberships or [])
                ],
            )
            for user in users
        ]
    else:
        items = [UserResponse.model_validate(user) for user in users]

    return UserListResponse(
        items=items,
        total=total,
        page=page,
        per_page=per_page,
        pages=pages,
    )


@admin_platform_users_router.post("", response_model=UserDetailResponse)
def create_user(
    user_data: UserCreate = Body(...),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Create a new user (Admin only)."""
    user = admin_service.create_user(
        db=db,
        email=user_data.email,
        username=user_data.username,
        password=user_data.password,
        first_name=user_data.first_name,
        last_name=user_data.last_name,
        role=user_data.role,
        current_admin_id=current_admin.id,
    )
    db.commit()

    return UserDetailResponse(
        id=user.id,
        email=user.email,
        username=user.username,
        role=user.role,
        is_active=user.is_active,
        last_login=user.last_login,
        created_at=user.created_at,
        updated_at=user.updated_at,
        first_name=user.first_name,
        last_name=user.last_name,
        full_name=user.full_name,
        is_email_verified=user.is_email_verified,
        owned_merchants_count=len(user.owned_merchants) if user.owned_merchants else 0,
        store_memberships_count=len(user.store_memberships)
        if user.store_memberships
        else 0,
    )


def _get_platform_id(request: Request, current_admin: UserContext) -> int:
    """Get platform_id from available sources."""
    # From JWT token
    if current_admin.token_platform_id:
        return current_admin.token_platform_id
    # From request state
    platform = getattr(request.state, "platform", None)
    if platform:
        return platform.id
    # First accessible platform
    if current_admin.accessible_platform_ids:
        return current_admin.accessible_platform_ids[0]
    # Fallback
    return 1


@admin_platform_users_router.get("/stats")
def get_user_statistics(
    request: Request,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get user statistics for admin dashboard (Admin only).

    Uses the stats_aggregator to get user metrics from the tenancy module's
    MetricsProvider, ensuring no cross-module import violations.
    """
    platform_id = _get_platform_id(request, current_admin)

    # Get metrics from stats_aggregator (tenancy module provides user stats)
    metrics = stats_aggregator.get_admin_dashboard_stats(db=db, platform_id=platform_id)

    # Extract user stats from tenancy metrics
    tenancy_metrics = metrics.get("tenancy", [])

    # Build response from metric values
    stats = {
        "total_users": 0,
        "active_users": 0,
        "inactive_users": 0,
        "admin_users": 0,
    }

    for metric in tenancy_metrics:
        if metric.key == "tenancy.total_users":
            stats["total_users"] = int(metric.value)
        elif metric.key == "tenancy.active_users":
            stats["active_users"] = int(metric.value)
        elif metric.key == "tenancy.inactive_users":
            stats["inactive_users"] = int(metric.value)
        elif metric.key == "tenancy.admin_users":
            stats["admin_users"] = int(metric.value)

    return stats


@admin_platform_users_router.get("/merchant-stats")
def get_merchant_user_statistics(
    request: Request,
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get merchant user statistics for admin dashboard.

    Uses the stats_aggregator to get merchant user metrics from the tenancy
    module's MetricsProvider.
    """
    platform_id = _get_platform_id(request, current_admin)

    metrics = stats_aggregator.get_admin_dashboard_stats(db=db, platform_id=platform_id)
    tenancy_metrics = metrics.get("tenancy", [])

    stats = {
        "merchant_users_total": 0,
        "merchant_users_active": 0,
        "merchant_owners": 0,
        "merchant_team_members": 0,
    }

    for metric in tenancy_metrics:
        if metric.key == "tenancy.merchant_users_total":
            stats["merchant_users_total"] = int(metric.value)
        elif metric.key == "tenancy.merchant_users_active":
            stats["merchant_users_active"] = int(metric.value)
        elif metric.key == "tenancy.merchant_owners":
            stats["merchant_owners"] = int(metric.value)
        elif metric.key == "tenancy.merchant_team_members":
            stats["merchant_team_members"] = int(metric.value)

    return stats


@admin_platform_users_router.get("/search", response_model=UserSearchResponse)
def search_users(
    q: str = Query(..., min_length=2, description="Search query (username or email)"),
    limit: int = Query(10, ge=1, le=50),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """
    Search users by username or email (Admin only).

    Used for autocomplete in ownership transfer.
    """
    users = admin_service.search_users(db=db, query=q, limit=limit)
    return UserSearchResponse(users=users)


@admin_platform_users_router.get("/{user_id}", response_model=UserDetailResponse)
def get_user_details(
    user_id: int = Path(..., description="User ID"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Get detailed user information (Admin only)."""
    user = admin_service.get_user_details(db=db, user_id=user_id)

    return UserDetailResponse(
        id=user.id,
        email=user.email,
        username=user.username,
        role=user.role,
        is_active=user.is_active,
        last_login=user.last_login,
        created_at=user.created_at,
        updated_at=user.updated_at,
        first_name=user.first_name,
        last_name=user.last_name,
        full_name=user.full_name,
        is_email_verified=user.is_email_verified,
        owned_merchants_count=len(user.owned_merchants) if user.owned_merchants else 0,
        store_memberships_count=len(user.store_memberships)
        if user.store_memberships
        else 0,
        owned_merchants=[
            OwnedMerchantSummary(
                id=m.id,
                name=m.name,
                is_active=m.is_active,
                store_count=len(m.stores) if m.stores else 0,
            )
            for m in (user.owned_merchants or [])
        ],
        store_memberships=[
            StoreMembershipSummary(
                store_id=su.store_id,
                store_code=su.store.store_code,
                store_name=su.store.name,
                role=su.user.role,
                is_active=su.is_active,
            )
            for su in (user.store_memberships or [])
        ],
    )


@admin_platform_users_router.put("/{user_id}", response_model=UserDetailResponse)
def update_user(
    user_id: int = Path(..., description="User ID"),
    user_update: UserUpdate = Body(...),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Update user information (Admin only)."""
    update_data = user_update.model_dump(exclude_unset=True)

    user = admin_service.update_user(
        db=db,
        user_id=user_id,
        current_admin_id=current_admin.id,
        email=update_data.get("email"),
        username=update_data.get("username"),
        first_name=update_data.get("first_name"),
        last_name=update_data.get("last_name"),
        role=update_data.get("role"),
        is_active=update_data.get("is_active"),
    )
    db.commit()

    return UserDetailResponse(
        id=user.id,
        email=user.email,
        username=user.username,
        role=user.role,
        is_active=user.is_active,
        last_login=user.last_login,
        created_at=user.created_at,
        updated_at=user.updated_at,
        first_name=user.first_name,
        last_name=user.last_name,
        full_name=user.full_name,
        is_email_verified=user.is_email_verified,
        owned_merchants_count=len(user.owned_merchants) if user.owned_merchants else 0,
        store_memberships_count=len(user.store_memberships)
        if user.store_memberships
        else 0,
    )


@admin_platform_users_router.put("/{user_id}/status", response_model=UserStatusToggleResponse)
def toggle_user_status(
    user_id: int = Path(..., description="User ID"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Toggle user active status (Admin only)."""
    user, message = admin_service.toggle_user_status(
        db=db,
        user_id=user_id,
        current_admin_id=current_admin.id,
    )
    db.commit()

    return UserStatusToggleResponse(message=message, is_active=user.is_active)


@admin_platform_users_router.delete("/{user_id}", response_model=UserDeleteResponse)
def delete_user(
    user_id: int = Path(..., description="User ID"),
    db: Session = Depends(get_db),
    current_admin: UserContext = Depends(get_current_admin_api),
):
    """Delete a user (Admin only)."""
    message = admin_service.delete_user(
        db=db,
        user_id=user_id,
        current_admin_id=current_admin.id,
    )
    db.commit()

    return UserDeleteResponse(message=message)
