import os
import json
import time
from datetime import datetime
import requests
import lzma
import re

def getBuildId():
    """Acessa o portal Oplab e extrai a chave buildId."""
    url = "https://opcoes.oplab.com.br/mercado-de-opcoes"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    }

    try:
        response = requests.get(url, headers=headers, timeout=15)
        response.raise_for_status()
        match = re.search(r'"buildId":"(.*?)"', response.text)
        return match.group(1) if match else None
    except Exception as e:
        print(f"Erro ao obter buildId: {e}")
        return None

def get_url_content(url):
    """Auxiliar para baixar conteúdo com headers de navegador."""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    }
    response = requests.get(url, headers=headers, timeout=15)
    response.raise_for_status()
    return response.text

def get_lista_ativos(buildId):
    """Extrai a lista de todos os símbolos disponíveis a partir do JSON da PETR4."""
    # Usamos PETR4 como 'âncora' pois o JSON de qualquer ativo traz a lista completa de 'assets'
    url = f"https://opcoes.oplab.com.br/mercado/_next/data/{buildId}/pt-br/acoes/opcoes/PETR4.json"
    print("Obtendo lista de ativos...")
    html_txt = get_url_content(url)
    data = json.loads(html_txt)
    
    assets_list = data['pageProps']['assets']
    symbol_list = [asset['symbol'] for asset in assets_list]
    return sorted(symbol_list)

def process_page(url, nome):
    """Baixa o JSON do ativo e remove chaves redundantes para economizar espaço."""
    try:
        html_txt = get_url_content(url)
        data = json.loads(html_txt)
        page_props = data.get('pageProps', {})
        
        # Removemos 'assets' porque a lista é igual para todos os arquivos
        if 'assets' in page_props:
            del page_props['assets']
            
        # Removemos 'filteredOptions' se existir (geralmente é pesado e redundante)
        if 'filteredOptions' in page_props:
            del page_props['filteredOptions']
            
        return json.dumps(data)
    except Exception as e:
        print(f"Error processing page for {nome}: {e}")
    return None

def format_bytes(size: int) -> str:
    if size < 1024: return f"{size} B"
    elif size < 1024**2: return f"{size / 1024:.2f} KB"
    elif size < 1024**3: return f"{size / 1024**2:.2f} MB"
    else: return f"{size / 1024**3:.2f} GB"

def save_to_local(file_content: str, subfolder: str, file_name: str, compress: bool = False):
    folder = f"oplaboptions/{subfolder}"
    os.makedirs(folder, exist_ok=True)
    
    original_size = len(file_content.encode('utf-8'))
    
    if compress:
        file_path = os.path.join(folder, f"{file_name}.json.xz")
        with lzma.open(file_path, "wt", encoding="utf-8") as f:
            f.write(file_content)
        
        compressed_size = os.path.getsize(file_path)
        ratio = compressed_size / original_size if original_size > 0 else 0
        print(f"  -> {file_name}: {format_bytes(original_size)} -> {format_bytes(compressed_size)} (Ratio: {ratio:.2%})")
    else:
        file_path = os.path.join(folder, f"{file_name}.json")
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(file_content)
        print(f"  -> {file_name} saved ({format_bytes(original_size)})")

def main():
    start_time = time.time()
    buildId = getBuildId()
    
    if buildId:
        print(f"BuildId encontrado: {buildId}")
        lista_ativos = get_lista_ativos(buildId) # Passando buildId como argumento
        print(f"Total de ativos encontrados: {len(lista_ativos)}")
        
        timestamp = datetime.now().strftime("%Y_%m_%d__%H_%M")
        
        # Para testar apenas os 5 primeiros, descomente a linha abaixo:
        # lista_ativos = lista_ativos[:5]
        
        for i, ativo in enumerate(lista_ativos):
            url = f"https://opcoes.oplab.com.br/mercado/_next/data/{buildId}/pt-br/acoes/opcoes/{ativo}.json"
            print(f"[{i+1}/{len(lista_ativos)}] Processing: {ativo}")
            
            file_content = process_page(url, ativo)
            if file_content:
                save_to_local(file_content, timestamp, ativo, compress=True)
            
            # Pequeno delay para não ser bloqueado pelo servidor
            time.sleep(0.5) 
            
        end_time = time.time()
        print(f"\nConcluído em {end_time - start_time:.2f} segundos.")
    else:
        print("Falha ao recuperar a urlKey.")

if __name__ == "__main__":
    main()