"""
Superadmin routes: user management, stats, permissions, app settings — v4.2.0
"""

from pydantic import BaseModel
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func

from backend.database import get_db
from backend.models import User, Chat, Message, KnowledgeBase, UserPermissions, AppSettings
from backend.auth import (
    require_superadmin, hash_password, get_user_permissions,
    ensure_user_permissions, get_default_permissions_template,
)
from backend.config import PERMISSION_FIELDS, DEFAULT_PERMISSIONS, SUPERADMIN_PERMISSIONS, AVAILABLE_MODELS

router = APIRouter()


class UpdateUserBody(BaseModel):
    email: Optional[str] = None
    role: Optional[str] = None
    is_active: Optional[bool] = None
    quota_tokens_monthly: Optional[int] = None
    password: Optional[str] = None


class CreateUserBody(BaseModel):
    username: str
    email: str
    password: str
    role: str = "user"
    quota_tokens_monthly: int = 2_000_000


class PermissionsBody(BaseModel):
    can_use_web_search: Optional[bool] = None
    can_use_ui_design: Optional[bool] = None
    can_use_knowledge_base: Optional[bool] = None
    can_use_gitlab: Optional[bool] = None
    can_use_attachments: Optional[bool] = None
    can_export_pptx: Optional[bool] = None
    can_export_docx: Optional[bool] = None
    allowed_models: Optional[str] = None
    max_tokens_cap: Optional[int] = None
    max_reasoning_budget: Optional[int] = None
    max_chats: Optional[int] = None
    max_messages_per_day: Optional[int] = None
    max_knowledge_bases: Optional[int] = None
    max_documents_per_kb: Optional[int] = None
    max_attachment_size_mb: Optional[int] = None
    max_attachments_per_message: Optional[int] = None


class AppSettingsBody(BaseModel):
    registration_enabled: Optional[bool] = None


# ═══════════════════════════════════════════════════
#  Stats & Users
# ═══════════════════════════════════════════════════

@router.get("/stats")
def get_stats(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    return {
        "total_users": db.query(User).count(),
        "active_users": db.query(User).filter(User.is_active == True).count(),
        "total_chats": db.query(Chat).count(),
        "total_messages": db.query(Message).count(),
        "total_tokens_used": db.query(func.sum(User.tokens_used_this_month)).scalar() or 0,
        "total_knowledge_bases": db.query(KnowledgeBase).count(),
    }


@router.get("/users")
def list_users(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    users = db.query(User).order_by(User.created_at.desc()).all()
    result = []
    for u in users:
        chat_count = db.query(Chat).filter(Chat.user_id == u.id).count()
        result.append({
            "id": u.id,
            "username": u.username,
            "email": u.email,
            "role": u.role,
            "is_active": u.is_active,
            "quota_tokens_monthly": u.quota_tokens_monthly,
            "tokens_used_this_month": u.tokens_used_this_month,
            "chat_count": chat_count,
            "created_at": str(u.created_at),
        })
    return result


@router.post("/users")
def create_user(body: CreateUserBody, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    if db.query(User).filter(
        (User.username == body.username) | (User.email == body.email)
    ).first():
        raise HTTPException(409, "Username or email taken")
    user = User(
        username=body.username,
        email=body.email,
        password_hash=hash_password(body.password),
        role=body.role,
        quota_tokens_monthly=body.quota_tokens_monthly,
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    ensure_user_permissions(user.id, db)
    return {"id": user.id, "username": user.username}


@router.put("/users/{user_id}")
def update_user(user_id: str, body: UpdateUserBody, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(404)
    if body.email is not None:
        user.email = body.email
    if body.role is not None:
        user.role = body.role
    if body.is_active is not None:
        user.is_active = body.is_active
    if body.quota_tokens_monthly is not None:
        user.quota_tokens_monthly = body.quota_tokens_monthly
    if body.password:
        user.password_hash = hash_password(body.password)
    db.commit()
    return {"ok": True}


@router.delete("/users/{user_id}")
def delete_user(user_id: str, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(404)
    if user.role == "superadmin":
        raise HTTPException(400, "Cannot delete superadmin")
    db.delete(user)
    db.commit()
    return {"ok": True}


@router.get("/chats")
def list_all_chats(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    chats = db.query(Chat).order_by(Chat.updated_at.desc()).limit(200).all()
    result = []
    for c in chats:
        user = db.query(User).filter(User.id == c.user_id).first()
        msg_count = db.query(Message).filter(Message.chat_id == c.id).count()
        result.append({
            "id": c.id,
            "title": c.title,
            "username": user.username if user else "?",
            "message_count": msg_count,
            "updated_at": str(c.updated_at),
        })
    return result


# ═══════════════════════════════════════════════════
#  APP SETTINGS (registration toggle, etc.)
# ═══════════════════════════════════════════════════

@router.get("/app-settings")
def get_app_settings(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    settings = db.query(AppSettings).first()
    if not settings:
        return {"registration_enabled": True}
    return {
        "registration_enabled": settings.registration_enabled,
        "updated_at": str(settings.updated_at) if settings.updated_at else None,
    }


@router.put("/app-settings")
def update_app_settings(body: AppSettingsBody, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    settings = db.query(AppSettings).first()
    if not settings:
        settings = AppSettings()
        db.add(settings)
    if body.registration_enabled is not None:
        settings.registration_enabled = body.registration_enabled
    db.commit()
    db.refresh(settings)
    return {
        "registration_enabled": settings.registration_enabled,
        "updated_at": str(settings.updated_at) if settings.updated_at else None,
    }


# ═══════════════════════════════════════════════════
#  PERMISSIONS MANAGEMENT
# ═══════════════════════════════════════════════════

@router.get("/models")
def list_available_models(admin: User = Depends(require_superadmin)):
    return AVAILABLE_MODELS


@router.get("/permissions/defaults")
def get_defaults(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    return get_default_permissions_template(db)


@router.put("/permissions/defaults")
def update_defaults(body: PermissionsBody, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    template = db.query(UserPermissions).filter(UserPermissions.user_id == "__defaults__").first()
    if not template:
        template = UserPermissions(user_id="__defaults__")
        db.add(template)
    _apply_permissions_body(template, body)
    db.commit()
    return get_default_permissions_template(db)


@router.post("/permissions/apply-defaults")
def apply_defaults_to_all(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    """Apply default permissions template to ALL non-superadmin users."""
    template = get_default_permissions_template(db)
    users = db.query(User).filter(User.role != "superadmin").all()
    count = 0
    for user in users:
        perms = db.query(UserPermissions).filter(UserPermissions.user_id == user.id).first()
        if not perms:
            perms = UserPermissions(user_id=user.id)
            db.add(perms)
        for field in PERMISSION_FIELDS:
            if hasattr(perms, field):
                setattr(perms, field, template.get(field))
        count += 1
    db.commit()
    return {"ok": True, "users_updated": count}


@router.get("/users/{user_id}/permissions")
def get_user_perms(user_id: str, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(404, "User not found")
    return get_user_permissions(user_id, db)


@router.put("/users/{user_id}/permissions")
def update_user_perms(user_id: str, body: PermissionsBody, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(404, "User not found")
    if user.role == "superadmin":
        raise HTTPException(400, "Cannot modify superadmin permissions — they always have full access")
    ensure_user_permissions(user_id, db)
    perms = db.query(UserPermissions).filter(UserPermissions.user_id == user_id).first()
    _apply_permissions_body(perms, body)
    db.commit()
    return get_user_permissions(user_id, db)


def _apply_permissions_body(perms: UserPermissions, body: PermissionsBody):
    """Apply non-None fields from the body to a permissions object."""
    data = body.dict(exclude_none=True)
    for field, value in data.items():
        if hasattr(perms, field):
            setattr(perms, field, value)