#brew install tesseract
#https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe
#ffmpeg -f avfoundation -list_devices true -i
#pip3 uninstall socketio
#pip3 uninstall python-socketio
#pip3 install "python-socketio[client]"
#pip3 install engineio
# pip3 install engineio==4.5.0 pygetwindow pyautogui  python-socketio==5.9.0 pillow requests websocket-client
# python3 -m pip install engineio==4.5.0 pyautogui  python-socketio==5.9.0 pygetwindow python-socketio pillow requests websocket-client
# winget install ffmpeg
# Verificar :   python3 -c "import pyautogui, socketio, PIL, requests, websocket; print('✅ Todas as dependências estão instaladas')"
# Testar se a porta 3000 está acessível
# curl -v https://173.249.31.98:3000
# cd /iot
# 1. Se não existir, instalar
# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
# python get-pip.py

# 2. Instalar as dependências do projeto
# Instalar python via homebrew // se nao tiver instalado
# brew install python3
# O pip será instalado automaticamente

# se nao tiver instalado :   /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# ls -la /opt/homebrew/bin/brew

# echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc eval "$(/opt/homebrew/bin/brew shellenv)"

# brew install ffmpeg // instalar no make
# winget install ffmpeg  // instalar no windows

# python maquina.py 1..2..3. quantas forem
# instalar os arquivos acima 3 atraz ai burro
# testar porta  :  curl -v https://173.249.31.98:3000  /  https://www.xkbitcoin.com/iot/  https://www.xkbitcoin.com:3000

# Testar se o caminho /iot/ está funcionando
# curl -v https://www.xkbitcoin.com/iot/

# Testar se o domínio com porta 3000 está funcionando
# curl -v https://www.xkbitcoin.com:3000


# pip3 install pygetwindow pyautogui python-socketio pillow requests websocket-client
# python3 -m pip install pyautogui pygetwindow python-socketio pillow requests websocket-client
# winget install ffmpeg
# Verificar :   python3 -c "import pyautogui, socketio, PIL, requests, websocket; print('✅ Todas as dependências estão instaladas')"
# Testar se a porta 3000 está acessível
# curl -v https://173.249.31.98:3000
# cd /iot
# 1. Se não existir, instalar
# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
# python get-pip.py

# 2. Instalar as dependências do projeto
# Instalar python via homebrew // se nao tiver instalado
# brew install python3
# O pip será instalado automaticamente

# se nao tiver instalado :   /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# ls -la /opt/homebrew/bin/brew

# echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc eval "$(/opt/homebrew/bin/brew shellenv)"

# brew install ffmpeg // instalar no make
# winget install ffmpeg  // instalar no windows

# python maquina.py 1..2..3. quantas forem
# instalar os arquivos acima 3 atraz ai burro
# testar porta  :  curl -v https://173.249.31.98:3000  /  https://www.xkbitcoin.com/iot/  https://www.xkbitcoin.com:3000

# Testar se o caminho /iot/ está funcionando
# curl -v https://www.xkbitcoin.com/iot/

# Testar se o domínio com porta 3000 está funcionando
# curl -v https://www.xkbitcoin.com:3000

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Cliente de Máquina para Sala VIP - H.264
Mantém todas as funções: créditos, cliques, JS, teclado, serial
Suporte: Windows, Mac, Linux
"""

import sys
import time
import threading
import base64
import platform
import requests
import os
import socketio
import signal
import serial
from io import BytesIO
from PIL import ImageGrab

# ==========================================
# SINALIZADOR DE ENCERRAMENTO
# ==========================================
encerrando = False

def handler(signum, frame):
    global encerrando
    print('\n👋 Encerrando...')
    encerrando = True
    if sio.connected:
        sio.disconnect()
    sys.exit(0)

signal.signal(signal.SIGINT, handler)

# ==========================================
# CONFIGURAÇÕES
# ==========================================
if len(sys.argv) < 2:
    print('❌ Use: python3 maquina.py <MAQUINA_ID>')
    sys.exit(1)

MAQUINA_ID = sys.argv[1]
SERVER_URL = 'https://xkbitcoin.com'
FPS = 5
QUALIDADE_JPEG = 25
SISTEMA = platform.system()

PORTA_SERIAL = 'COM3' if SISTEMA == 'Windows' else '/dev/ttyUSB0'
BAUDRATE = 115200

MAPA_TECLAS = {
    "btn_ajuda": "tab",
    "btn_cobrar": "c",
    "btn_numeros": "n",
    "btn_aposta": "p",
    "btn_auto": "i",
    "btn_cartelas": "k",
    "btn_extra": "e",
    "btn_jogar": "h",
    "btn_ver_cartoes": "b",
    "btn_turbo": "t",
    "btn_velocidade_menos": "-", 
    "btn_velocidade_mais": "+",  
    "inserir_notas5": "n",
    "inserir_notas10": "n",
    "inserir_notas20": "n",
    "inserir_notas50": "n",
    "inserir_notas100": "n",
    "inserir_notas200": "n"
}

conexao_serial = None

# ==========================================
# IMPORTAÇÕES CONDICIONAIS
# ==========================================
try:
    import pyautogui
    pyautogui.FAILSAFE = False
except ImportError:
    print('❌ pyautogui não instalado.')
    sys.exit(1)

try:
    import serial
    SERIAL_DISPONIVEL = True
except ImportError:
    SERIAL_DISPONIVEL = False

try:
    import keyboard
    TECLADO_DISPONIVEL = True
except ImportError:
    TECLADO_DISPONIVEL = False

# ==========================================
# INICIALIZAÇÃO SERIAL
# ==========================================
if SERIAL_DISPONIVEL:
    try:
        conexao_serial = serial.Serial(PORTA_SERIAL, BAUDRATE, timeout=1)
    except:
        pass

def enviar_para_esp32(comando):
    if conexao_serial and conexao_serial.is_open:
        try:
            conexao_serial.write(f"{comando}\n".encode())
        except:
            pass

def obter_token(maquina_id):
    try:
        response = requests.get(f'{SERVER_URL}:3000/api/maquina/token/{maquina_id}', timeout=10)
        if response.status_code == 200:
            return response.json().get('token')
        return None
    except:
        return None

TOKEN = obter_token(MAQUINA_ID)
if not TOKEN:
    print('❌ Token inválido. Abortando.')
    sys.exit(1)

# ==========================================
# SOCKET.IO
# ==========================================
sio = socketio.Client(
    logger=False,
    engineio_logger=False,
    reconnection=True,
    reconnection_attempts=10,
    reconnection_delay=2,
    reconnection_delay_max=30,
    transports=['polling']
)

# ==========================================
# STREAMING JPEG
# ==========================================
def capturar_jpeg():
    print("📸 Stream JPEG iniciado...")
    intervalo = 1.0 / FPS
    
    while not encerrando:
        if not sio.connected:
            time.sleep(1)
            continue
            
        inicio = time.time()
        
        try:
            img = ImageGrab.grab()
            if img.mode != 'RGB':
                img = img.convert('RGB')
            img = img.resize((854, 480))
            buffer = BytesIO()
            img.save(buffer, format="JPEG", quality=QUALIDADE_JPEG)
            img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
            
            sio.emit('tela_maquina', {
                'maquina_id': MAQUINA_ID,
                'imagem': img_base64
            })
        except Exception as e:
            print(f'⚠️ Erro: {e}')
            time.sleep(1)
            continue
            
        tempo_gasto = time.time() - inicio
        time.sleep(max(0.01, intervalo - tempo_gasto))

# ==========================================
# MANTER CONEXÃO VIVA
# ==========================================
def manter_conexao_viva():
    while not encerrando:
        time.sleep(15)
        if sio.connected:
            sio.emit('ping')
        else:
            try:
                print('🔄 Tentando reconectar...')
                sio.connect(f'{SERVER_URL}:3000', auth={'token': TOKEN})
                sio.emit('entrar_na_maquina', MAQUINA_ID)
            except:
                pass

# ==========================================
# EVENTOS SOCKET.IO
# ==========================================
@sio.event
def connect():
    sio.emit('entrar_na_maquina', MAQUINA_ID)

@sio.event
def disconnect():
    print('🔴 Desconectado')

@sio.on('executar_clique')
def executar_clique(data):
    try:
        largura, altura = pyautogui.size()
        x_real = int(data['x'] * largura)
        y_real = int(data['y'] * altura)
        pyautogui.click(x_real, y_real)
    except:
        pass

@sio.on('executar_js')
def executar_js(data):
    try:
        funcao = data.get('funcao')
        args = data.get('args', [])

        if funcao == 'ClickBtn' and len(args) >= 2:
            comando_recebido = args[1]
            enviar_para_esp32(comando_recebido)
            tecla_alvo = MAPA_TECLAS.get(comando_recebido)
            if tecla_alvo:
                trazer_navegador_para_frente()
                pyautogui.press(tecla_alvo)
                return

        args_formatados = ", ".join([f"'{a}'" if isinstance(a, str) else str(a) for a in args])
        comando_js = f"javascript:{funcao}({args_formatados});"
        trazer_navegador_para_frente()
        if SISTEMA == 'Darwin':
            pyautogui.hotkey('command', 'l')
        else:
            pyautogui.hotkey('ctrl', 'l')
        time.sleep(0.15)
        pyautogui.write(comando_js)
        pyautogui.press('enter')
    except:
        pass

@sio.on('inserirCredito')
def inserir_credito(data):
    try:
        valor = data['args'][1]
        creditos = valor * 4
        enviar_para_esp32(f"credito_{creditos}")
        trazer_navegador_para_frente()
        pyautogui.press('n')
    except:
        pass

# ==========================================
# CAPTURA DE TECLAS LOCAIS
# ==========================================
def capturar_teclas():
    if not TECLADO_DISPONIVEL:
        return
    
    def ao_pressionar(e):
        if e.event_type == 'down':
            tecla = e.name.lower()
            if tecla in MAPA_TECLAS and sio.connected:
                comando = MAPA_TECLAS[tecla]
                sio.emit('executar_js', {'funcao': 'ClickBtn', 'args': [MAQUINA_ID, comando]})
                enviar_para_esp32(comando)
    
    keyboard.hook(ao_pressionar)
    keyboard.wait()

# ==========================================
# FUNÇÕES DE NAVEGADOR
# ==========================================
def trazer_navegador_para_frente():
    try:
        if SISTEMA == 'Darwin':
            os.system('osascript -e "tell application \\"Google Chrome\\" to activate"')
        elif SISTEMA == 'Windows':
            os.system('start chrome')
        else:
            os.system('wmctrl -a Google Chrome')
    except:
        pass

# ==========================================
# INÍCIO DO PROGRAMA
# ==========================================
if __name__ == '__main__':
    try:
        sio.connect(f'{SERVER_URL}:3000', auth={'token': TOKEN})
        
        threads = [
            threading.Thread(target=capturar_jpeg, daemon=True),
            threading.Thread(target=manter_conexao_viva, daemon=True),
            threading.Thread(target=capturar_teclas, daemon=True)
        ]
        
        for t in threads:
            t.start()
        
        print('✅ Sistema rodando! Pressione Ctrl+C para encerrar.')
        
        while not encerrando:
            time.sleep(1)
            
    except KeyboardInterrupt:
        print('\n👋 Ctrl+C detectado!')
    except Exception as e:
        print(f'❌ Erro: {e}')
    finally:
        encerrando = True
        if sio.connected:
            sio.disconnect()
        if conexao_serial and conexao_serial.is_open:
            conexao_serial.close()
        print('✅ Programa encerrado com sucesso.')
        sys.exit(0)