# -*- coding: utf-8 -*-
# /var/www/html/utils_hibrido.py

import json
import re
import requests
import mysql.connector
from datetime import datetime

LOG_FILE_PATH = '/var/www/html/chat.log'

DB_CONFIG = {
    'host': 'localhost',
    'user': 'whatsapp_user',
    'password': '@dlkobs901',
    'database': 'whatsapp_atendimento_hibrido',
    'charset': 'utf8mb4'
}

def obter_conexao():
    """Retorna uma nova conexão ativa com a base de dados MySQL."""
    return mysql.connector.connect(**DB_CONFIG)

def registrar_log(origem, mensagem):
    """Grava as ações centralizadamente no arquivo chat.log e espelha no console."""
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    log_linha = f"[{timestamp}] [{origem.upper()}] {mensagem}"
    print(log_linha)
    try:
        with open(LOG_FILE_PATH, 'a', encoding='utf-8') as f:
            f.write(log_linha + "\n")
    except Exception as e:
        print(f"❌ Erro ao escrever log: {str(e)}")

def limpar_cpf_cnpj(texto):
    """Filtra o input do cliente mantendo apenas os caracteres numéricos."""
    if not texto:
        return ""
    return re.sub(r'\D', '', texto)

def obter_mensagem_db(cursor, chave, fallback=""):
    """Recupera dinamicamente as respostas configuradas na tabela robot_prompts_mensagens."""
    try:
        cursor.execute("SELECT conteudo FROM robot_prompts_mensagens WHERE chave = %s", (chave,))
        result = cursor.fetchone()
        if result and result['conteudo']:
            return result['conteudo']
    except Exception as e:
        registrar_log('SYSTEM_ERROR', f"Erro ao ler mensagem '{chave}': {str(e)}")
    return fallback

def buscar_config(cursor, chave):
    """Busca uma configuração específica no banco de dados."""
    cursor.execute("SELECT valor FROM config_sistema WHERE chave = %s", (chave,))
    res = cursor.fetchone()
    return res['valor'] if res else None

def enviar_whatsapp(configs, numero, texto):
    """Efetua o envio de mensagens de texto via API Cloud oficial do WhatsApp."""
    token = configs.get('WHATSAPP_TOKEN')
    phone_id = configs.get('PHONE_NUMBER_ID')
    
    if not token or not phone_id:
        registrar_log('SYSTEM_ERROR', "Falha ao enviar WhatsApp: WHATSAPP_TOKEN ou PHONE_NUMBER_ID ausentes.")
        return False
        
    url = f"https://graph.facebook.com/v25.0/{phone_id}/messages"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    payload = {
        "messaging_product": "whatsapp",
        "to": numero,
        "type": "text",
        "text": {"body": texto}
    }
    
    try:
        response = requests.post(url, json=payload, headers=headers, timeout=15)
        if response.status_code == 200:
            registrar_log('WHATSAPP_API', f"✔ Mensagem enviada com sucesso para {numero}.")
            return True
        else:
            registrar_log('WHATSAPP_API', f"❌ Erro de envio ({response.status_code}): {response.text[:200]}")
            return False
    except Exception as e:
        registrar_log('SYSTEM_ERROR', f"Exceção ao enviar mensagem: {str(e)}")
        return False

def consultar_deepseek(configs, mensagem_usuario, prompt_sistema):
    """Consulta a API do DeepSeek retornando estritamente um objeto JSON estruturado."""
    api_key = configs.get('DEEPSEEK_API_KEY')
    api_url = configs.get('DEEPSEEK_API_URL')
    
    if not api_key or not api_url:
        registrar_log('IA_CLASSIFIER', "Credenciais da API DeepSeek não encontradas.")
        return None
        
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    payload = {
        "model": "deepseek-chat",
        "messages": [
            {"role": "system", "content": prompt_sistema},
            {"role": "user", "content": mensagem_usuario}
        ],
        "temperature": 0.0,
        "response_format": {"type": "json_object"}
    }
    
    try:
        response = requests.post(api_url, json=payload, headers=headers, timeout=20)
        if response.status_code == 200:
            resultado = response.json()
            retorno_texto = resultado['choices'][0]['message']['content'].strip()
            registrar_log('IA_CLASSIFIER', f"Resposta da IA: {retorno_texto[:200]}")
            return json.loads(retorno_texto)
        else:
            registrar_log('IA_CLASSIFIER', f"Erro na requisição ({response.status_code}): {response.text[:200]}")
            return None
    except Exception as e:
        registrar_log('IA_CLASSIFIER', f"Exceção ao consultar DeepSeek: {str(e)}")
        return None


# ============================================================
# FUNÇÕES DA API RADIUSNET
# ============================================================

def chamar_api_radiusnet(cursor, endpoint, params=None, metodo='GET'):
    """
    Chama a API RadiusNet usando as configurações do banco.
    
    Args:
        cursor: cursor do banco de dados
        endpoint: string do endpoint (ex: '/cp/{cpf}/2')
        params: dict com parâmetros para substituir na URL
        metodo: 'GET', 'POST' ou 'PUT'
    
    Returns:
        dict: {'success': bool, 'data': dict ou list, 'error': str}
    """
    base_url = buscar_config(cursor, 'RADIUSNET_API_URL')
    api_key = buscar_config(cursor, 'RADIUSNET_API_KEY')
    
    if not base_url or not api_key:
        registrar_log('RADIUSNET', "Credenciais não encontradas no config_sistema")
        return {"success": False, "error": "Credenciais não configuradas"}
    
    # Monta URL substituindo placeholders
    url = base_url.rstrip('/') + endpoint
    if params:
        for key, value in params.items():
            placeholder = "{" + key + "}"
            if placeholder in url:
                url = url.replace(placeholder, str(value))
    
    headers = {
        "RTOKEN": api_key,
        "Content-Type": "application/json"
    }
    
    registrar_log('RADIUSNET', f"Chamando API: {metodo} {url}")
    
    try:
        if metodo == 'GET':
            resp = requests.get(url, headers=headers, timeout=15)
        elif metodo == 'POST':
            # Para POST, envia os parâmetros que não foram usados na URL
            body = {k: v for k, v in params.items() if f"{{{k}}}" not in endpoint} if params else {}
            resp = requests.post(url, json=body, headers=headers, timeout=15)
        elif metodo == 'PUT':
            body = {k: v for k, v in params.items() if f"{{{k}}}" not in endpoint} if params else {}
            resp = requests.put(url, json=body, headers=headers, timeout=15)
        else:
            return {"success": False, "error": f"Método {metodo} não suportado"}
        
        registrar_log('RADIUSNET', f"Resposta HTTP: {resp.status_code}")
        
        if resp.status_code == 200:
            return {"success": True, "data": resp.json()}
        else:
            registrar_log('RADIUSNET', f"Erro HTTP {resp.status_code}: {resp.text[:500]}")
            return {"success": False, "error": f"HTTP {resp.status_code}", "details": resp.text}
    except Exception as e:
        registrar_log('RADIUSNET', f"Exceção: {str(e)}")
        return {"success": False, "error": str(e)}


def consultar_cliente_por_cpf(cursor, cpf):
    """
    Busca cliente por CPF.
    Endpoint: GET /cp/{cpf}/2
    Retorna lista de cadastros (extrai do campo 'rows' da resposta)
    """
    endpoint = "/cp/{cpf}/2"
    params = {"cpf": cpf}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        data = resultado['data']
        # A API retorna {"rows": [...], "count": N}
        if isinstance(data, dict) and 'rows' in data:
            registrar_log('RADIUSNET', f"Encontrados {data.get('count', 0)} cadastros para CPF {cpf}")
            return data['rows']
        elif isinstance(data, list):
            registrar_log('RADIUSNET', f"Encontrados {len(data)} cadastros para CPF {cpf}")
            return data
        else:
            registrar_log('RADIUSNET', f"Estrutura de resposta inesperada: {type(data)}")
            return []
    else:
        registrar_log('RADIUSNET', f"Erro na consulta: {resultado.get('error')}")
        return []


def consultar_cliente_por_id(cursor, id_cliente):
    """
    Busca dados completos do cliente por ID.
    Endpoint: GET /cpcd/cli/{id_cliente}
    Retorna: dados do cliente incluindo emails e telefones
    """
    endpoint = "/cpcd/cli/{id_cliente}"
    params = {"id_cliente": id_cliente}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        data = resultado['data']
        # A API pode retornar diretamente os dados ou dentro de 'rows'
        if isinstance(data, dict) and 'rows' in data:
            return data['rows']
        return data
    return None


def cobrancas_cliente_atraso(cursor, id_cliente):
    """
    Busca cobranças em atraso do cliente.
    Endpoint: GET /cbc/at/{id_cliente}
    """
    endpoint = "/cbc/at/{id_cliente}"
    params = {"id_cliente": id_cliente}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        return resultado['data']
    return []


def cobrancas_cliente_nao_pagas(cursor, id_cliente):
    """
    Busca cobranças não pagas do cliente (inclui vencidas e a vencer).
    Endpoint: GET /cbc/np/{id_cliente}
    """
    endpoint = "/cbc/np/{id_cliente}"
    params = {"id_cliente": id_cliente}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        return resultado['data']
    return []


def cobrancas_plano_atraso(cursor, id_cliente_plano):
    """
    Busca cobranças em atraso de um plano específico.
    Endpoint: GET /cbp/at/{id_cliente_plano}
    """
    endpoint = "/cbp/at/{id_cliente_plano}"
    params = {"id_cliente_plano": id_cliente_plano}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        return resultado['data']
    return []


def cobrancas_plano_nao_pagas(cursor, id_cliente_plano):
    """
    Busca cobranças não pagas de um plano específico.
    Endpoint: GET /cbp/np/{id_cliente_plano}
    """
    endpoint = "/cbp/np/{id_cliente_plano}"
    params = {"id_cliente_plano": id_cliente_plano}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        return resultado['data']
    return []


def gerar_boleto(cursor, id_cobranca):
    """
    Gera URL do boleto PDF.
    Endpoint: GET /bc/{id_cobranca}
    Retorna: {'url': 'https://...'}
    """
    endpoint = "/bc/{id_cobranca}"
    params = {"id_cobranca": id_cobranca}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        return resultado['data']
    return None


def desbloquear_confianca(cursor, id_cobranca):
    """
    Solicita desbloqueio em confiança.
    Endpoint: PUT /ppg/{id_cobranca}
    """
    endpoint = "/ppg/{id_cobranca}"
    params = {"id_cobranca": id_cobranca}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='PUT')
    
    if resultado.get('success'):
        return resultado['data']
    return None


def atualizar_email(cursor, id_cliente, email):
    """
    Adiciona novo e-mail ao cadastro.
    Endpoint: POST /adicemail/
    Body: {"IDCLI": id_cliente, "EMAIL": email}
    """
    endpoint = "/adicemail/"
    params = {"IDCLI": id_cliente, "EMAIL": email}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='POST')
    return resultado.get('success', False)


def atualizar_telefone(cursor, id_cliente, ddd, telefone, tipo=2):
    """
    Adiciona novo telefone ao cadastro.
    Endpoint: POST /ct/
    Body: {"IDCLI": id_cliente, "DDD": ddd, "TEL": telefone, "TT": tipo}
    Tipos: 1-Residencial, 2-Celular, 3-Comercial
    """
    endpoint = "/ct/"
    params = {"IDCLI": id_cliente, "DDD": ddd, "TEL": telefone, "TT": tipo}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='POST')
    return resultado.get('success', False)


def verificar_status_online(cursor, login):
    """
    Verifica se o cliente está online (conectado).
    Endpoint: GET /cpl/{login}
    """
    endpoint = "/cpl/{login}"
    params = {"login": login}
    resultado = chamar_api_radiusnet(cursor, endpoint, params, metodo='GET')
    
    if resultado.get('success'):
        return resultado['data']
    return None
