"""Demonstra as oito chamadas com transporte SIMULADO; nenhuma rede ou assinatura real.

Usa unittest.mock para ilustrar o contrato de integração, não o funcionamento
fiscal do worker. Não adapte esse simulador para decidir estados de produção.
"""
import base64
import json
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import patch

from acbr import (Cancelamento, CertificadoA1, Configuracao, Consulta,
                  Diagnostico, Emissor, EventoEnvio, Inutilizacao, ResultadoFiscal)
from contrato_offline import carregar_documento

XML_SINTETICO = "<NFe>SIMULACAO-SEM-ASSINATURA-OU-VALOR-FISCAL</NFe>"


def main() -> int:
    config = Configuracao(cnpj="00000000000000", uf="CE", ambiente=2,
                         certificado=CertificadoA1(b"SYNTHETIC-NOT-A-PFX", "SYNTHETIC-PASSWORD"))
    runtime = SimpleNamespace(directory=Path("."), executable=Path("NAO-EXECUTAR"),
                              capabilities=frozenset({"recuperarXml"}))
    eventos = []

    def ao_iniciar_envio(evento: EventoEnvio) -> None:
        eventos.append({"id": evento.id, "comando": evento.comando})

    def simular(executable, directory, environment, request, *, cancel=None):
        command = request["comando"]
        assert request["config"]["ambiente"] == 2
        states = {"gerarXml": "XML_GERADO", "validar": "VALIDADO", "assinar": "ASSINADO",
                  "transmitir": "PENDENTE", "consultar": "CONSULTADO", "cancelar": "REJEITADO",
                  "inutilizar": "REJEITADO", "recuperarXml": "CONSULTADO"}
        local = command in {"gerarXml", "validar", "assinar"}
        sending = command in {"transmitir", "cancelar", "inutilizar"}
        if sending:
            # Evento também simulado, sem marcador nativo nem envio remoto.
            ao_iniciar_envio(EventoEnvio(id=request["id"], comando=command))
        status = "nao_enviado" if local else "pendente" if command == "transmitir" else "nao_autorizado"
        diagnostic = Diagnostico("SIMULADO", "teste_offline", "Resposta simulada; sem rede.",
                                 "Não utilizar como evidência fiscal.", status_envio=status)
        xml = base64.b64encode(XML_SINTETICO.encode("utf-8")).decode("ascii") if command in {"gerarXml", "assinar"} else None
        return ResultadoFiscal(sucesso=local or command == "consultar", estado=states[command],
                               diagnostico=diagnostic, c_stat=None if local else 103 if command == "transmitir" else 217,
                               xml_base64=xml, envio_iniciado=sending)

    # Essas substituições impedem qualquer verificação, início do motor ou rede.
    # As respostas NÃO testam criptografia, schema ou aceitação fiscal.
    with patch("acbr.client.verify_runtime", return_value=runtime), \
         patch("acbr.client.runtime_environment", return_value={}), \
         patch("acbr.transport.ProcessTransport.execute", side_effect=simular), \
         patch("subprocess.Popen", side_effect=AssertionError("Processo nativo bloqueado no exemplo")):
        with Emissor(config, runtime_directory="SIMULADO", ao_iniciar_envio=ao_iniciar_envio) as emissor:
            resultados = [
                emissor.gerar_xml(carregar_documento()),
                emissor.validar(XML_SINTETICO),
                emissor.assinar(XML_SINTETICO),
                emissor.transmitir(XML_SINTETICO, allow_network=True),
                emissor.consultar(Consulta(chave="0" * 44), allow_network=True),
                emissor.cancelar(Cancelamento("0" * 44, "0" * 15,
                                             "TESTE SINTETICO SEM VALOR FISCAL"), allow_network=True),
                emissor.inutilizar(Inutilizacao(26, 1, 1, 1,
                                               "TESTE SINTETICO SEM VALOR FISCAL"), allow_network=True),
                emissor.recuperar_xml(XML_SINTETICO, allow_network=True),
            ]
    assert len(resultados) == 8 and len(eventos) == 3
    print(json.dumps({"SIMULACAO_OFFLINE": True, "rede_realizada": False,
                      "resultados": [item.to_dict() for item in resultados]}, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
