from lxml import etree

def reordenar(xml_string):
    parser = etree.XMLParser(remove_blank_text=False)
    source_root = etree.XML(xml_string.encode('utf-8'), parser)

    new_root = etree.Element("root")

    # Capturar header e footer existentes
    header_node = source_root.find("header")
    footer_node = source_root.find("footer")

    if header_node is not None:
        new_root.append(etree.fromstring(etree.tostring(header_node)))
    else:
        new_root.append(etree.Element("header"))

    # Preparar containers para coletar todas as tags
    collected = {
        "reportName": [],
        "identificationReport": [],
        "QSAReport": [],
        "companyParticipationsReport": [],
        "advancedCommercialPaymentHistory_1": [],
        "spcMarketInquirySummary": [],
        "advancedCommercialPaymentHistory_2": [],
        "negativeData": [],
        "facts": []
    }

    # Varre todo XML e coleta as tags desejadas
    for elem in source_root.iter():
        if elem.tag == "reportName":
            collected["reportName"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "identificationReport":
            collected["identificationReport"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "QSAReport":
            collected["QSAReport"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "companyParticipationsReport":
            collected["companyParticipationsReport"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "advancedCommercialPaymentHistory":
            # Dependendo da posição vamos dividir entre 1 e 2
            # Se já preencheu advancedCommercialPaymentHistory_1, então vai para _2
            if not collected["advancedCommercialPaymentHistory_1"]:
                collected["advancedCommercialPaymentHistory_1"].append(etree.fromstring(etree.tostring(elem)))
            else:
                collected["advancedCommercialPaymentHistory_2"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "spcMarketInquirySummary":
            collected["spcMarketInquirySummary"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "negativeData":
            collected["negativeData"].append(etree.fromstring(etree.tostring(elem)))
        elif elem.tag == "facts":
            collected["facts"].append(etree.fromstring(etree.tostring(elem)))

    # Função auxiliar para montar blocos
    def criar_bloco(nome, elementos):
        if elementos:
            bloco = etree.Element(nome)
            for e in elementos:
                bloco.append(e)
            return bloco
        return None

    # Agora adiciona os blocos na ordem correta:

    bloco_reports = criar_bloco("reports", collected["reportName"] + collected["identificationReport"])
    if bloco_reports is not None:
        new_root.append(bloco_reports)

    bloco_optional_features = criar_bloco("optionalFeatures", collected["QSAReport"] + collected["companyParticipationsReport"])
    if bloco_optional_features is not None:
        new_root.append(bloco_optional_features)

    bloco_reports = criar_bloco("reports", collected["advancedCommercialPaymentHistory_1"])
    if bloco_reports is not None:
        new_root.append(bloco_reports)

    bloco_optional_features = criar_bloco("optionalFeatures", collected["spcMarketInquirySummary"])
    if bloco_optional_features is not None:
        new_root.append(bloco_optional_features)

    bloco_reports = criar_bloco("reports", collected["advancedCommercialPaymentHistory_2"] + collected["negativeData"] + collected["facts"])
    if bloco_reports is not None:
        new_root.append(bloco_reports)

    # Adicionar elementos desconhecidos (não perder nada que não seja conhecido)
    known_tags = [
        "reports", "optionalFeatures", "header", "footer",
        "reportName", "identificationReport", "QSAReport", "companyParticipationsReport",
        "advancedCommercialPaymentHistory", "spcMarketInquirySummary", "negativeData", "facts"
    ]
    
    for child in source_root:
        if child.tag not in known_tags:
            new_root.append(etree.fromstring(etree.tostring(child)))

    if footer_node is not None:
        new_root.append(etree.fromstring(etree.tostring(footer_node)))
    else:
        new_root.append(etree.Element("footer"))

    return etree.tostring(new_root, pretty_print=True, encoding="unicode")