import os
import logging

from pathlib import Path
from typing import Optional
from dotenv import load_dotenv
from fastapi import Depends, HTTPException, Request, Header, status
from sqlalchemy.ext.asyncio import AsyncSession

from core.database import get_sqlserver_db
from services.auth import AuthService
from models.alerta_cliente import Cliente

env_path = Path(__file__).parent.parent / '.env'
load_dotenv(dotenv_path=env_path)

logger = logging.getLogger(__name__)

def _extract_bearer_token(authorization_header: Optional[str]) -> Optional[str]:
    if not authorization_header:
        return None
    parts = authorization_header.split()
    if len(parts) == 2 and parts[0].lower() == "bearer":
        return parts[1].strip()
    return None

async def require_fix_token(
    request: Request,
) -> None:
    """
    Valida o token fixo da API.
    - Authorization: Bearer <FIX_API_TOKEN>
    """
    logger.info(f"Validando autenticação - Path: {request.url.path}")
    
    fix_api_token = os.getenv("FIX_API_TOKEN", "").strip()
    if fix_api_token:
        logger.debug(f"Token configurado no ambiente: Sim (tamanho: {len(fix_api_token)} caracteres)")
    else:
        logger.error("❌ Token de API NÃO configurado no ambiente (FIX_API_TOKEN está vazio ou não existe)")
        logger.error("   Configure a variável FIX_API_TOKEN no arquivo .env")

    auth_header = request.headers.get("authorization") or request.headers.get("Authorization")
    if auth_header:
        logger.debug(f"Header Authorization presente: Sim")
        # Não logar o token completo por segurança, apenas indicar que existe
        logger.debug(f"Header Authorization contém: {auth_header[:20]}...")
    else:
        logger.warning(f"Header Authorization ausente na requisição")
    
    bearer = _extract_bearer_token(auth_header) or ""

    if not fix_api_token:
        logger.error("ERRO: Token de API não configurado. Configure FIX_API_TOKEN no arquivo .env")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Token de API não configurado. Verifique a configuração do servidor."
        )

    if not bearer:
        logger.warning(f"Token Bearer não fornecido na requisição - Path: {request.url.path}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Credenciais inválidas ou ausentes. Forneça o header: Authorization: Bearer <token>"
        )
    
    if bearer != fix_api_token:
        logger.warning(f"Token inválido fornecido - Path: {request.url.path}")
        logger.debug(f"Token recebido não corresponde ao token configurado")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Credenciais inválidas ou ausentes"
        )
    
    logger.info("✅ Token validado com sucesso")

async def get_current_user(
    Authorization: Optional[str] = Header(None),
    db: AsyncSession = Depends(get_sqlserver_db),
) -> Cliente:
    """
    Dependência para obter o cliente autenticado baseado no token do cliente.
    Usa o token retornado no login (token do cliente da tabela dbo.Cliente).
    
    Args:
        Authorization: Header Authorization com Bearer token
        db: Sessão do banco de dados SQL Server
        
    Returns:
        Cliente autenticado
        
    Raises:
        HTTPException: Se token não fornecido ou inválido
    """
    if Authorization is None:
        logger.warning("Token não enviado")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token não enviado"
        )

    # Extrai o token do header
    try:
        token = Authorization.replace("Bearer ", "").strip()
    except Exception as e:
        logger.warning(f"Erro ao extrair token: {e}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Formato de token inválido"
        )
    
    try:
        cliente = await AuthService.get_current_cliente(db=db, token=token)
        return cliente
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Erro ao validar token: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Erro interno ao validar token"
        )