# -*- coding: utf-8 -*-
"""
AGENTE MINERO - PARA TU PC LOCAL
=================================
Este programa ejecuta XMRig en tu PC y envía estadísticas al panel en la gota.

INSTALACIÓN:
  pip install requests

CONFIGURACIÓN:
  1. Descarga XMRig: https://github.com/xmrig/xmrig/releases
  2. Coloca xmrig.exe en la misma carpeta que este script
  3. Edita las variables abajo (PANEL_URL, WALLET, WORKER_ID)
  4. Ejecuta: python agente_pc.py

WINDOWS: Ejecuta como Administrador para mejor rendimiento
"""

import os
import sys
import json
import time
import queue
import signal
import threading
import subprocess
import re
from datetime import datetime
import requests

# ============================================================================
# ⚙️ CONFIGURACIÓN - EDITA ESTOS VALORES
# ============================================================================

# URL del panel en tu droplet (cambia cuando configures nginx)
PANEL_URL = "http://64.227.26.128:5000"  # Temporal, luego será https://miner.drantoninoparisi.cloud

# Tu wallet de Monero (cámbiala por la tuya real)
WALLET = "4BKesue7tcjBuNWGwM9BbPUffdeGFxCu6968nys96vjj1dfWjPSNvtx9PMjWJMkrwrVuSvLdH2FvsgzVrNXuWVadRqpX97g"

# Identificador único de este PC (cámbialo por algo descriptivo)
WORKER_ID = "laptop-principal"

# Pool (puedes cambiarlo)
POOL_HOST = "donate.v2.xmrig.com"
POOL_PORT = 3333

# Threads (usa la mitad de tus cores para no saturar)
THREADS = max(1, (os.cpu_count() or 2) // 2)

# Ruta a XMRig (busca automático o especifica)
XMRIG_PATH = r"C:\minero\xmrig-6.24.0\xmrig.exe"  # Déjalo vacío para buscar automáticamente

# ============================================================================
# Búsqueda automática de XMRig
# ============================================================================

def find_xmrig():
    """Busca xmrig.exe en ubicaciones comunes"""
    if XMRIG_PATH and os.path.exists(XMRIG_PATH):
        return XMRIG_PATH
    
    candidates = [
        "xmrig.exe",
        "xmrig",
        "./xmrig.exe",
        "./xmrig",
        r"C:\minero\xmrig\xmrig.exe",
        r"C:\xmrig\xmrig.exe",
        "/usr/local/bin/xmrig",
        "/usr/bin/xmrig",
    ]
    
    for path in candidates:
        if os.path.exists(path):
            return path
    
    return None

# ============================================================================
# Parser de salida de XMRig
# ============================================================================

class XMRigStats:
    def __init__(self):
        self.hashrate = 0.0
        self.shares_ok = 0
        self.shares_rej = 0
        self.pool = ""
        self.uptime_start = time.time()
        self.last_line = ""
    
    def parse_line(self, line):
        """Parsea líneas de XMRig para extraer métricas"""
        L = line.lower()
        
        # Hashrate - MEJORADO para capturar el formato de XMRig
        if "speed" in L and "h/s" in L:
            # Buscar patrón: "speed 10s/60s/15m 1117.1 n/a n/a H/s max 1259.2 H/s"
            # Queremos capturar el primer número (1117.1)
            match = re.search(r'speed\s+[\d/sma]+\s+([\d.]+)', line, re.IGNORECASE)
            if match:
                try:
                    self.hashrate = float(match.group(1))
                except:
                    pass
            else:
                # Fallback: buscar primer número seguido de espacios y h/s
                parts = L.replace("\t", " ").split()
                for i, part in enumerate(parts):
                    if i > 0 and "h/s" in part:
                        try:
                            # Intentar convertir la parte anterior
                            val = parts[i-1].replace("h/s", "").strip()
                            self.hashrate = float(val)
                            break
                        except:
                            pass
        
        # Shares aceptados
        if "accepted" in L:
            self.shares_ok += 1
        
        # Shares rechazados
        if "rejected" in L:
            self.shares_rej += 1
        
        # Pool conectado
        if "use pool" in L:
            try:
                self.pool = line.split("use pool", 1)[1].strip().split()[0]
            except:
                pass
        
        self.last_line = line.strip()
    
    def uptime(self):
        """Retorna uptime formateado"""
        s = int(time.time() - self.uptime_start)
        h, m = s // 3600, (s % 3600) // 60
        return f"{h:02d}:{m:02d}:{s%60:02d}"

# ============================================================================
# Controlador de XMRig
# ============================================================================

class XMRigController:
    def __init__(self, xmrig_path):
        self.xmrig_path = xmrig_path
        self.process = None
        self.stats = XMRigStats()
        self.output_queue = queue.Queue()
        self.running = False
        self.mining = False
    
    def start(self):
        """Inicia XMRig"""
        if self.mining:
            print("❌ Ya está minando")
            return False
        
        args = [
            self.xmrig_path,
            "-o", f"{POOL_HOST}:{POOL_PORT}",
            "-u", WALLET,
            "-p", "x",
            "--rig-id", WORKER_ID,
            "-t", str(THREADS),
            "-k",
            "--donate-level", "1",
            "--print-time", "10",
            "-a", "rx/0",
        ]
        
        print(f"\n▶️  Iniciando minería...")
        print(f"   Pool: {POOL_HOST}:{POOL_PORT}")
        print(f"   Worker: {WORKER_ID}")
        print(f"   Threads: {THREADS}\n")
        
        try:
            self.process = subprocess.Popen(
                args,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                bufsize=1,
            )
            self.mining = True
            self.stats = XMRigStats()
            
            # Thread para leer salida
            threading.Thread(target=self._reader, daemon=True).start()
            return True
        except Exception as e:
            print(f"❌ Error al iniciar: {e}")
            return False
    
    def stop(self):
        """Detiene XMRig"""
        if not self.mining:
            return
        
        print("\n⏹  Deteniendo minería...")
        if self.process:
            try:
                if os.name == 'nt':
                    self.process.send_signal(signal.CTRL_BREAK_EVENT)
                else:
                    self.process.terminate()
                self.process.wait(timeout=5)
            except:
                try:
                    self.process.kill()
                except:
                    pass
        self.mining = False
        self.process = None
    
    def _reader(self):
        """Lee stdout de XMRig"""
        for line in iter(self.process.stdout.readline, b''):
            try:
                txt = line.decode('utf-8', 'replace')
                print(txt, end='')  # Muestra en consola
                self.stats.parse_line(txt)
            except:
                pass
    
    def get_stats(self):
        """Retorna estadísticas actuales"""
        return {
            'worker_id': WORKER_ID,
            'mining': self.mining,
            'hashrate': self.stats.hashrate,
            'shares_ok': self.stats.shares_ok,
            'shares_rej': self.stats.shares_rej,
            'pool': f"{POOL_HOST}:{POOL_PORT}",
            'uptime': self.stats.uptime(),
            'wallet': WALLET[:8] + "..." + WALLET[-8:],
        }

# ============================================================================
# Enviador de heartbeats al panel
# ============================================================================

class PanelReporter:
    def __init__(self, panel_url, controller):
        self.panel_url = panel_url
        self.controller = controller
        self.running = False
    
    def start(self):
        """Inicia envío periódico de datos"""
        self.running = True
        threading.Thread(target=self._loop, daemon=True).start()
    
    def stop(self):
        self.running = False
    
    def _loop(self):
        """Loop que envía datos cada 5 segundos"""
        while self.running:
            try:
                stats = self.controller.get_stats()
                url = f"{self.panel_url}/api/agent/heartbeat"
                requests.post(url, json=stats, timeout=5)
            except Exception as e:
                print(f"⚠️  Error enviando al panel: {e}")
            time.sleep(5)

# ============================================================================
# Main
# ============================================================================

def main():
    print("\n" + "="*60)
    print("  ⛏️  AGENTE MINERO - PC LOCAL")
    print("="*60)
    
    # Buscar XMRig
    xmrig = find_xmrig()
    if not xmrig:
        print("\n❌ ERROR: No se encuentra XMRig")
        print("\nDescárgalo de: https://github.com/xmrig/xmrig/releases")
        print("Y colócalo en la misma carpeta que este script\n")
        input("Presiona Enter para salir...")
        sys.exit(1)
    
    print(f"✅ XMRig encontrado: {xmrig}")
    print(f"📡 Panel: {PANEL_URL}")
    print(f"💼 Wallet: {WALLET[:8]}...{WALLET[-8:]}")
    print(f"👷 Worker: {WORKER_ID}")
    print(f"🧵 Threads: {THREADS}")
    print("="*60)
    
    # Crear controlador
    controller = XMRigController(xmrig)
    reporter = PanelReporter(PANEL_URL, controller)
    
    # Iniciar reporter
    reporter.start()
    
    # Menú simple
    while True:
        print("\n┌─────────────────────────────┐")
        print("│  MENÚ                       │")
        print("├─────────────────────────────┤")
        print("│  1. ▶️  Iniciar minería     │")
        print("│  2. ⏹  Detener minería      │")
        print("│  3. 📊 Ver estadísticas     │")
        print("│  4. ❌ Salir                │")
        print("└─────────────────────────────┘")
        
        opcion = input("\nSelecciona opción: ").strip()
        
        if opcion == "1":
            controller.start()
        
        elif opcion == "2":
            controller.stop()
        
        elif opcion == "3":
            stats = controller.get_stats()
            print("\n📊 ESTADÍSTICAS:")
            print(f"   Estado: {'⛏️ Minando' if stats['mining'] else '⏹ Detenido'}")
            print(f"   Hashrate: {stats['hashrate']:.1f} H/s")
            print(f"   Shares OK: {stats['shares_ok']}")
            print(f"   Shares Rej: {stats['shares_rej']}")
            print(f"   Uptime: {stats['uptime']}")
            print(f"   Pool: {stats['pool']}")
        
        elif opcion == "4":
            print("\n👋 Cerrando...")
            controller.stop()
            reporter.stop()
            break

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n👋 Interrumpido por usuario")
    except Exception as e:
        print(f"\n❌ Error: {e}")
        input("Presiona Enter para salir...")