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.BancoProcedimentos;
import br.com.elotech.websaude.integracao.esus.model.EsusHistoricoItens;
import br.com.elotech.websaude.integracao.esus.model.enums.TipoDadoSerializado;
import br.com.elotech.websaude.integracao.esus.util.Compactador;
import br.com.elotech.websaude.integracao.esus.util.DataConvert;
import br.com.elotech.websaude.integracao.esus.util.Util;
import br.ufsc.esus.dadoinstalacao.DadoInstalacaoTransport;
import br.ufsc.esus.dadotransporte.DadoTransporteTransportProcedimentoXml;
import br.ufsc.esus.fichaprocedimentochild.FichaProcedimentoChildTransport;
import br.ufsc.esus.fichaprocedimentomaster.FichaProcedimentoMasterTransport;
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.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Procedimento extends BD {

  public void executeMain(int eehCodigo, DadoInstalacaoTransport remetenteOriginadora)
    throws SQLException, JAXBException, IOException {
    BancoProcedimentos bdProcedimentos = new BancoProcedimentos();
    EsusHistoricoItens bdEsusHistoricoItens = new EsusHistoricoItens();
    List<HashMap> dadosProcedimentos = bdProcedimentos.getDadosProcedimentos();
    List<String> listaRepassados = new ArrayList<>();

    for (HashMap hash : dadosProcedimentos) {
      if (!listaRepassados.contains(String.valueOf(hash.get("age_codigo")))) {

        Procedimento dadosThrift = new Procedimento();
        String uuid = dadosThrift.getGUID();
        FichaProcedimentoMasterTransport fichaMaster = montaArrayFichaProcedimentoMaster(uuid, hash);

        DadoTransporteTransportProcedimentoXml fichaMasterSerializa = montaArrayEnvioDto(fichaMaster, uuid, hash,
          eehCodigo, remetenteOriginadora);

        zipWriter(fichaMasterSerializa, uuid);
        bdEsusHistoricoItens.registratHistoricoItens(eehCodigo, uuid, 3);

        Integer ageCodigo = Integer.parseInt(String.valueOf(hash.get("age_codigo")));
        bdProcedimentos.atualizaStatus(uuid, ageCodigo);
        listaRepassados.add(String.valueOf(hash.get("age_codigo")));
      }
    }
  }

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

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

  public DadoTransporteTransportProcedimentoXml montaArrayEnvioDto(
    FichaProcedimentoMasterTransport fichaMasterSerializado, String uuid, HashMap row, int eehCodigo,
    DadoInstalacaoTransport remetenteOriginadora) {

    remetenteOriginadora.setUuidInstalacao(uuid);

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

    DadoTransporteTransportProcedimentoXml dadoTransporteTransportXml = new DadoTransporteTransportProcedimentoXml();
    dadoTransporteTransportXml.setUuidDadoSerializado(uuid);

    dadoTransporteTransportXml.setTipoDadoSerializado(TipoDadoSerializado.PROCEDIMENTOS.getValue());
    dadoTransporteTransportXml.setCnesDadoSerializado(Util.verificaNulo(row.get("efp_cnes")));
    if (dadoTransporteTransportXml.getCnesDadoSerializado() != null) {
      dadoTransporteTransportXml.setCnesDadoSerializado(StringUtils.leftPad(dadoTransporteTransportXml.getCnesDadoSerializado(), 7, "0"));
    }
    dadoTransporteTransportXml.setCodIbge(Util.verificaNulo(row.get("efp_codigo_ibge_mun")));
    dadoTransporteTransportXml.setIneDadoSerializado(Util.verificaNulo(row.get("efp_ine")));
    dadoTransporteTransportXml.setNumLote(eehCodigo);
    dadoTransporteTransportXml.setRemetente(remetenteOriginadora);
    dadoTransporteTransportXml.setOriginadora(remetenteOriginadora);
    dadoTransporteTransportXml.setVersao(arrayVersao);
    dadoTransporteTransportXml.setFichaProcedimentoMasterTransport(fichaMasterSerializado);
    return dadoTransporteTransportXml;

  }

  public FichaProcedimentoMasterTransport montaArrayFichaProcedimentoMaster(String uuid, HashMap row)
    throws SQLException {
    // Pega os dados do profissional e do atendimento e coloca em array, para ser transformado em um objeto do E-SUS
    UnicaLotacaoHeaderTransport arrayUnica = montaArrayUnica(row);
    // Pega os dados do paciente, atendimento e procedimentos realizados e coloca em array
    List<FichaProcedimentoChildTransport> arrayAtendProcedimentos = montaArrayAtendProcedimentos(row);
    // Pega mais alguns dados do atendimento, os array especificados acima e coloca tudo dentro de um �nico array

    FichaProcedimentoMasterTransport arrayDto = new FichaProcedimentoMasterTransport();
    arrayDto.setUuidFicha(uuid);
    arrayDto.setTpCdsOrigem(3);
    arrayDto.setHeaderTransport(arrayUnica);

    arrayDto.getAtendProcedimentos().addAll(arrayAtendProcedimentos);

    if (Long.parseLong(row.get("numtotalafericaopa").toString()) > 0) {
      arrayDto.setNumTotalAfericaoPa(Long.valueOf(Util.verificaNulo(row.get("numtotalafericaopa"))));
    }
    if (Long.parseLong(row.get("numtotalglicemiacapilar").toString()) > 0) {
      arrayDto.setNumTotalGlicemiaCapilar(Long.valueOf(Util.verificaNulo(row.get("numtotalglicemiacapilar"))));
    }
    if (Long.parseLong(row.get("numtotalafericaotemperatura").toString()) > 0) {
      arrayDto.setNumTotalAfericaoTemperatura(Long.valueOf(Util.verificaNulo(row.get("numtotalafericaotemperatura"))));
    }
    if (Long.parseLong(row.get("numtotalmedicaoalturapeso").toString()) > 0) {
      arrayDto.setNumTotalMedicaoAltura(Long.valueOf(Util.verificaNulo(row.get("numtotalmedicaoalturapeso"))));
    }
    if (Long.parseLong(row.get("numtotalcurativo").toString()) > 0) {
      arrayDto.setNumTotalCurativoSimples(Long.valueOf(Util.verificaNulo(row.get("numtotalcurativo"))));
    }
    if (Long.parseLong(row.get("numtotalmedicaoalturapeso").toString()) > 0) {
      arrayDto.setNumTotalMedicaoPeso(Long.valueOf(Util.verificaNulo(row.get("numtotalmedicaoalturapeso"))));
    }
    if (Long.parseLong(row.get("numtotalexame").toString()) > 0) {
      arrayDto
        .setNumTotalColetaMaterialParaExameLaboratorial(Long.valueOf(Util.verificaNulo(row.get("numtotalexame"))));
    }

    return arrayDto;
  }

  public UnicaLotacaoHeaderTransport montaArrayUnica(HashMap row) {

    UnicaLotacaoHeaderTransport arrayUnica = new UnicaLotacaoHeaderTransport();
    String efpProfissionalCns = Util.verificaNulo(row.get("efp_profissional_cns"));
    arrayUnica.setProfissionalCNS((validaCnsBanco(efpProfissionalCns) ? efpProfissionalCns : null));

    arrayUnica.setCboCodigo2002(Util.verificaNulo(row.get("efp_cbo_codigo_2002")));
    arrayUnica.setCnes(Util.verificaNulo(row.get("efp_cnes")));
    if (arrayUnica.getCnes() != null) {
      arrayUnica.setCnes(StringUtils.leftPad(arrayUnica.getCnes(), 7, "0"));
    }
    arrayUnica.setIne(Util.verificaNulo(row.get("efp_ine")));
    arrayUnica
      .setDataAtendimento(DataConvert.dateToEpoch(Date.valueOf(Util.verificaNulo(row.get("efp_dtatendimento")))));
    arrayUnica.setCodigoIbgeMunicipio(Util.verificaNulo(row.get("efp_codigo_ibge_mun")));

    return arrayUnica;
  }

  public List<FichaProcedimentoChildTransport> montaArrayAtendProcedimentos(HashMap row) throws SQLException {
    FichaProcedimentoChildTransport arrayAtendProced = new FichaProcedimentoChildTransport();
    arrayAtendProced.setNumProntuario(Util.verificaNulo(row.get("efp_numprontuario")));
    String efpNumCartaoSus = Util.verificaNulo(row.get("efp_num_cartao_sus"));
    arrayAtendProced.setCnsCidadao((validaCnsBanco(efpNumCartaoSus) ? efpNumCartaoSus : null));
    arrayAtendProced
      .setDtNascimento(DataConvert.dateToEpoch(Date.valueOf(Util.verificaNulo(row.get("efp_dtnascimento")))));
    String efpSexo = Util.verificaNulo(row.get("efp_sexo"));
    if (!efpSexo.equals("")) {
      efpSexo = efpSexo.replace(" L", "");
    }
    arrayAtendProced.setSexo(Long.valueOf(efpSexo));
    if (Long.valueOf(row.get("co_local_atend").toString()).intValue() <= 10)
      arrayAtendProced.setLocalAtendimento(Long.valueOf(Util.verificaNulo(row.get("co_local_atend"))));
    arrayAtendProced.setTurno(row.get("turno") != null ? Long.parseLong(Util.verificaNulo(row.get("turno"))) : 1L);
    arrayAtendProced.getProcedimentos()
      .addAll(listaProcedimentos(Integer.parseInt(Util.verificaNulo(row.get("age_codigo")))));
    // Verifica se o procedimento 03.01.04.007-9 foi adicionado, e caso sim, remove-o e seta o parâmetro setStatusEscutaInicialOrientacao como True
    if (arrayAtendProced.getProcedimentos().contains("0301040079")) {
      arrayAtendProced.getProcedimentos().remove("0301040079");
      arrayAtendProced.setStatusEscutaInicialOrientacao(true);
    }
    if (Util.verificaNulo(row.get("efp_data_hora_inicial")) != null) {
      Timestamp dataHoraInicial = Timestamp.valueOf(row.get("efp_data_hora_inicial").toString());
      arrayAtendProced.setDataHoraInicialAtendimento(DataConvert.dateToEpoch(new Date(dataHoraInicial.getTime())));
    }
    if (Util.verificaNulo(row.get("efp_data_hora_final")) != null) {
      Timestamp dataHoraFinal = Timestamp.valueOf(row.get("efp_data_hora_final").toString());
      arrayAtendProced.setDataHoraFinalAtendimento(DataConvert.dateToEpoch(new Date(dataHoraFinal.getTime())));
    }
    List<FichaProcedimentoChildTransport> lista = new ArrayList<>();
    lista.add(arrayAtendProced);
    return lista;
  }

  public List<String> listaProcedimentos(int ageCodigo) throws SQLException {
    BancoProcedimentos bdProcedimentos = new BancoProcedimentos();
    ResultSet dadosProcedimentos = bdProcedimentos.getProcedimentosSigtap(ageCodigo);
    List<String> procsFicha = new ArrayList<>();
    while (dadosProcedimentos.next()) {
      procsFicha.add(dadosProcedimentos.getString("proc_codigo_sus"));
    }
    dadosProcedimentos.close();
    return procsFicha;
  }

}
