from typing import Optional
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import APIRouter, Depends, HTTPException, Query, Body, status

from src.core.database import get_db
from src.core.auth import require_enterprise_or_front
from src.services.computadores import ComputadorService
from src.schemas.computadores import (
    ComputerCreate, ComputerUpdate, ComputerResponse,)
from src.core.api_responses import (
    build_success_payload, to_schema_dict, SuccessResponse, ErrorResponse)

router = APIRouter(
    prefix="/computadores",
    tags=["Computadores"],
)

computador_service = ComputadorService()


def _get_constraint_error_message(error: IntegrityError) -> str:
    error_parts: list[str] = []
    if hasattr(error, "orig"):
        try:
            orig_args = getattr(error.orig, "args", None)
            if orig_args:
                error_parts.extend([str(a) for a in orig_args])
        except Exception:
            pass
        try:
            error_parts.append(str(error.orig))
        except Exception:
            pass
    try:
        error_parts.append(str(error))
    except Exception:
        pass

    error_str_lower = " ".join(error_parts).lower()

    if ("nomeusuario" in error_str_lower or
            "nome_usuario" in error_str_lower or
            "uq_computadores_nomeusuario_empresa" in error_str_lower):
        return (
            "Já existe um computador cadastrado com este nome de usuário "
            "nesta empresa.")
    elif ("nomehost" in error_str_lower or
            "nome_host" in error_str_lower or
            "uq_computadores_nomehost_empresa" in error_str_lower):
        return "Já existe um computador com este nome de host."
    elif "numeroserie" in error_str_lower or "numero_serie" in error_str_lower:
        return "Já existe um computador cadastrado com este número de série."
    else:
        return "Conflito ao criar/atualizar computador."


@router.get(
    "/buscar",
    summary="Listar computadores",
    description=(
        "Retorna computadores, com opção de filtrar por empresa.\n\n"
        "Parâmetros:\n"
        "- empresa_id (query, opcional): filtra pelos computadores.\n\n"
        "Exemplo cURL (sem filtro):\n\n"
            "```bash\n"
        "curl -X GET 'https://exemplo/computadores/buscar'"" \\\n"
        "-H 'Authorization: Bearer <TOKEN>'\n"
        "```\n\n"
        "Com filtro empresa_id:\n\n"
        "```bash\n"
        "curl -X GET 'https://exemplo/computadores/buscar?empresa_id=id' \\\n"
        "  -H 'Authorization: Bearer <TOKEN>'\n"
        "```\n\n"
        "Usando X-Enterprise-Token:\n\n"
        "```bash\n"
        "curl -X GET 'https://exemplo/computadores/buscar?empresa_id=id' \\\n"
        "  -H 'X-Enterprise-Token: <TOKEN_EMPRESA>'\n"
        "```"
    ),
    response_model=SuccessResponse,
    responses={
        200:
            {
                "description": "Lista de computadores"
            },
        401:
            {
                "description": "Credenciais inválidas ou ausentes",
                "model": ErrorResponse
            },
        500:
            {
                "description": "Erro interno",
                "model": ErrorResponse
            },
    },
    openapi_extra={
        "responses": {
            "200": {
                "content": {
                    "application/json": {
                        "examples": {
                            "message": "2 computadores encontrados",
                            "data": [
                                {
                                    "id": "1a2bbf80-9a6e-4527-9b7c",
                                    "empresa_id": "id",
                                    "nome_host": "SRV-01"
                                },
                                {
                                    "id": "2b3c4d5e-6f7a-8b9c-0d1e",
                                    "empresa_id": "id",
                                    "nome_host": "SRV-02"
                                }
                            ],
                            "timestamp": "2025-01-01T12:00:00Z"
                        }
                    }
                }
            },
            "500":
                {
                    "content":
                        {
                            "application/json":
                                {
                                    "examples":
                                        {
                                            "error":
                                                {
                                                    "code": "INTERNA_ERROR",
                                                    "message": "Erro"
                                                },
                                            "timestamp": "2025-01-01T12:00:00Z"
                                            }
                                        }
                                }
                        }
        }
    }
)
async def listar_computadores(
    empresa_id: Optional[str] = Query(
        None,
        description="Filtrar por ID da empresa",
        examples="id",
    ),
    db: AsyncSession = Depends(get_db),
    _auth=Depends(require_enterprise_or_front),
):
    items = await computador_service.listar(db, empresa_id=empresa_id)
    data = [to_schema_dict(ComputerResponse, x) for x in items]
    qtd = len(data)
    if empresa_id:
        sufixo = f" da empresa {empresa_id}"
    else:
        sufixo = ""
    if qtd == 0:
        message = f"Nenhum computador encontrado{sufixo}"
    elif qtd == 1:
        message = f"1 computador encontrado{sufixo}"
    else:
        message = f"{qtd} computadores encontrados{sufixo}"
    return build_success_payload(data=data, message=message)

@router.get(
    "/heartbeat/{computador_id}",
    summary="Listar computadores online",
    description=(
        "Retorna a lista de computadores ativos nos últimos 5 minutos.\n\n"
        "Requer token válido."),
    response_model=SuccessResponse,
    responses={
        200: {
            "description": "status do computador"},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse},
        500: {
            "description": "Erro interno",
            "model": ErrorResponse},
    })
async def get_heartbeat_computer(
    computador_id: str,
    db: AsyncSession = Depends(get_db),
        _auth=Depends(require_enterprise_or_front),
):
    computador = await computador_service.verificar_heartbeat(
        db,
        computador_id
    )
    status_str = "online" if computador else "offline"
    return build_success_payload(message=f"Status: {status_str}")


@router.get(
    "/computadores-online",
    summary="Listar computadores online",
    description=(
        "Retorna a lista de computadores ativos nos últimos 5 minutos.\n\n"
        "Requer token válido."),
    response_model=SuccessResponse,
    responses={
        200: {
            "description": "Lista de computadores online"},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse},
        500: {
            "description": "Erro interno",
            "model": ErrorResponse},
    })
async def get_computadores_online(
    db: AsyncSession = Depends(get_db),
        _auth=Depends(require_enterprise_or_front),
):
    computadoresOnline = await computador_service.listar_computadores_online(
        db
    )
    return build_success_payload(data=computadoresOnline)
