"""
Admin User Management Module
Full CRUD + role management for tenant admins and super admins.
Tenant admin: manages users within their organization
Super admin: manages all users across all organizations
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query, UploadFile, File
from typing import Optional, List, Dict, Any
from datetime import datetime
from pydantic import BaseModel, EmailStr
import uuid
import logging
import base64

from auth import get_current_user, get_current_org, get_password_hash, require_super_admin
from models import UserRole

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/admin", tags=["Admin User Management"])

db = None


def init_admin_user_management(database):
    global db
    db = database


class AdminUserCreate(BaseModel):
    email: EmailStr
    username: str
    password: str
    role: str = "viewer"
    phone: Optional[str] = None


class AdminUserUpdate(BaseModel):
    email: Optional[EmailStr] = None
    username: Optional[str] = None
    password: Optional[str] = None
    role: Optional[str] = None
    phone: Optional[str] = None
    is_active: Optional[bool] = None
    status: Optional[str] = None


class RoleChangeRequest(BaseModel):
    role: str


# ==================== Tenant Admin: User CRUD ====================

@router.get("/manage/users")
async def admin_list_users(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    search: Optional[str] = None,
    role: Optional[str] = None,
    is_active: Optional[bool] = None,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """List all users in the organization (admin only)"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    query: Dict[str, Any] = {"organization_id": org_id}

    if search:
        query["$or"] = [
            {"email": {"$regex": search, "$options": "i"}},
            {"username": {"$regex": search, "$options": "i"}},
        ]
    if role:
        query["role"] = role
    if is_active is not None:
        query["is_active"] = is_active

    total = await db.users.count_documents(query)
    users = await db.users.find(
        query, {"hashed_password": 0}
    ).sort("created_at", -1).skip(skip).limit(limit).to_list(limit)

    for user in users:
        user.pop("_id", None)

    return {"users": users, "total": total, "skip": skip, "limit": limit}


@router.get("/manage/users/{user_id}")
async def admin_get_user(
    user_id: str,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Get user details within organization"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    user = await db.users.find_one(
        {"id": user_id, "organization_id": org_id},
        {"hashed_password": 0}
    )
    if not user:
        raise HTTPException(status_code=404, detail="User not found in your organization")

    user.pop("_id", None)

    login_logs = await db.login_logs.find(
        {"user_id": user_id}
    ).sort("login_time", -1).limit(10).to_list(10)
    for log in login_logs:
        log.pop("_id", None)

    tickets = await db.support_tickets.find(
        {"user_id": user_id}
    ).sort("created_at", -1).limit(5).to_list(5)
    for t in tickets:
        t.pop("_id", None)

    devices_count = await db.devices.count_documents({"created_by": user_id})

    return {
        "user": user,
        "login_logs": login_logs,
        "tickets": tickets,
        "devices_created": devices_count,
    }


@router.post("/manage/users")
async def admin_create_user(
    user_data: AdminUserCreate,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Create a new user within the organization"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    existing = await db.users.find_one({"email": user_data.email})
    if existing:
        raise HTTPException(status_code=400, detail="Email already registered")

    allowed_roles = [UserRole.ENGINEER.value, UserRole.VIEWER.value]
    if user_data.role not in allowed_roles and current_user.get("role") != UserRole.SUPER_ADMIN.value:
        raise HTTPException(
            status_code=403,
            detail=f"Tenant admin can only create users with roles: {allowed_roles}"
        )

    org = await db.organizations.find_one({"id": org_id})
    if org:
        max_users = org.get("max_users", 50)
        current_count = await db.users.count_documents({"organization_id": org_id})
        if current_count >= max_users:
            raise HTTPException(status_code=400, detail=f"Organization user limit ({max_users}) reached")

    new_user = {
        "id": str(uuid.uuid4()),
        "email": user_data.email,
        "username": user_data.username,
        "hashed_password": get_password_hash(user_data.password),
        "role": user_data.role,
        "phone": user_data.phone,
        "organization_id": org_id,
        "is_active": True,
        "status": "approved",
        "created_at": datetime.utcnow(),
        "created_by": current_user["sub"],
    }

    await db.users.insert_one(new_user)
    new_user.pop("hashed_password", None)
    new_user.pop("_id", None)

    return {"message": "User created successfully", "user": new_user}


@router.put("/manage/users/{user_id}")
async def admin_update_user(
    user_id: str,
    updates: AdminUserUpdate,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Update a user within the organization"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    if user_id == current_user["sub"]:
        raise HTTPException(status_code=400, detail="Use profile settings to update your own account")

    user = await db.users.find_one({"id": user_id, "organization_id": org_id})
    if not user:
        raise HTTPException(status_code=404, detail="User not found in your organization")

    if user.get("role") == UserRole.ADMIN.value and current_user.get("role") != UserRole.SUPER_ADMIN.value:
        raise HTTPException(status_code=403, detail="Cannot modify another admin. Only super admin can do this.")

    update_data: Dict[str, Any] = {"updated_at": datetime.utcnow()}

    if updates.email is not None:
        dup = await db.users.find_one({"email": updates.email, "id": {"$ne": user_id}})
        if dup:
            raise HTTPException(status_code=400, detail="Email already in use")
        update_data["email"] = updates.email

    if updates.username is not None:
        update_data["username"] = updates.username

    if updates.password is not None:
        update_data["hashed_password"] = get_password_hash(updates.password)

    if updates.phone is not None:
        update_data["phone"] = updates.phone

    if updates.is_active is not None:
        update_data["is_active"] = updates.is_active

    if updates.status is not None:
        update_data["status"] = updates.status

    if updates.role is not None:
        allowed_roles = [UserRole.ENGINEER.value, UserRole.VIEWER.value]
        if updates.role not in allowed_roles and current_user.get("role") != UserRole.SUPER_ADMIN.value:
            raise HTTPException(
                status_code=403,
                detail=f"Tenant admin can only assign roles: {allowed_roles}"
            )
        update_data["role"] = updates.role

    await db.users.update_one({"id": user_id}, {"$set": update_data})

    updated_user = await db.users.find_one({"id": user_id}, {"hashed_password": 0})
    updated_user.pop("_id", None)

    return {"message": "User updated successfully", "user": updated_user}


@router.delete("/manage/users/{user_id}")
async def admin_delete_user(
    user_id: str,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Delete a user within the organization"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    if user_id == current_user["sub"]:
        raise HTTPException(status_code=400, detail="Cannot delete yourself")

    user = await db.users.find_one({"id": user_id, "organization_id": org_id})
    if not user:
        raise HTTPException(status_code=404, detail="User not found in your organization")

    if user.get("role") == UserRole.ADMIN.value and current_user.get("role") != UserRole.SUPER_ADMIN.value:
        raise HTTPException(status_code=403, detail="Cannot delete another admin. Only super admin can do this.")

    await db.users.delete_one({"id": user_id})
    await db.login_logs.delete_many({"user_id": user_id})
    await db.user_settings.delete_many({"user_id": user_id})

    return {"message": "User deleted successfully"}


# ==================== Role Change ====================

@router.patch("/manage/users/{user_id}/role")
async def admin_change_role(
    user_id: str,
    data: RoleChangeRequest,
    current_user: dict = Depends(get_current_user),
    org_id: str = Depends(get_current_org),
):
    """Change a user's role (tenant admin: engineer/viewer only, super admin: any)"""
    if current_user.get("role") not in [UserRole.ADMIN.value, UserRole.SUPER_ADMIN.value]:
        raise HTTPException(status_code=403, detail="Admin access required")

    if user_id == current_user["sub"]:
        raise HTTPException(status_code=400, detail="Cannot change your own role")

    valid_roles = [r.value for r in UserRole]
    if data.role not in valid_roles:
        raise HTTPException(status_code=400, detail=f"Invalid role. Must be one of: {valid_roles}")

    user = await db.users.find_one({"id": user_id, "organization_id": org_id})
    if not user:
        raise HTTPException(status_code=404, detail="User not found in your organization")

    if current_user.get("role") == UserRole.ADMIN.value:
        allowed = [UserRole.ENGINEER.value, UserRole.VIEWER.value]
        if data.role not in allowed:
            raise HTTPException(status_code=403, detail=f"Tenant admin can only assign roles: {allowed}")
        if user.get("role") == UserRole.ADMIN.value:
            raise HTTPException(status_code=403, detail="Cannot change role of another admin")

    await db.users.update_one(
        {"id": user_id},
        {"$set": {"role": data.role, "updated_at": datetime.utcnow()}}
    )

    updated = await db.users.find_one({"id": user_id}, {"hashed_password": 0})
    updated.pop("_id", None)

    return {"message": f"Role changed to {data.role}", "user": updated}


# ==================== Super Admin: Change Any Role (including tenant admins) ====================

@router.patch("/super/change-role/{user_id}")
async def super_admin_change_role(
    user_id: str,
    data: RoleChangeRequest,
    current_user: dict = Depends(require_super_admin),
):
    """Super admin can change role of any user including tenant admins"""
    valid_roles = [r.value for r in UserRole]
    if data.role not in valid_roles:
        raise HTTPException(status_code=400, detail=f"Invalid role. Must be one of: {valid_roles}")

    if user_id == current_user["sub"]:
        raise HTTPException(status_code=400, detail="Cannot change your own role")

    user = await db.users.find_one({"id": user_id})
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    if user.get("role") == UserRole.SUPER_ADMIN.value and data.role != UserRole.SUPER_ADMIN.value:
        raise HTTPException(status_code=400, detail="Cannot demote a super admin")

    await db.users.update_one(
        {"id": user_id},
        {"$set": {"role": data.role, "updated_at": datetime.utcnow()}}
    )

    updated = await db.users.find_one({"id": user_id}, {"hashed_password": 0})
    updated.pop("_id", None)

    return {"message": f"Role changed to {data.role}", "user": updated}
