"""
Rutas para gestión de usuarios de Keycloak
"""

from typing import Optional
import os
import uuid
from pathlib import Path

from core.database import get_core_db
from core.security import get_current_user, validate_access_to_resource
from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile
from sqlalchemy.orm import Session

from ..user_tenant.models import UserTenant
from .dto import (
    ChangePasswordRequestDTO,
    CreateUserRequestDTO,
    UpdateUserRequestDTO,
    UserListResponseDTO,
    UserResponseDTO,
    UserStatsDTO,
)
from .service import UserService

router = APIRouter(prefix="/users", tags=["Users"])


@router.get("/stats", response_model=UserStatsDTO)
def get_user_statistics(
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Obtiene estadísticas de usuarios del tenant actual

    Muestra:
    - Total de usuarios
    - Usuarios activos e inactivos
    - Límite de licencia
    - Usuarios disponibles
    - Porcentaje de uso
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user)
    service = UserService(db, tenant_id, company_id)
    return service.get_user_stats()


@router.get("/", response_model=UserListResponseDTO)
def list_users(
    company_id: int = Query(..., description="Company ID"),
    page: int = Query(1, ge=1, description="Número de página"),
    page_size: int = Query(20, ge=1, le=100, description="Tamaño de página"),
    search: Optional[str] = Query(None, description="Término de búsqueda"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Lista todos los usuarios del tenant con paginación

    Se puede filtrar por término de búsqueda (busca en username, email, nombre)
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user)
    service = UserService(db, tenant_id, company_id)
    result = service.get_tenant_users(page=page, page_size=page_size, search=search)
    return result


@router.get("/{user_id}", response_model=UserResponseDTO)
def get_user(
    user_id: str,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Obtiene información detallada de un usuario específico

    El usuario debe pertenecer al tenant actual
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["user.view"])
    service = UserService(db, tenant_id, company_id)
    return service.get_user(user_id)


@router.post("/", response_model=UserResponseDTO, status_code=201)
def create_user(
    data: CreateUserRequestDTO,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Crea un nuevo usuario en Keycloak y lo asocia al tenant

    Validaciones:
    - Verifica que no se exceda el límite de usuarios de la licencia
    - Verifica que el email y username sean únicos
    - Crea el usuario con contraseña temporal

    Nota: El tenant_id se obtiene automáticamente del servicio (del token del usuario actual)
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["user.create"])
    service = UserService(db, tenant_id, company_id)
    user = service.create_user(
        email=data.email,
        username=data.username,
        first_name=data.first_name,
        last_name=data.last_name,
        password=data.password,
        role=data.role,
        enabled=data.enabled,
        email_verified=data.email_verified,
    )
    return user


@router.put("/{user_id}", response_model=UserResponseDTO)
def update_user(
    user_id: str,
    data: UpdateUserRequestDTO,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Actualiza información de un usuario

    Puede actualizar:
    - Datos personales (nombre, apellido, email)
    - Estado (habilitado/deshabilitado)
    - Verificación de email
    - Rol en el tenant
    - Perfil (avatar, teléfono, bio, preferencias)
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["user.update"])
    service = UserService(db, tenant_id, company_id)
    user = service.update_user(
        user_id=user_id,
        first_name=data.first_name,
        last_name=data.last_name,
        email=data.email,
        enabled=data.enabled,
        email_verified=data.email_verified,
        role=data.role,
        avatar_url=data.avatar_url,
        phone=data.phone,
        bio=data.bio,
        preferences=data.preferences,
    )
    return user


@router.delete("/{user_id}")
def delete_user(
    user_id: str,
    company_id: int = Query(..., description="Company ID"),
    soft_delete: bool = Query(
        True,
        description="Si es True, solo desactiva. Si es False, elimina permanentemente",
    ),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Elimina un usuario del tenant

    - soft_delete=True: Solo desactiva la relación (recomendado)
    - soft_delete=False: Elimina permanentemente de Keycloak
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["user.delete"])
    service = UserService(db, tenant_id, company_id)
    service.delete_user(user_id, soft_delete=soft_delete)
    return {"message": "User deleted successfully"}


@router.post("/{user_id}/change-password")
def change_user_password(
    user_id: str,
    data: ChangePasswordRequestDTO,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Cambia la contraseña de un usuario

    - temporary=True: Usuario debe cambiar la contraseña en el próximo login
    - temporary=False: Contraseña permanente
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user)
    service = UserService(db, tenant_id, company_id)
    service.change_password(user_id, data.password, data.temporary)
    return {"message": "Password changed successfully"}


# === Endpoints de Perfil del Usuario Actual ===


@router.get("/me/profile", response_model=UserResponseDTO)
def get_my_profile(
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_core_db),
):
    """
    Obtiene el perfil completo del usuario actual
    Incluye datos de Keycloak y datos de perfil (avatar, bio, etc.)
    """
    keycloak_user_id = current_user.get("sub")
    if not keycloak_user_id:
        raise HTTPException(status_code=400, detail="User ID not found in token")

    # Obtener user_tenant para crear servicio
    user_tenant = (
        db.query(UserTenant)
        .filter(
            UserTenant.keycloak_user_id == keycloak_user_id,
            UserTenant.is_active == True,
        )
        .first()
    )

    if not user_tenant:
        raise HTTPException(
            status_code=400, detail="User does not belong to any tenant"
        )

    service = UserService(db, user_tenant.tenant_id, user_tenant.company_id)
    return service.get_current_user_profile(keycloak_user_id)


@router.put("/me/profile", response_model=UserResponseDTO)
def update_my_profile(
    data: UpdateUserRequestDTO,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_core_db),
):
    """
    Actualiza el perfil del usuario actual

    Puede actualizar:
    - Datos de Keycloak: nombre, apellido, email
    - Datos de perfil: avatar, teléfono, biografía, preferencias
    """
    keycloak_user_id = current_user.get("sub")
    if not keycloak_user_id:
        raise HTTPException(status_code=400, detail="User ID not found in token")

    # Obtener user_tenant
    user_tenant = (
        db.query(UserTenant)
        .filter(
            UserTenant.keycloak_user_id == keycloak_user_id,
            UserTenant.is_active == True,
        )
        .first()
    )

    if not user_tenant:
        raise HTTPException(
            status_code=400, detail="User does not belong to any tenant"
        )

    service = UserService(db, user_tenant.tenant_id, user_tenant.company_id)
    return service.update_current_user_profile(
        keycloak_user_id=keycloak_user_id,
        first_name=data.first_name,
        last_name=data.last_name,
        email=data.email,
        avatar_url=data.avatar_url,
        phone=data.phone,
        bio=data.bio,
        preferences=data.preferences,
    )


@router.post("/me/avatar")
async def upload_avatar(
    file: UploadFile = File(...),
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_core_db),
):
    """
    Sube un avatar para el usuario actual
    Retorna la URL del avatar subido
    """
    # Validar tipo de archivo
    if not file.content_type or not file.content_type.startswith("image/"):
        raise HTTPException(status_code=400, detail="El archivo debe ser una imagen")

    # Validar tamaño (max 2MB)
    contents = await file.read()
    if len(contents) > 2 * 1024 * 1024:
        raise HTTPException(status_code=400, detail="La imagen debe ser menor a 2MB")

    # Crear directorio si no existe
    upload_dir = Path("/app/uploads/avatars")
    upload_dir.mkdir(parents=True, exist_ok=True)

    # Generar nombre con keycloak_user_id (sobrescribe si existe)
    keycloak_user_id = current_user.get("sub")
    ext = Path(file.filename or "image.jpg").suffix
    filename = f"{keycloak_user_id}{ext}"
    file_path = upload_dir / filename

    # Guardar archivo
    with open(file_path, "wb") as f:
        f.write(contents)

    # Retornar URL relativa
    avatar_url = f"/uploads/avatars/{filename}"

    return {"avatar_url": avatar_url}
