# -*- coding: utf-8 -*-
"""
SCRIPT DE VALIDAÇÃO - ROBÔ DE BALANCEAMENTO
Testa a configuração, conexão com Binance e pronta para uso
"""

import json
import ccxt
import os
from colorama import init, Fore, Style

init()

def print_sucesso(msg):
    print(Fore.GREEN + "✓ " + msg + Style.RESET_ALL)

def print_erro(msg):
    print(Fore.RED + "✗ " + msg + Style.RESET_ALL)

def print_aviso(msg):
    print(Fore.YELLOW + "⚠ " + msg + Style.RESET_ALL)

def print_info(msg):
    print(Fore.CYAN + "ℹ " + msg + Style.RESET_ALL)

def validar_arquivo_config():
    """Valida se o arquivo de configuração existe e é válido"""
    print("\n" + "="*60)
    print("VALIDANDO ARQUIVO DE CONFIGURAÇÃO")
    print("="*60)
    
    if not os.path.exists('configuracoes_balanceamento.json'):
        print_erro("Arquivo 'configuracoes_balanceamento.json' não encontrado!")
        return None
    
    try:
        with open('configuracoes_balanceamento.json', 'r', encoding='utf-8') as f:
            config = json.load(f)
        print_sucesso("Arquivo encontrado e válido (JSON)")
        return config
    except json.JSONDecodeError as e:
        print_erro(f"Erro ao ler JSON: {e}")
        return None

def validar_chaves_api(config):
    """Valida se as chaves da API estão configuradas"""
    print("\n" + "="*60)
    print("VALIDANDO CHAVES DA API")
    print("="*60)
    
    testnet = config.get('testnet', False)
    
    if testnet:
        print_info("Modo TESTNET ativado")
        api_key = config.get('api_key_testnet', '')
        api_secret = config.get('api_secret_testnet', '')
    else:
        print_aviso("Modo REAL - Use com cuidado!")
        api_key = config.get('api_key', '')
        api_secret = config.get('api_secret', '')
    
    if not api_key:
        print_erro("API Key não configurada!")
        return False
    
    if not api_secret:
        print_erro("API Secret não configurado!")
        return False
    
    if len(api_key) < 30:
        print_erro("API Key parece inválida (muito curta)")
        return False
    
    if len(api_secret) < 30:
        print_erro("API Secret parece inválido (muito curto)")
        return False
    
    print_sucesso("API Key e Secret encontrados")
    return True

def validar_conexao_binance(config):
    """Testa a conexão com a Binance"""
    print("\n" + "="*60)
    print("TESTANDO CONEXÃO COM BINANCE")
    print("="*60)
    
    testnet = config.get('testnet', False)
    api_key = config.get('api_key_testnet' if testnet else 'api_key', '')
    api_secret = config.get('api_secret_testnet' if testnet else 'api_secret', '')
    
    try:
        exchange = ccxt.binance({
            'apiKey': api_key,
            'secret': api_secret,
            'enableRateLimit': True,
            'options': {'defaultType': 'spot'},
        })
        
        if testnet:
            exchange.set_sandbox_mode(True)
            print_info("Usando Testnet (sandbox)")
        
        exchange.load_markets()
        print_sucesso("Conexão com Binance estabelecida!")
        
        # Testar obtenção de saldo
        try:
            balance = exchange.fetch_balance()
            total_balance = balance.get('total', {})
            print_info(f"Saldo recuperado com sucesso")
            
            usdt_balance = balance.get('free', {}).get('USDT', 0)
            print_info(f"USDT disponível: {usdt_balance}")
            
            return True
        except Exception as e:
            print_aviso(f"Não foi possível obter saldo: {e}")
            print_aviso("Verifique as permissões da chave API (deve ter 'Read')")
            return True  # Ainda assim é ok se conseguiu conectar
            
    except Exception as e:
        print_erro(f"Falha ao conectar com Binance: {e}")
        return False

def validar_portfolio(config):
    """Valida a configuração do portfólio"""
    print("\n" + "="*60)
    print("VALIDANDO PORTFÓLIO")
    print("="*60)
    
    portfolio = config.get('portfolio', [])
    
    if not portfolio:
        print_erro("Nenhuma moeda configurada no portfólio!")
        return False
    
    print_sucesso(f"Portfólio com {len(portfolio)} moedas")
    
    total_percentual = 0
    moedas_ativas = 0
    
    for i, moeda in enumerate(portfolio, 1):
        try:
            nome = moeda.get('moeda', 'DESCONHECIDA')
            percentual = moeda.get('percentual', 0)
            preco_compra = moeda.get('preco_compra', 0)
            ativa = moeda.get('ativa', True)
            
            if ativa:
                moedas_ativas += 1
                total_percentual += percentual
                
                print_info(f"  {i}. {nome:8s} | {percentual:6.1f}% | Entrada: ${preco_compra:12.8f}")
        except Exception as e:
            print_erro(f"  Erro na moeda {i}: {e}")
            return False
    
    print_info(f"Moedas ativas: {moedas_ativas}")
    print_info(f"Total de percentuais: {total_percentual:.1f}%")
    
    if abs(total_percentual - 100) > 1:
        print_aviso(f"Percentuais não somam 100%! (somam {total_percentual:.1f}%)")
        print_aviso("O robô funcionará mas com risco de desequilíbrio")
    else:
        print_sucesso("Percentuais corretos (somam ~100%)")
    
    return True

def validar_parametros(config):
    """Valida os parâmetros de funcionamento"""
    print("\n" + "="*60)
    print("VALIDANDO PARÂMETROS")
    print("="*60)
    
    capital = config.get('capital_inicial', 0)
    tempo_ciclo = config.get('tempo_ciclo', 0)
    variacao = config.get('variacao_balanceamento', 0)
    comissao = config.get('comissao', 0)
    saldo_minimo = config.get('saldo_minimo', 0)
    
    if capital <= 0:
        print_erro("Capital inicial deve ser > 0")
        return False
    
    print_info(f"Capital Inicial: ${capital:.2f}")
    
    if capital < 50:
        print_aviso(f"Capital muito baixo (${capital:.2f}) - considere aumentar")
    
    if tempo_ciclo <= 0:
        print_erro("Tempo de ciclo deve ser > 0")
        return False
    
    print_info(f"Tempo de Ciclo: {tempo_ciclo}s")
    
    if variacao <= 0:
        print_erro("Variação de balanceamento deve ser > 0")
        return False
    
    print_info(f"Variação Balanceamento: {variacao}%")
    
    if variacao > 10:
        print_aviso("Variação muito alta (>10%) - rebalanceamento raro")
    
    if variacao < 0.1:
        print_aviso("Variação muito baixa (<0.1%) - rebalanceamento frequente")
    
    print_info(f"Comissão: {comissao}%")
    print_info(f"Saldo Mínimo: ${saldo_minimo:.2f}")
    
    return True

def testar_preco_moeda(config):
    """Testa obtenção de preços de algumas moedas"""
    print("\n" + "="*60)
    print("TESTANDO PREÇOS DE MOEDAS")
    print("="*60)
    
    testnet = config.get('testnet', False)
    api_key = config.get('api_key_testnet' if testnet else 'api_key', '')
    api_secret = config.get('api_secret_testnet' if testnet else 'api_secret', '')
    
    try:
        exchange = ccxt.binance({
            'apiKey': api_key,
            'secret': api_secret,
            'enableRateLimit': True,
        })
        
        if testnet:
            exchange.set_sandbox_mode(True)
        
        exchange.load_markets()
        
        portfolio = config.get('portfolio', [])
        moedas_base = config.get('moeda_base', 'USDT')
        
        for moeda in portfolio[:3]:  # Testar apenas as 3 primeiras
            try:
                nome = moeda.get('moeda', '')
                symbol = f"{nome}/{moedas_base}"
                
                ticker = exchange.fetch_ticker(symbol)
                preco = ticker.get('last') or ticker.get('close')
                
                print_sucesso(f"{symbol:12s} → ${preco:.8f}")
            except Exception as e:
                print_erro(f"{symbol} → Erro: {e}")
        
        return True
    except Exception as e:
        print_erro(f"Erro ao buscar preços: {e}")
        return False

def mostrar_resumo(config):
    """Mostra um resumo final da configuração"""
    print("\n" + "="*60)
    print("RESUMO DA CONFIGURAÇÃO")
    print("="*60)
    
    print_info(f"Modo: {'TESTNET' if config.get('testnet') else 'REAL - CUIDADO!'}")
    print_info(f"Capital: ${config.get('capital_inicial', 0):.2f}")
    print_info(f"Moeda Base: {config.get('moeda_base', 'USDT')}")
    print_info(f"Portfólio: {len([m for m in config.get('portfolio', []) if m.get('ativa', True)])} moedas")
    print_info(f"Tempo Ciclo: {config.get('tempo_ciclo', 0)}s")
    print_info(f"Variação Balanceamento: {config.get('variacao_balanceamento', 0)}%")

def main():
    print("\n")
    print(Fore.CYAN + "╔════════════════════════════════════════════════════════════╗")
    print("║   VALIDADOR - ROBÔ DE BALANCEAMENTO DE PORTFÓLIO          ║")
    print("╚════════════════════════════════════════════════════════════╝" + Style.RESET_ALL)
    
    # Validações
    config = validar_arquivo_config()
    if not config:
        print_erro("\nNão foi possível prosseguir!")
        return False
    
    if not validar_chaves_api(config):
        print_erro("\nConfigure suas chaves da API!")
        return False
    
    if not validar_conexao_binance(config):
        print_erro("\nNão foi possível conectar à Binance!")
        return False
    
    if not validar_portfolio(config):
        print_erro("\nPortfólio inválido!")
        return False
    
    if not validar_parametros(config):
        print_erro("\nParâmetros inválidos!")
        return False
    
    testar_preco_moeda(config)
    
    # Resumo
    mostrar_resumo(config)
    
    # Status final
    print("\n" + "="*60)
    print_sucesso("TODAS AS VALIDAÇÕES PASSARAM!")
    print("="*60)
    
    print("\n" + Fore.YELLOW + "PRÓXIMOS PASSOS:" + Style.RESET_ALL)
    print("1. Se estiver usando TESTNET: Teste o robô sem risco real")
    print("2. Se estiver usando REAL: Comece com pequeno capital")
    print("3. Monitore o arquivo 'log_balanceamento.log' durante execução")
    print("4. Verifique o 'portfolio_estado.json' para ver status do portfólio")
    
    print("\nPara iniciar o robô:")
    print(Fore.GREEN + "  python interface_graficabalanceamento.py  (Interface gráfica)" + Style.RESET_ALL)
    print(Fore.GREEN + "  python robo_balanceamento.py             (Linha de comando)" + Style.RESET_ALL)
    
    return True

if __name__ == "__main__":
    sucesso = main()
    exit(0 if sucesso else 1)
