import requests
import xml.etree.ElementTree as ET
import json
import time
import re

# --- CONFIGURAÇÕES ---
# O endpoint OAI do Dataverse da Redape/Embrapa
# Nota: Se o endereço principal é redape.dados.embrapa.br, o OAI costuma ser /oai
OAI_URL = "https://www.redape.dados.embrapa.br/oai"
TARGET_RECORDS = 50 

# 'oai_datacite' garante a captura de todos os campos técnicos
PARAMS_INICIAIS = {
    "verb": "ListRecords",
    "metadataPrefix": "oai_datacite"
}

HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
}

# --- FUNÇÕES DE CONVERSÃO (Igual ao SciELO) ---

def remove_namespace(tag):
    """Remove os prefixos {http://...} das tags XML."""
    return re.sub(r'\{.*?\}', '', tag)

def xml_to_dict(element):
    """
    Transforma a árvore XML do DataCite em um Dicionário Python/JSON,
    preservando atributos (como @type) e listas de valores.
    """
    tag_clean = remove_namespace(element.tag)
    data = {}
    
    # Atributos (ex: dateType="Submitted")
    if element.attrib:
        data.update({f"@{k}": v for k, v in element.attrib.items()})

    # Texto do elemento
    text = element.text.strip() if element.text else None
    if text:
        data["#text"] = text

    # Processa os filhos recursivamente
    for child in element:
        child_tag = remove_namespace(child.tag)
        child_data = xml_to_dict(child)
        
        # Se a tag aparece mais de uma vez (ex: vários creators), vira lista
        if child_tag in data:
            if not isinstance(data[child_tag], list):
                data[child_tag] = [data[child_tag]]
            data[child_tag].append(child_data)
        else:
            data[child_tag] = child_data
            
    # Simplifica se for apenas texto
    if len(data) == 1 and "#text" in data:
        return data["#text"]
    
    return data if data else None

# --- FUNÇÃO PRINCIPAL ---

def coleta_redape_embrapa():
    print(f"--- INICIANDO COLETA REDAPE EMBRAPA ---")
    print(f"1. Conectando ao endpoint: {OAI_URL}")
    print(f"   Meta: {TARGET_RECORDS} registros completos (DataCite).")

    datasets_coletados = []
    resumption_token = None
    
    # Loop de Paginação
    while len(datasets_coletados) < TARGET_RECORDS:
        
        # Define se pede a 1ª página ou a continuação
        if resumption_token:
            params = {"verb": "ListRecords", "resumptionToken": resumption_token}
            print(f"   -> Buscando próxima página...")
        else:
            params = PARAMS_INICIAIS
            print(f"   -> Buscando primeira página...")

        try:
            # Pausa de etiqueta para não sobrecarregar o servidor da Embrapa
            if resumption_token: time.sleep(1)
            
            response = requests.get(OAI_URL, params=params, headers=HEADERS, timeout=60)
            
            if response.status_code != 200:
                print(f"Erro HTTP {response.status_code} ao acessar o repositório.")
                break

            # Parse do XML de resposta
            root = ET.fromstring(response.content)
            
            # Namespaces OAI padrão
            ns = {'oai': 'http://www.openarchives.org/OAI/2.0/'}
            
            # Verifica se o servidor retornou erro (ex: sem registros)
            error_node = root.find('.//oai:error', ns)
            if error_node is not None:
                print(f"O servidor retornou um erro OAI: {error_node.text}")
                break

            records = root.findall('.//oai:record', ns)
            
            if not records:
                print("Nenhum registro encontrado nesta página.")
                break

            # Itera sobre os registros encontrados
            for record in records:
                if len(datasets_coletados) >= TARGET_RECORDS: break
                
                header = record.find('oai:header', ns)
                # Ignora registros marcados como deletados
                if header.get('status') == 'deleted': continue
                
                metadata_node = record.find('oai:metadata', ns)
                
                # Se houver metadados, extrai tudo
                if metadata_node is not None and len(list(metadata_node)) > 0:
                    payload = list(metadata_node)[0] # O bloco DataCite/XML
                    dados_completos = xml_to_dict(payload)
                    
                    id_oai = header.find('oai:identifier', ns).text
                    
                    obj = {
                        "embrapa_id": id_oai,
                        "metadata_datacite": dados_completos
                    }
                    
                    datasets_coletados.append(obj)
                    print(f"      [{len(datasets_coletados)}/{TARGET_RECORDS}] Coletado: {id_oai}")

            # Verifica se tem token para mais páginas
            token_node = root.find('.//oai:resumptionToken', ns)
            if token_node is not None and token_node.text:
                resumption_token = token_node.text
            else:
                print("Fim da paginação disponível.")
                break

        except Exception as e:
            print(f"Erro crítico durante a coleta: {e}")
            break

    # Salva o resultado final
    nome_arquivo = "redape_embrapa_50_datacite.json"
    with open(nome_arquivo, "w", encoding="utf-8") as f:
        json.dump(datasets_coletados, f, ensure_ascii=False, indent=2)
        
    print("\n" + "="*50)
    print(f"SUCESSO! Coleta finalizada.")
    print(f" - Registros salvos: {len(datasets_coletados)}")
    print(f" - Arquivo gerado: {nome_arquivo}")
    print("="*50)

if __name__ == "__main__":
    coleta_redape_embrapa()