#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
UTILITÁRIOS DE TESTE - Interface Web e Banco de Dados
Ferramentas para diagnóstico, testes e geração de dados de exemplo

Uso:
    python utilis_web_balanceamento.py [comando]
    
Comandos:
    - verificar_arquivos     Valida existência e formato de arquivos JSON
    - testar_conexao_db     Testa conexão com MySQL
    - gerar_dados_exemplo   Cria dados de exemplo para testes
    - limpar_dados          Remove dados de teste
    - diagnosticar          Rodada completa de diagnósticos
    - backup_dados          Faz backup do portfolio_estado.json
    - restaurar_backup      Restaura de backup anterior
"""

import json
import os
import sys
import shutil
import argparse
import re
from datetime import datetime, timedelta
from pathlib import Path

import pytz

try:
    import mysql.connector
    MYSQL_DISPONIVEL = True
except ImportError:
    MYSQL_DISPONIVEL = False

# ===================== CONFIGURAÇÃO =====================

SUBDIR = "robobalanceamento"
CONFIG_FILE = f"{SUBDIR}/configuracoes_balanceamento.json"
ESTADO_FILE = f"{SUBDIR}/portfolio_estado.json"
LOG_FILE = f"{SUBDIR}/log_balanceamento.log"
BACKUP_DIR = f"{SUBDIR}/backups"

DB_HOST = "localhost"
DB_USER = "root"
DB_PASS = ""
DB_NAME = "balanceamento_db"

TIMEZONE = pytz.timezone("America/Sao_Paulo")

# ===================== CORES PARA OUTPUT =====================

class Cor:
    VERDE = '\033[92m'
    VERMELHO = '\033[91m'
    AMARELO = '\033[93m'
    AZUL = '\033[94m'
    CINZA = '\033[90m'
    RESET = '\033[0m'
    BOLD = '\033[1m'

def info(msg):
    print(f"{Cor.AZUL}ℹ {msg}{Cor.RESET}")

def sucesso(msg):
    print(f"{Cor.VERDE}✓ {msg}{Cor.RESET}")

def erro(msg):
    print(f"{Cor.VERMELHO}✗ {msg}{Cor.RESET}")

def aviso(msg):
    print(f"{Cor.AMARELO}⚠ {msg}{Cor.RESET}")

def debug(msg):
    print(f"{Cor.CINZA}  {msg}{Cor.RESET}")

# ===================== VERIFICAÇÃO DE ARQUIVOS =====================

def verificar_arquivos():
    """Valida arquivo JSON e log"""
    print(f"\n{Cor.BOLD}=== VERIFICAÇÃO DE ARQUIVOS ==={Cor.RESET}")
    
    todos_ok = True
    
    # Verificar diretório
    if not os.path.isdir(SUBDIR):
        erro(f"Diretório não encontrado: {SUBDIR}")
        return False
    else:
        sucesso(f"Diretório existe: {SUBDIR}")
    
    # Verificar configurações
    if os.path.exists(CONFIG_FILE):
        sucesso(f"Arquivo existe: {CONFIG_FILE}")
        try:
            with open(CONFIG_FILE, 'r') as f:
                json.load(f)
            sucesso("  → JSON válido")
            tamanho = os.path.getsize(CONFIG_FILE)
            debug(f"  → Tamanho: {tamanho} bytes")
        except json.JSONDecodeError as e:
            erro(f"  → JSON inválido: {e}")
            todos_ok = False
    else:
        aviso(f"Arquivo não encontrado: {CONFIG_FILE}")
    
    # Verificar estado
    if os.path.exists(ESTADO_FILE):
        sucesso(f"Arquivo existe: {ESTADO_FILE}")
        try:
            with open(ESTADO_FILE, 'r') as f:
                dados = json.load(f)
            sucesso("  → JSON válido")
            tamanho = os.path.getsize(ESTADO_FILE)
            debug(f"  → Tamanho: {tamanho} bytes")
            
            moedas = len(dados.get('moedas_compradas', []))
            trades = len(dados.get('historico_trades', []))
            debug(f"  → Moedas: {moedas}, Trades: {trades}")
        except json.JSONDecodeError as e:
            erro(f"  → JSON inválido: {e}")
            todos_ok = False
    else:
        aviso(f"Arquivo não encontrado: {ESTADO_FILE} (normal em primeira execução)")
    
    # Verificar log
    if os.path.exists(LOG_FILE):
        sucesso(f"Arquivo existe: {LOG_FILE}")
        tamanho = os.path.getsize(LOG_FILE)
        linhas = len(open(LOG_FILE).readlines())
        debug(f"  → Tamanho: {tamanho} bytes, Linhas: {linhas}")
        
        # Verificar data da última linha
        with open(LOG_FILE, 'r') as f:
            ultima_linha = f.readlines()[-1] if f else ""
            match = re.search(r'\[(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2})\]', ultima_linha)
            if match:
                debug(f"  → Última atualização: {match.group(1)}")
    else:
        aviso(f"Arquivo não encontrado: {LOG_FILE} (normal, será criado na 1ª execução)")
    
    # Permissões
    print(f"\n{Cor.AZUL}Permissões:{Cor.RESET}")
    for arquivo in [CONFIG_FILE, ESTADO_FILE, LOG_FILE]:
        if os.path.exists(arquivo):
            mode = oct(os.stat(arquivo).st_mode)[-3:]
            sucesso(f"  {arquivo}: {mode}")
    
    return todos_ok

# ===================== TESTE DE BANCO DE DADOS =====================

def testar_conexao_db():
    """Testa conectividade com MySQL"""
    print(f"\n{Cor.BOLD}=== TESTE DE CONEXÃO MySQL ==={Cor.RESET}")
    
    if not MYSQL_DISPONIVEL:
        erro("mysql-connector-python não instalado")
        print("  Instale com: pip install mysql-connector-python")
        return False
    
    info(f"Host: {DB_HOST}")
    info(f"Usuario: {DB_USER}")
    info(f"Banco: {DB_NAME}")
    
    try:
        conn = mysql.connector.connect(
            host=DB_HOST,
            user=DB_USER,
            password=DB_PASS,
            database=DB_NAME
        )
        sucesso("Conectado ao MySQL!")
        
        # Verificar tabelas
        cursor = conn.cursor()
        cursor.execute("SHOW TABLES")
        tabelas = [row[0] for row in cursor.fetchall()]
        
        debug(f"Tabelas encontradas: {len(tabelas)}")
        for tabela in tabelas:
            debug(f"  - {tabela}")
        
        conn.close()
        return True
        
    except Exception as e:
        erro(f"Erro na conexão: {e}")
        print("\nDicas:")
        print("  1. Verifique se MySQL está rodando (XAMPP Control Panel)")
        print("  2. Verifique credenciais (host, user, password)")
        print("  3. Execute setup_db_balanceamento.php para criar banco")
        return False

# ===================== GERAR DADOS DE EXEMPLO =====================

def gerar_dados_exemplo():
    """Cria dados de exemplo para testes"""
    print(f"\n{Cor.BOLD}=== GERAÇÃO DE DADOS DE EXEMPLO ==={Cor.RESET}")
    
    # Estado de exemplo
    estado_exemplo = {
        "data_inicio": datetime.now(TIMEZONE).isoformat(),
        "fase": "balanceamento",
        "capital_inicial": 1000.00,
        "valor_total": 1150.50,
        "moedas_compradas": ["BTC", "ETH", "HBAR"],
        "moedas_pendentes": ["ADA", "SOL"],
        "percentuais_alvo": {
            "BTC": 25.0,
            "ETH": 25.0,
            "HBAR": 25.0,
            "ADA": 12.5,
            "SOL": 12.5
        },
        "precos_compra": {
            "BTC": 42000.00,
            "ETH": 2500.00,
            "HBAR": 0.0881,
            "ADA": 0.65,
            "SOL": 140.00
        },
        "historico_trades": [
            {
                "timestamp": (datetime.now(TIMEZONE) - timedelta(hours=2)).isoformat(),
                "moeda": "BTC",
                "tipo": "entrada",
                "preco": 42000.00,
                "quantidade": 0.01,
                "valor": 420.00
            },
            {
                "timestamp": (datetime.now(TIMEZONE) - timedelta(hours=1)).isoformat(),
                "moeda": "ETH",
                "tipo": "compra",
                "preco": 2500.00,
                "quantidade": 0.2,
                "valor": 500.00
            },
            {
                "timestamp": datetime.now(TIMEZONE).isoformat(),
                "moeda": "HBAR",
                "tipo": "rebalanceamento",
                "preco": 0.0881,
                "quantidade": 680.0,
                "valor": 60.00
            }
        ]
    }
    
    # Salvar arquivo
    backup_arquivo_existente()
    
    try:
        with open(ESTADO_FILE, 'w') as f:
            json.dump(estado_exemplo, f, indent=2, ensure_ascii=False)
        sucesso(f"Arquivo de exemplo criado: {ESTADO_FILE}")
        debug("✓ 3 trades de exemplo")
        debug("✓ 3 moedas compradas")
        debug("✓ 2 moedas pendentes")
        return True
    except Exception as e:
        erro(f"Erro ao criar arquivo: {e}")
        return False

# ===================== LIMPAR DADOS =====================

def limpar_dados():
    """Remove dados de teste"""
    print(f"\n{Cor.BOLD}=== LIMPEZA DE DADOS ==={Cor.RESET}")
    
    aviso("Essa operação é IRREVERSÍVEL")
    print("Os seguintes arquivos serão deletados:")
    print(f"  - {ESTADO_FILE}")
    print(f"  - {LOG_FILE}")
    
    resposta = input("\nContinuar? (s/n): ")
    
    if resposta.lower() != 's':
        aviso("Operação cancelada")
        return False
    
    deleted = 0
    
    if os.path.exists(ESTADO_FILE):
        try:
            os.remove(ESTADO_FILE)
            sucesso(f"Deletado: {ESTADO_FILE}")
            deleted += 1
        except Exception as e:
            erro(f"Erro ao deletar {ESTADO_FILE}: {e}")
    
    if os.path.exists(LOG_FILE):
        try:
            os.remove(LOG_FILE)
            sucesso(f"Deletado: {LOG_FILE}")
            deleted += 1
        except Exception as e:
            erro(f"Erro ao deletar {LOG_FILE}: {e}")
    
    sucesso(f"Limpeza concluída: {deleted} arquivo(s) deletado(s)")
    return True

# ===================== DIAGNÓSTICO COMPLETO =====================

def diagnosticar():
    """Rodada completa de diagnósticos"""
    print(f"\n{Cor.BOLD}{Cor.AZUL}")
    print("╔" + "═" * 50 + "╗")
    print("║" + " " * 50 + "║")
    print("║" + "  🔍 DIAGNÓSTICO COMPLETO - ROBÔ DE BALANCEAMENTO".center(50) + "║")
    print("║" + " " * 50 + "║")
    print("╚" + "═" * 50 + "╝")
    print(Cor.RESET)
    
    resultados = []
    
    # 1. Verificar arquivos
    info("1. Verificando arquivos...")
    resultado1 = verificar_arquivos()
    resultados.append(("Arquivos", resultado1))
    
    # 2. Teste de MySQL
    if MYSQL_DISPONIVEL:
        info("2. Testando MySQL...")
        resultado2 = testar_conexao_db()
        resultados.append(("MySQL", resultado2))
    
    # 3. Espaço em disco
    print(f"\n{Cor.BOLD}=== VERIFICAÇÃO DE ESPAÇO ==={Cor.RESET}")
    try:
        import shutil
        espaco = shutil.disk_usage(SUBDIR)
        sucesso(f"Espaço livre: {espaco.free / (1024**3):.2f} GB")
    except:
        aviso("Não foi possível verificar espaço")
    
    # Resumo
    print(f"\n{Cor.BOLD}=== RESUMO ==={Cor.RESET}")
    for nome, resultado in resultados:
        status = "✓ OK" if resultado else "✗ FALHA"
        cor = Cor.VERDE if resultado else Cor.VERMELHO
        print(f"{cor}{status}{Cor.RESET} - {nome}")
    
    # Recomendações
    print(f"\n{Cor.BOLD}=== PRÓXIMOS PASSOS ==={Cor.RESET}")
    print("1. Verifique se o robô está rodando")
    print("2. Acesse: http://localhost/projetos/balanceamento/log_balanceamento.php")
    print("3. Para MySQL: http://localhost/projetos/balanceamento/setup_db_balanceamento.php")

# ===================== BACKUP E RESTORE =====================

def backup_dados():
    """Faz backup do portfolio_estado.json"""
    print(f"\n{Cor.BOLD}=== BACKUP DE DADOS ==={Cor.RESET}")
    
    if not os.path.exists(ESTADO_FILE):
        aviso(f"Arquivo não encontrado: {ESTADO_FILE}")
        return False
    
    # Criar diretório de backup
    os.makedirs(BACKUP_DIR, exist_ok=True)
    
    # Nome do backup com timestamp
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_path = f"{BACKUP_DIR}/portfolio_estado_{timestamp}.json"
    
    try:
        shutil.copy2(ESTADO_FILE, backup_path)
        sucesso(f"Backup criado: {backup_path}")
        
        # Listar backups
        backups = sorted(os.listdir(BACKUP_DIR))
        debug(f"Total de backups: {len(backups)}")
        
        return True
    except Exception as e:
        erro(f"Erro ao criar backup: {e}")
        return False

def backup_arquivo_existente():
    """Backup automático antes de sobrescrever"""
    if os.path.exists(ESTADO_FILE):
        os.makedirs(BACKUP_DIR, exist_ok=True)
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_path = f"{BACKUP_DIR}/portfolio_estado_{timestamp}.bak"
        shutil.copy2(ESTADO_FILE, backup_path)
        debug(f"Backup automático: {backup_path}")

def restaurar_backup():
    """Restaura de um backup anterior"""
    print(f"\n{Cor.BOLD}=== RESTAURAR BACKUP ==={Cor.RESET}")
    
    if not os.path.exists(BACKUP_DIR):
        erro(f"Diretório de backups não encontrado: {BACKUP_DIR}")
        return False
    
    backups = sorted(os.listdir(BACKUP_DIR), reverse=True)
    
    if not backups:
        erro("Nenhum backup encontrado")
        return False
    
    print("Backups disponíveis:")
    for i, backup in enumerate(backups[:10], 1):  # Mostrar últimos 10
        tamanho = os.path.getsize(f"{BACKUP_DIR}/{backup}") / 1024
        print(f"  {i}. {backup} ({tamanho:.1f} KB)")
    
    try:
        escolha = int(input(f"\nEscolha o número do backup (1-{len(backups[:10])}): "))
        if 1 <= escolha <= len(backups[:10]):
            backup_escolhido = backups[escolha - 1]
            
            # Backup do arquivo atual
            backup_arquivo_existente()
            
            # Restaurar
            shutil.copy2(
                f"{BACKUP_DIR}/{backup_escolhido}",
                ESTADO_FILE
            )
            sucesso(f"Restaurado: {backup_escolhido}")
            return True
    except ValueError:
        erro("Número inválido")
    
    return False

# ===================== PROGRAMA PRINCIPAL =====================

def main():
    parser = argparse.ArgumentParser(
        description="Utilitários para Interface Web do Robô de Balanceamento"
    )
    parser.add_argument(
        'comando',
        nargs='?',
        choices=['verificar_arquivos', 'testar_conexao_db', 'gerar_dados_exemplo',
                'limpar_dados', 'diagnosticar', 'backup_dados', 'restaurar_backup'],
        help='Comando a executar'
    )
    
    args = parser.parse_args()
    
    if not args.comando:
        print(f"{Cor.BOLD}Utilitários de Teste - Interface Web{Cor.RESET}\n")
        print("Comandos disponíveis:")
        print("  verificar_arquivos      - Valida JSON e permissões")
        print("  testar_conexao_db       - Testa MySQL")
        print("  gerar_dados_exemplo     - Cria dados de exemplo")
        print("  limpar_dados            - Remove dados de teste")
        print("  diagnosticar            - Rodada completa")
        print("  backup_dados            - Faz backup")
        print("  restaurar_backup        - Restaura backup")
        print("\nUso: python utilis_web_balanceamento.py [comando]")
        return
    
    # Executar comando
    if args.comando == 'verificar_arquivos':
        verificar_arquivos()
    elif args.comando == 'testar_conexao_db':
        testar_conexao_db()
    elif args.comando == 'gerar_dados_exemplo':
        gerar_dados_exemplo()
    elif args.comando == 'limpar_dados':
        limpar_dados()
    elif args.comando == 'diagnosticar':
        diagnosticar()
    elif args.comando == 'backup_dados':
        backup_dados()
    elif args.comando == 'restaurar_backup':
        restaurar_backup()

if __name__ == "__main__":
    main()
