#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
from io import BytesIO

# Importações de Visão e Imagem
from PIL import ImageGrab
import cv2
import numpy as np
import pytesseract

# ==========================================
# CONFIGURAÇÕES INICIAIS
# ==========================================
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 = 15
INTERVALO = 1.0 / FPS
SISTEMA = platform.system()

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

# Se estiver no Windows e o Tesseract não estiver no PATH, descomente e ajuste:
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

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

try:
    import socketio
except ImportError:
    print('❌ python-socketio não instalado.')
    sys.exit(1)

# ==========================================
# INICIALIZAÇÃO E COMUNICAÇÃO
# ==========================================
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)

sio = socketio.Client(logger=False, engineio_logger=False, reconnection=True)

# ==========================================
# EXTRAÇÃO OCR (SALDO E CRÉDITO)
# ==========================================
def extrair_dados_bingo(pil_img):
    try:
        img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
        img = cv2.resize(img, (1024, 768))

        roi_saldo = img[20:55, 875:1000]
        roi_credito = img[235:280, 810:865]

        gray_saldo = cv2.cvtColor(roi_saldo, cv2.COLOR_BGR2GRAY)
        gray_credito = cv2.cvtColor(roi_credito, cv2.COLOR_BGR2GRAY)

        _, thresh_saldo = cv2.threshold(gray_saldo, 100, 255, cv2.THRESH_BINARY_INV)
        _, thresh_credito = cv2.threshold(gray_credito, 130, 255, cv2.THRESH_BINARY)

        config_numeros = r'--psm 6 -c tessedit_char_whitelist=0123456789'

        txt_saldo = pytesseract.image_to_string(thresh_saldo, config=config_numeros).strip()
        txt_credito = pytesseract.image_to_string(thresh_credito, config=config_numeros).strip()

        saldo = int(txt_saldo) if txt_saldo.isdigit() else 0
        credito = int(txt_credito) if txt_credito.isdigit() else 0

        return saldo, credito
    except:
        return 0, 0

# ==========================================
# STREAMING DE TELA
# ==========================================
def capturar_stream():
    print("🎥 Stream iniciado...")
    while True:
        if not sio.connected:
            time.sleep(1)
            continue
            
        inicio = time.time()
        
        try:
            img = ImageGrab.grab()
            if img.mode != 'RGB':
                img = img.convert('RGB')
            
            # OCR em background (Descomente a linha abaixo para enviar via socket)
            saldo, credito = extrair_dados_bingo(img)
            # sio.emit('atualizar_status_maquina', {'maquina_id': MAQUINA_ID, 'saldo': saldo, 'credito': credito})

            img_redimensionada = img.resize((1280, 720))
            buffer = BytesIO()
            img_redimensionada.save(buffer, format="JPEG", quality=50)
            img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
            
            sio.emit('stream_jpeg', {
                'maquina_id': MAQUINA_ID,
                'chunk': img_base64
            })
        except Exception as e:
            time.sleep(1)
            continue
            
        tempo_gasto = time.time() - inicio
        time.sleep(max(0.01, INTERVALO - tempo_gasto))

# ==========================================
# GERENCIAMENTO DO 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

# ==========================================
# EVENTOS SOCKET.IO
# ==========================================
@sio.event
def connect():
    print(f'✅ Conectado (Máquina {MAQUINA_ID})')
    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 = next((t for t, cmd in MAPA_TECLAS.items() if cmd == comando_recebido), None)
            if tecla_alvo:
                trazer_navegador_para_frente()
                pyautogui.press(tecla_alvo)
                return

        # Fallback JS
        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}")
        
        tecla_credito = {
            5: 'N',
            10: 'N',
            20: 'N',
            50: 'N',
            100: 'N',
            200: 'N'
        }.get(valor)
        
        if tecla_credito:
            trazer_navegador_para_frente()
            pyautogui.press(tecla_credito)
    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()

# ==========================================
# INÍCIO DO PROGRAMA
# ==========================================
if __name__ == '__main__':
    try:
        sio.connect(f'{SERVER_URL}:3000', auth={'token': TOKEN})
        
        threading.Thread(target=capturar_stream, daemon=True).start()
        threading.Thread(target=capturar_teclas, daemon=True).start()
        
        sio.wait()
    except KeyboardInterrupt:
        print('\n👋 Encerrando...')
        sys.exit(0)
    except Exception as e:
        print(f'❌ Erro: {e}')
        sys.exit(1)