package ru.nbch.credit_tracker.service.xml.stax;

import lombok.extern.slf4j.Slf4j;
import ru.nbch.credit_tracker.entities.external_request.signals.Auth;
import ru.nbch.credit_tracker.entities.external_request.signals.Person;
import ru.nbch.credit_tracker.entities.external_request.signals.Signals;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.List;

@Slf4j
public class SignalsStaxXmlWriter extends StaxXmlWriter<Signals, Person> {

    public SignalsStaxXmlWriter(String charsetName) {
        super(charsetName);
    }

    public void writeWithStax(String filePath, Signals signals, LoaderWriter<Person> loader) {
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath), 8 * 1024 * 1024)) {
            XMLOutputFactory output = XMLOutputFactory.newInstance();
            XMLEventFactory xmlEventFactory = XMLEventFactory.newInstance();
            XMLEventWriter writer = output.createXMLEventWriter(bos, charsetName);
            writer = new IndentingXMLEventWriter(writer);

            writerWrapper = new WriterWrapper(xmlEventFactory, writer);
            writerWrapper.addStartDocument(charsetName);

            writerWrapper.addStartElement("Signals");
            writerWrapper.addAttribute("online", signals.getOnline());
            writerWrapper.addAttribute("processWithErrors", signals.getProcessWithErrors());
            writerWrapper.addSimplelement("Id", signals.getId());
            writeAuth(signals.getAuth());

            writerWrapper.addStartElement("Conditions");
            writerWrapper.addStartElement("Persons");


            loader.accept(persons -> {
                try {
                    writePersons(persons);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

            writerWrapper.addEndElement("Persons");
            writerWrapper.addEndElement("Conditions");

            writerWrapper.addEndElement("Signals");

            writerWrapper.addEndDocument();
            writerWrapper.flush();
            System.gc();
        } catch (Throwable e) {
            log.error("Error serializing object to XML string: {}", e.getMessage(), e);
            throw new IllegalStateException("cannot serialize object to XML");
        }
    }

    public void writePersons(List<Person> persons) throws Exception{
        writerWrapper.writeCollection("p", persons, this::writePerson);
    }


    private void writeAuth(Auth auth) throws Exception {
        writerWrapper.addStartElement("Auth");
        writerWrapper.addSimplelement("User", auth.getUser());
        writerWrapper.addEndElement("Auth");
    }

    private void writePerson(Person person, String name) throws Exception {
        if (person == null) {
            return;
        }
        writerWrapper.addStartElement(name);
        writerWrapper.addAttribute("uid", String.valueOf(person.getUid()));
        writerWrapper.addAttribute("oksm", person.getOksm());
        writerWrapper.addAttribute("s", person.getS());
        writerWrapper.addAttribute("n", person.getN());
        writerWrapper.addAttribute("m", person.getM());
        writerWrapper.addAttribute("d", person.getD());
        writerWrapper.addAttribute("pn", person.getPn());
        writerWrapper.addAttribute("pd", person.getPd());
        writerWrapper.addAttribute("dt", person.getDt());
        writerWrapper.addAttribute("odt", person.getOdt());
        writerWrapper.addAttribute("ip", person.getIp());
        writerWrapper.addAttribute("consentDate", person.getConsentDate());
        writerWrapper.addAttribute("consentPurpose", person.getConsentPurpose());
        writerWrapper.addAttribute("reportUser", person.getReportUser());
        writerWrapper.addAttribute("liability", person.getLiability());
        writerWrapper.addAttribute("consentPeriod", person.getConsentPeriod());
        writerWrapper.addAttribute("agrDate", person.getAgrDate());
        writerWrapper.addAttribute("reportUserRegNum", person.getReportUserRegNum());
        writerWrapper.addAttribute("reportUserTaxID", person.getReportUserTaxID());
        writerWrapper.addAttribute("consentHash", person.getConsentHash());
        writerWrapper.addAttribute("cS", person.getCs());
        writerWrapper.addAttribute("consentN", person.getConsentN());
        writerWrapper.addAttribute("consentM", person.getConsentM());
        writerWrapper.addAttribute("consentBd", person.getConsentBd());
        writerWrapper.addAttribute("consentPn", person.getConsentPn());
        writerWrapper.addAttribute("consentPd", person.getConsentPd());
        writerWrapper.addAttribute("consentDivCode", person.getConsentDivCode());
        writerWrapper.addAttribute("consentDt", person.getConsentDt());
        writerWrapper.addAttribute("consentOdt", person.getConsentOdt());
        writerWrapper.addAttribute("consentIssueAuthority", person.getConsentIssueAuthority());
        writerWrapper.addAttribute("inqPurpose", person.getInqPurpose());
        writerWrapper.addEndElement(name);
    }


}
