package br.com.elotech.websaude.integracao.esus.controller;

import br.com.elotech.websaude.integracao.esus.model.BD;
import br.com.elotech.websaude.integracao.esus.model.BancoFichaVacinacao;
import br.com.elotech.websaude.integracao.esus.model.EsusHistoricoItens;
import br.com.elotech.websaude.integracao.esus.util.Compactador;
import br.ufsc.esus.dadoinstalacao.DadoInstalacaoTransport;
import br.ufsc.esus.dadotransporte.DadoTransporteTransportVacinacaoXml;
import br.ufsc.esus.fichavacinacaochild.FichaVacinacaoChildTransport;
import br.ufsc.esus.fichavacinacaochild.VacinaRowThriftTransport;
import br.ufsc.esus.fichavacinacaomaster.FichaVacinacaoMasterTransport;
import br.ufsc.esus.unicalotacaoheader.UnicaLotacaoHeaderTransport;
import br.ufsc.esus.versao.VersaoTransport;
import org.apache.commons.lang3.StringUtils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static br.com.elotech.websaude.integracao.esus.util.DataConvert.dateToEpoch;

public class FichaVacinacao extends BD {

  public void executeMain(int eehCodigo, DadoInstalacaoTransport remetenteOriginadora)
    throws SQLException, JAXBException, IOException {
    BancoFichaVacinacao bdFichaVac = new BancoFichaVacinacao();
    EsusHistoricoItens bdEsusHistoricoItens = new EsusHistoricoItens();
    ResultSet dadosVacina = bdFichaVac.getDadosFichaVacinacaoChild();
    while (dadosVacina.next()) {
      FichaVacinacao vacinacao = new FichaVacinacao();
      String uuid = vacinacao.getGUID();
      FichaVacinacaoMasterTransport ficha = fichaVacinacaoThrift(uuid, dadosVacina);
      DadoTransporteTransportVacinacaoXml arrayEnvio = montaArrayEnvioDto(ficha, uuid,
        dadosVacina, eehCodigo, remetenteOriginadora);
      zipWriter(arrayEnvio, uuid);
      bdEsusHistoricoItens.registratHistoricoItens(eehCodigo, uuid, 14);
      bdFichaVac.atualizaStatus(uuid, dadosVacina.getInt("codigo"));
    }
    dadosVacina.close();
  }

  public void zipWriter(DadoTransporteTransportVacinacaoXml xmlText, String uuid) throws JAXBException, IOException {
    String arquivo = uuid + ".esus.xml";
    br.ufsc.esus.dadotransporte.ObjectFactoryVacinacao factoryFichaVacinacao = new br.ufsc.esus.dadotransporte.ObjectFactoryVacinacao();

    JAXBContext context;
    context = JAXBContext.newInstance(br.ufsc.esus.dadotransporte.ObjectFactoryVacinacao.class);
    JAXBElement<DadoTransporteTransportVacinacaoXml> element
      = factoryFichaVacinacao.createDadoTransporteTransportVacinacaoXml(xmlText);
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
    marshaller.marshal(element, new FileWriter("arqs/" + arquivo));
    Compactador.ARQUIVOS.add(arquivo);
  }

  private FichaVacinacaoMasterTransport fichaVacinacaoThrift(String uuid, ResultSet row)
    throws SQLException {

    BancoFichaVacinacao bdFichaVac = new BancoFichaVacinacao();
    UnicaLotacaoHeaderTransport arrayUnica = montaArrayUnica(row);
    FichaVacinacaoMasterTransport dadosFv = new FichaVacinacaoMasterTransport();
    List<FichaVacinacaoChildTransport> fichas = new ArrayList<>();
    FichaVacinacaoChildTransport ficha = new FichaVacinacaoChildTransport();
    List<VacinaRowThriftTransport> vacinas = new ArrayList<>();
    Integer origem = 3;

    dadosFv.setHeaderTransport(arrayUnica);
    dadosFv.setUuidFicha(uuid);
    dadosFv.setTpCdsOrigem(origem);

    ficha.setTurno(row.getLong("turno"));
    ficha.setNumProntuario(row.getString("numProntuario"));

    if ((validaCnsBanco(row.getString("cnsCidadao")))) {
      ficha.setCnsCidadao(row.getString("cnsCidadao"));
    } else if (validaCpf(row.getString("cpfCidadao"))) {
      ficha.setCpfCidadao(row.getString("cpfCidadao"));
    }

    ficha.setDtNascimento(dateToEpoch(row.getDate("dtNascimento")));
    long sexo = 4;
    if (row.getString("sexo").equals("M")) {
      sexo = 0;
    } else if (row.getString("sexo").equals("F")) {
      sexo = 1;
    }
    ficha.setSexo(sexo);
    ficha.setLocalAtendimento(row.getLong("localAtendimento"));
    ficha.setViajante(row.getBoolean("viajante"));
    ficha.setGestante(row.getBoolean("gestante"));
    ficha.setPuerpera(row.getBoolean("puerpera"));

    ficha.setDataHoraInicialAtendimento(
      row.getDate("horaInicial") != null ? dateToEpoch(row.getDate("horaInicial")) : null);
    ficha.setDataHoraFinalAtendimento(
      row.getDate("horaFinal") != null ? dateToEpoch(row.getDate("horaFinal")) : null);

    ResultSet dados = bdFichaVac.getDadosVacinaRowThrift(row.getInt("codigo"));
    while (dados.next()) {
      VacinaRowThriftTransport vac = new VacinaRowThriftTransport();
      vac.setImunobiologico(dados.getLong("imunobiologico"));
      vac.setEstrategiaVacinacao(dados.getLong("estrategiaVacinacao"));
      vac.setDose(dados.getLong("dose"));
      if (vac.getImunobiologico() == 15) {
        if (row.getString("comunicanteHanseniase") != null
          && !row.getString("comunicanteHanseniase").isEmpty()) {
          ficha.setComunicanteHanseniase(row.getBoolean("comunicanteHanseniase"));
        }
        if (vac.getDose() == 1) {
          vac.setDose(Long.parseLong("9"));
        }
        if (vac.getDose() != 9 && vac.getDose() != 1 && vac.getDose() != 10) {
          vac.setDose(Long.parseLong("10"));
        }
      }
      vac.setLote(dados.getString("lote"));
      vac.setFabricante(dados.getString("fabricante"));
      if (vacinas.size() < 10) {
        vacinas.add(vac);
      }
    }
    dados.close();
    ficha.setVacinas(vacinas);
    fichas.add(ficha);

    dadosFv.setVacinacoes(fichas);

    return dadosFv;
  }

  private UnicaLotacaoHeaderTransport montaArrayUnica(ResultSet row) throws SQLException {
    UnicaLotacaoHeaderTransport headerTransport = new UnicaLotacaoHeaderTransport();
    headerTransport.setProfissionalCNS((validaCnsBanco(row.getString("profissionalCNS").trim())
      ? row.getString("profissionalCNS").trim()
      : null));
    headerTransport.setCboCodigo2002(row.getString("cboCodigo_2002"));
    headerTransport.setCnes(StringUtils.leftPad(row.getString("cnes"), 7, "0"));
    headerTransport.setIne(row.getString("ine"));
    headerTransport.setDataAtendimento(dateToEpoch(row.getDate("dataAtendimento")));
    headerTransport.setCodigoIbgeMunicipio(row.getString("codigoIbgeMunicipio"));
    return headerTransport;
  }

  private DadoTransporteTransportVacinacaoXml montaArrayEnvioDto(
    FichaVacinacaoMasterTransport dadosVacinacaoSerializado, String uuid, ResultSet row, int eehCodigo,
    DadoInstalacaoTransport remetenteOriginadora)
    throws SQLException {

    remetenteOriginadora.setUuidInstalacao(uuid);

    VersaoTransport arrayVersao = new VersaoTransport();
    arrayVersao.setMajor(3);
    arrayVersao.setMinor(2);
    arrayVersao.setRevision(4);

    DadoTransporteTransportVacinacaoXml dadoTransporteTransportXml = new DadoTransporteTransportVacinacaoXml();
    dadoTransporteTransportXml.setUuidDadoSerializado(uuid);
    dadoTransporteTransportXml.setTipoDadoSerializado(14);
    dadoTransporteTransportXml.setCnesDadoSerializado(StringUtils.leftPad(row.getString("cnes"), 7, "0"));
    dadoTransporteTransportXml.setCodIbge(row.getString("codigoIbgeMunicipio"));
    dadoTransporteTransportXml.setIneDadoSerializado(row.getString("ine"));
    dadoTransporteTransportXml.setNumLote(eehCodigo);
    dadoTransporteTransportXml.setFichaVacinacaoMasterTransport(dadosVacinacaoSerializado);
    dadoTransporteTransportXml.setRemetente(remetenteOriginadora);
    dadoTransporteTransportXml.setOriginadora(remetenteOriginadora);
    dadoTransporteTransportXml.setVersao(arrayVersao);

    return dadoTransporteTransportXml;
  }

}
