"""
Super Admin Module - Platform-wide administration
Provides full CRUD access to all users, organizations, devices, and data
across the entire platform regardless of organization boundaries.
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query
from typing import Optional, List, Dict, Any
from datetime import datetime
from pydantic import BaseModel, EmailStr
import uuid
import logging

from auth import require_super_admin, get_password_hash
from models import UserRole

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/super", tags=["Super Admin"])


class SuperAdminUserCreate(BaseModel):
    email: EmailStr
    username: str
    password: str
    role: UserRole = UserRole.VIEWER
    organization_id: Optional[str] = None


class SuperAdminUserUpdate(BaseModel):
    email: Optional[EmailStr] = None
    username: Optional[str] = None
    password: Optional[str] = None
    role: Optional[UserRole] = None
    is_active: Optional[bool] = None
    organization_id: Optional[str] = None
    status: Optional[str] = None


class SuperAdminOrgUpdate(BaseModel):
    name: Optional[str] = None
    plan: Optional[str] = None
    is_active: Optional[bool] = None
    max_users: Optional[int] = None
    max_devices: Optional[int] = None
    domain: Optional[str] = None


db = None


def init_super_admin(database):
    """Initialize module with database reference"""
    global db
    db = database


# ==================== Dashboard ====================

@router.get("/dashboard")
async def super_admin_dashboard(current_user: dict = Depends(require_super_admin)):
    """Get platform-wide dashboard stats"""
    total_users = await db.users.count_documents({})
    active_users = await db.users.count_documents({"is_active": True})
    total_orgs = await db.organizations.count_documents({})
    total_devices = await db.devices.count_documents({})
    online_devices = await db.devices.count_documents({"status": "online"})
    total_scans = await db.scans.count_documents({})
    open_tickets = await db.support_tickets.count_documents({"status": "open"})
    total_alerts = await db.alerts.count_documents({})

    recent_users = await db.users.find(
        {}, {"hashed_password": 0}
    ).sort("created_at", -1).limit(10).to_list(10)

    recent_logins = await db.login_logs.find().sort("login_time", -1).limit(10).to_list(10)

    orgs_with_stats = []
    async for org in db.organizations.find().limit(10):
        org_id = org["id"]
        org_users = await db.users.count_documents({"organization_id": org_id})
        org_devices = await db.devices.count_documents({"organization_id": org_id})
        orgs_with_stats.append({
            "id": org_id,
            "name": org.get("name", "Unknown"),
            "plan": org.get("plan", "free"),
            "users_count": org_users,
            "devices_count": org_devices,
            "is_active": org.get("is_active", True),
        })

    return {
        "stats": {
            "total_users": total_users,
            "active_users": active_users,
            "total_organizations": total_orgs,
            "total_devices": total_devices,
            "online_devices": online_devices,
            "offline_devices": total_devices - online_devices,
            "total_scans": total_scans,
            "open_tickets": open_tickets,
            "total_alerts": total_alerts,
        },
        "recent_users": recent_users,
        "recent_logins": recent_logins,
        "organizations": orgs_with_stats,
        "generated_at": datetime.utcnow().isoformat(),
    }


# ==================== User Management ====================

@router.get("/users")
async def list_all_users(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    search: Optional[str] = None,
    role: Optional[str] = None,
    org_id: Optional[str] = None,
    is_active: Optional[bool] = None,
    current_user: dict = Depends(require_super_admin),
):
    """List all users across all organizations with filtering"""
    query: Dict[str, Any] = {}

    if search:
        query["$or"] = [
            {"email": {"$regex": search, "$options": "i"}},
            {"username": {"$regex": search, "$options": "i"}},
        ]
    if role:
        query["role"] = role
    if org_id:
        query["organization_id"] = org_id
    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)
        org = await db.organizations.find_one({"id": user.get("organization_id")})
        user["organization_name"] = org.get("name") if org else None

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


@router.get("/users/{user_id}")
async def get_user_detail(
    user_id: str,
    current_user: dict = Depends(require_super_admin),
):
    """Get detailed info about any user including all associated data"""
    user = await db.users.find_one({"id": user_id}, {"hashed_password": 0})
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    user.pop("_id", None)

    org = await db.organizations.find_one({"id": user.get("organization_id")})
    user["organization"] = org

    devices_count = await db.devices.count_documents({"created_by": user_id})
    scans_count = await db.scans.count_documents({"created_by": user_id})
    login_logs = await db.login_logs.find(
        {"user_id": user_id}
    ).sort("login_time", -1).limit(20).to_list(20)
    tickets = await db.support_tickets.find(
        {"user_id": user_id}
    ).sort("created_at", -1).limit(10).to_list(10)
    settings = await db.user_settings.find_one({"user_id": user_id})

    return {
        "user": user,
        "activity": {
            "devices_created": devices_count,
            "scans_performed": scans_count,
            "recent_logins": login_logs,
            "support_tickets": tickets,
        },
        "settings": settings,
    }


@router.post("/users")
async def create_user(
    user_data: SuperAdminUserCreate,
    current_user: dict = Depends(require_super_admin),
):
    """Create a new user in any organization"""
    existing = await db.users.find_one({"email": user_data.email})
    if existing:
        raise HTTPException(status_code=400, detail="Email already registered")

    if user_data.organization_id:
        org = await db.organizations.find_one({"id": user_data.organization_id})
        if not org:
            raise HTTPException(status_code=404, detail="Organization not found")

    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.value,
        "organization_id": user_data.organization_id,
        "is_active": True,
        "status": "approved",
        "created_at": datetime.utcnow(),
        "created_by_super_admin": 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("/users/{user_id}")
async def update_user(
    user_id: str,
    updates: SuperAdminUserUpdate,
    current_user: dict = Depends(require_super_admin),
):
    """Update any user's information (role, email, status, org, etc.)"""
    user = await db.users.find_one({"id": user_id})
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    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.role is not None:
        update_data["role"] = updates.role.value

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

    if updates.organization_id is not None:
        if updates.organization_id:
            org = await db.organizations.find_one({"id": updates.organization_id})
            if not org:
                raise HTTPException(status_code=404, detail="Organization not found")
        update_data["organization_id"] = updates.organization_id

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

    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("/users/{user_id}")
async def delete_user(
    user_id: str,
    purge_data: bool = Query(False, description="Also delete all user-associated data"),
    current_user: dict = Depends(require_super_admin),
):
    """Delete a user. Optionally purge all their associated data."""
    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:
        raise HTTPException(status_code=400, detail="Cannot delete a super admin account")

    deleted_data = {"user": True}

    if purge_data:
        await db.devices.delete_many({"created_by": user_id})
        await db.scans.delete_many({"created_by": user_id})
        await db.login_logs.delete_many({"user_id": user_id})
        await db.support_tickets.delete_many({"user_id": user_id})
        await db.user_settings.delete_many({"user_id": user_id})
        await db.chat_history.delete_many({"user_id": user_id})
        deleted_data["devices"] = True
        deleted_data["scans"] = True
        deleted_data["login_logs"] = True
        deleted_data["support_tickets"] = True
        deleted_data["user_settings"] = True
        deleted_data["chat_history"] = True

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

    return {"message": "User deleted successfully", "purged_data": deleted_data}


@router.get("/users/{user_id}/data")
async def get_user_all_data(
    user_id: str,
    current_user: dict = Depends(require_super_admin),
):
    """Get ALL data associated with a specific user across all collections"""
    user = await db.users.find_one({"id": user_id}, {"hashed_password": 0})
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    user.pop("_id", None)

    devices = await db.devices.find({"created_by": user_id}).to_list(500)
    scans = await db.scans.find({"created_by": user_id}).sort("started_at", -1).to_list(100)
    login_logs = await db.login_logs.find({"user_id": user_id}).sort("login_time", -1).to_list(200)
    tickets = await db.support_tickets.find({"user_id": user_id}).to_list(100)
    settings = await db.user_settings.find_one({"user_id": user_id})
    chat_history = await db.chat_history.find({"user_id": user_id}).sort("created_at", -1).to_list(100)

    for collection in [devices, scans, login_logs, tickets, chat_history]:
        for doc in collection:
            doc.pop("_id", None)
    if settings:
        settings.pop("_id", None)

    return {
        "user": user,
        "devices": devices,
        "scans": scans,
        "login_logs": login_logs,
        "support_tickets": tickets,
        "settings": settings,
        "chat_history": chat_history,
    }


# ==================== Organization Management ====================

@router.get("/organizations")
async def list_all_organizations(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    search: Optional[str] = None,
    plan: Optional[str] = None,
    current_user: dict = Depends(require_super_admin),
):
    """List all organizations with user/device counts"""
    query: Dict[str, Any] = {}

    if search:
        query["name"] = {"$regex": search, "$options": "i"}
    if plan:
        query["plan"] = plan

    total = await db.organizations.count_documents(query)
    orgs = await db.organizations.find(query).sort("created_at", -1).skip(skip).limit(limit).to_list(limit)

    result = []
    for org in orgs:
        org.pop("_id", None)
        org_id = org["id"]
        org["users_count"] = await db.users.count_documents({"organization_id": org_id})
        org["devices_count"] = await db.devices.count_documents({"organization_id": org_id})
        owner = await db.users.find_one(
            {"id": org.get("owner_id")}, {"hashed_password": 0, "_id": 0}
        )
        org["owner"] = owner
        result.append(org)

    return {
        "organizations": result,
        "total": total,
        "skip": skip,
        "limit": limit,
    }


@router.get("/organizations/{org_id}")
async def get_organization_detail(
    org_id: str,
    current_user: dict = Depends(require_super_admin),
):
    """Get full organization details including members, devices, usage"""
    org = await db.organizations.find_one({"id": org_id})
    if not org:
        raise HTTPException(status_code=404, detail="Organization not found")

    org.pop("_id", None)

    members = await db.users.find(
        {"organization_id": org_id}, {"hashed_password": 0}
    ).to_list(500)
    for m in members:
        m.pop("_id", None)

    devices = await db.devices.find({"organization_id": org_id}).to_list(500)
    for d in devices:
        d.pop("_id", None)

    subscription = await db.subscriptions.find_one({"organization_id": org_id})
    if subscription:
        subscription.pop("_id", None)

    return {
        "organization": org,
        "members": members,
        "devices": devices,
        "subscription": subscription,
        "stats": {
            "total_members": len(members),
            "total_devices": len(devices),
            "active_members": sum(1 for m in members if m.get("is_active")),
            "online_devices": sum(1 for d in devices if d.get("status") == "online"),
        },
    }


@router.put("/organizations/{org_id}")
async def update_organization(
    org_id: str,
    updates: SuperAdminOrgUpdate,
    current_user: dict = Depends(require_super_admin),
):
    """Update any organization's settings, plan, limits"""
    org = await db.organizations.find_one({"id": org_id})
    if not org:
        raise HTTPException(status_code=404, detail="Organization not found")

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

    if updates.name is not None:
        update_data["name"] = updates.name
    if updates.plan is not None:
        update_data["plan"] = updates.plan
    if updates.is_active is not None:
        update_data["is_active"] = updates.is_active
    if updates.max_users is not None:
        update_data["max_users"] = updates.max_users
    if updates.max_devices is not None:
        update_data["max_devices"] = updates.max_devices
    if updates.domain is not None:
        update_data["domain"] = updates.domain

    await db.organizations.update_one({"id": org_id}, {"$set": update_data})

    updated_org = await db.organizations.find_one({"id": org_id})
    updated_org.pop("_id", None)

    return {"message": "Organization updated successfully", "organization": updated_org}


@router.delete("/organizations/{org_id}")
async def delete_organization(
    org_id: str,
    current_user: dict = Depends(require_super_admin),
):
    """Delete an organization and optionally reassign or remove its users"""
    org = await db.organizations.find_one({"id": org_id})
    if not org:
        raise HTTPException(status_code=404, detail="Organization not found")

    await db.users.update_many(
        {"organization_id": org_id},
        {"$set": {"organization_id": None, "is_active": False, "status": "org_deleted"}}
    )
    await db.devices.delete_many({"organization_id": org_id})
    await db.scans.delete_many({"organization_id": org_id})
    await db.alerts.delete_many({"organization_id": org_id})
    await db.support_tickets.delete_many({"organization_id": org_id})
    await db.subscriptions.delete_many({"organization_id": org_id})
    await db.organizations.delete_one({"id": org_id})

    return {"message": f"Organization '{org.get('name')}' and all its data deleted"}


# ==================== Device Management ====================

@router.get("/devices")
async def list_all_devices(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    search: Optional[str] = None,
    org_id: Optional[str] = None,
    device_status: Optional[str] = None,
    current_user: dict = Depends(require_super_admin),
):
    """List all devices across all organizations"""
    query: Dict[str, Any] = {}

    if search:
        query["$or"] = [
            {"hostname": {"$regex": search, "$options": "i"}},
            {"ip": {"$regex": search, "$options": "i"}},
            {"vendor": {"$regex": search, "$options": "i"}},
        ]
    if org_id:
        query["organization_id"] = org_id
    if device_status:
        query["status"] = device_status

    total = await db.devices.count_documents(query)
    devices = await db.devices.find(query).sort("last_seen", -1).skip(skip).limit(limit).to_list(limit)

    for device in devices:
        device.pop("_id", None)
        org = await db.organizations.find_one({"id": device.get("organization_id")})
        device["organization_name"] = org.get("name") if org else None

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


@router.delete("/devices/{device_id}")
async def delete_device(
    device_id: str,
    current_user: dict = Depends(require_super_admin),
):
    """Delete any device from the platform"""
    device = await db.devices.find_one({"id": device_id})
    if not device:
        raise HTTPException(status_code=404, detail="Device not found")

    await db.devices.delete_one({"id": device_id})
    await db.device_metrics.delete_many({"device_id": device_id})
    await db.alerts.delete_many({"device_id": device_id})
    await db.backups.delete_many({"device_id": device_id})

    return {"message": "Device and associated data deleted"}


# ==================== Logs & Audit ====================

@router.get("/logs/logins")
async def get_all_login_logs(
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=500),
    user_id: Optional[str] = None,
    success: Optional[bool] = None,
    current_user: dict = Depends(require_super_admin),
):
    """Get login logs across all organizations"""
    query: Dict[str, Any] = {}
    if user_id:
        query["user_id"] = user_id
    if success is not None:
        query["success"] = success

    total = await db.login_logs.count_documents(query)
    logs = await db.login_logs.find(query).sort("login_time", -1).skip(skip).limit(limit).to_list(limit)

    for log in logs:
        log.pop("_id", None)

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


@router.get("/logs/audit")
async def get_audit_trail(
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=500),
    current_user: dict = Depends(require_super_admin),
):
    """Get audit trail of admin actions"""
    logs = await db.audit_logs.find().sort("timestamp", -1).skip(skip).limit(limit).to_list(limit)

    for log in logs:
        log.pop("_id", None)

    total = await db.audit_logs.count_documents({})
    return {"audit_logs": logs, "total": total, "skip": skip, "limit": limit}


# ==================== Support Tickets ====================

@router.get("/tickets")
async def list_all_tickets(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    ticket_status: Optional[str] = None,
    priority: Optional[str] = None,
    current_user: dict = Depends(require_super_admin),
):
    """List all support tickets across organizations"""
    query: Dict[str, Any] = {}
    if ticket_status:
        query["status"] = ticket_status
    if priority:
        query["priority"] = priority

    total = await db.support_tickets.count_documents(query)
    tickets = await db.support_tickets.find(query).sort("created_at", -1).skip(skip).limit(limit).to_list(limit)

    for ticket in tickets:
        ticket.pop("_id", None)

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


# ==================== Alerts ====================

@router.get("/alerts")
async def list_all_alerts(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    severity: Optional[str] = None,
    current_user: dict = Depends(require_super_admin),
):
    """List all alerts across all organizations"""
    query: Dict[str, Any] = {}
    if severity:
        query["severity"] = severity

    total = await db.alerts.count_documents(query)
    alerts = await db.alerts.find(query).sort("created_at", -1).skip(skip).limit(limit).to_list(limit)

    for alert in alerts:
        alert.pop("_id", None)

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


# ==================== Bulk Operations ====================

@router.post("/users/bulk-deactivate")
async def bulk_deactivate_users(
    user_ids: List[str],
    current_user: dict = Depends(require_super_admin),
):
    """Deactivate multiple users at once"""
    result = await db.users.update_many(
        {"id": {"$in": user_ids}, "role": {"$ne": UserRole.SUPER_ADMIN.value}},
        {"$set": {"is_active": False, "updated_at": datetime.utcnow()}}
    )
    return {"message": f"{result.modified_count} users deactivated"}


@router.post("/users/bulk-delete")
async def bulk_delete_users(
    user_ids: List[str],
    current_user: dict = Depends(require_super_admin),
):
    """Delete multiple users at once (excluding super admins)"""
    result = await db.users.delete_many(
        {"id": {"$in": user_ids}, "role": {"$ne": UserRole.SUPER_ADMIN.value}}
    )
    return {"message": f"{result.deleted_count} users deleted"}


# ==================== Platform Settings ====================

@router.get("/settings")
async def get_platform_settings(
    current_user: dict = Depends(require_super_admin),
):
    """Get global platform settings"""
    settings = await db.platform_settings.find_one({"key": "global"})
    if not settings:
        settings = {
            "key": "global",
            "allow_registration": True,
            "require_approval": False,
            "default_plan": "free",
            "maintenance_mode": False,
            "max_orgs": 100,
        }
    settings.pop("_id", None)
    return settings


@router.put("/settings")
async def update_platform_settings(
    settings: Dict[str, Any],
    current_user: dict = Depends(require_super_admin),
):
    """Update global platform settings"""
    settings["updated_at"] = datetime.utcnow().isoformat()
    settings["updated_by"] = current_user["sub"]

    await db.platform_settings.update_one(
        {"key": "global"},
        {"$set": settings},
        upsert=True,
    )

    return {"message": "Platform settings updated", "settings": settings}
