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.BancoOdonto;
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.ufsc.esus.dadoinstalacao.DadoInstalacaoTransport;
import br.ufsc.esus.dadotransporte.DadoTransporteTransportOdontoXml;
import br.ufsc.esus.fichaatendimentoodontologicochild.FichaAtendimentoOdontologicoChildTransport;
import br.ufsc.esus.fichaatendimentoodontologicomaster.FichaAtendimentoOdontologicoMasterTransport;
import br.ufsc.esus.lotacaoheader.LotacaoHeaderTransport;
import br.ufsc.esus.procedimentoquantidade.ProcedimentoQuantidadeTransport;
import br.ufsc.esus.variaslotacoesheader.VariasLotacoesHeaderTransport;
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 Odonto extends BD {
  BancoOdonto bdOdonto = new BancoOdonto();

  public void executeMain(int eehCodigo, DadoInstalacaoTransport remetenteOriginadora)
    throws SQLException, JAXBException, IOException {
    EsusHistoricoItens bdEsusHistoricoItens = new EsusHistoricoItens();
    ResultSet dadosOdonto = bdOdonto.getDados();
    while (dadosOdonto.next()) {

      Odonto dadosThrift = new Odonto();
      String uuid = dadosThrift.getGUID();
      FichaAtendimentoOdontologicoMasterTransport fichaMaster = fichaAtendimentoOdontologicoMasterThrift(uuid,
        dadosOdonto);
      DadoTransporteTransportOdontoXml arrayEnvio = montaArrayEnvioDto(fichaMaster, uuid, dadosOdonto, eehCodigo,
        remetenteOriginadora);
      zipWriter(arrayEnvio, uuid);
      bdEsusHistoricoItens.registratHistoricoItens(eehCodigo, uuid, 7);
      bdOdonto.atualizaStatus(uuid, dadosOdonto.getInt("odo_pcon_codigo"));
    }
    dadosOdonto.close();
  }

  public void zipWriter(DadoTransporteTransportOdontoXml xmlText, String uuid)
    throws JAXBException, IOException {

    String arquivo = uuid + ".esus.xml";
    br.ufsc.esus.dadotransporte.ObjectFactoryOdonto factoryCadastroIndividual = new br.ufsc.esus.dadotransporte.ObjectFactoryOdonto();

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

  public FichaAtendimentoOdontologicoMasterTransport fichaAtendimentoOdontologicoMasterThrift(String uuid,
    ResultSet row) throws SQLException {

    VariasLotacoesHeaderTransport variasLotacoes = variasLotacoes(row);
    FichaAtendimentoOdontologicoChildTransport atendimentosOdontologicos = fichaAtendimentoOdontologicoChildThrift(row);

    FichaAtendimentoOdontologicoMasterTransport arrayDto = new FichaAtendimentoOdontologicoMasterTransport();
    arrayDto.setUuidFicha(uuid);
    arrayDto.setHeaderTransport(variasLotacoes);
    arrayDto.setTpCdsOrigem(3);
    arrayDto.getAtendimentosOdontologicos().add(atendimentosOdontologicos);
    return arrayDto;
  }

  public VariasLotacoesHeaderTransport variasLotacoes(ResultSet row) throws SQLException {

    LotacaoHeaderTransport headerTransport = new LotacaoHeaderTransport();

    headerTransport.setProfissionalCNS(
      (validaCnsBanco(row.getString("eo_profissional_cns")) ? row.getString("eo_profissional_cns") : null));
    headerTransport.setCboCodigo2002(row.getString("eo_cbo_codigo_2002"));
    headerTransport.setCnes(StringUtils.leftPad(row.getString("eo_cnes"), 7, "0"));
    headerTransport.setIne(row.getString("eo_ine"));

    VariasLotacoesHeaderTransport variasLotacoes = new VariasLotacoesHeaderTransport();

    variasLotacoes.setLotacaoFormPrincipal(headerTransport);
    variasLotacoes.setDataAtendimento(DataConvert.dateToEpoch(row.getDate("eo_dtatendimento")));
    variasLotacoes.setCodigoIbgeMunicipio(row.getString("eo_codigo_ibge_mun"));

    return variasLotacoes;
  }

  public FichaAtendimentoOdontologicoChildTransport fichaAtendimentoOdontologicoChildThrift(ResultSet row)
    throws SQLException {

    long tiposConsultaOdonto = row.getLong("eo_tipo_consulta");
    FichaAtendimentoOdontologicoChildTransport arrayAtendOdonto = new FichaAtendimentoOdontologicoChildTransport();
    arrayAtendOdonto.setDtNascimento(DataConvert.dateToEpoch(row.getDate("eo_dtnascimento")));
    if ((validaCnsBanco(row.getString("eo_num_cartao_sus")))) {
      arrayAtendOdonto.setCnsCidadao(row.getString("eo_num_cartao_sus"));
    } else if (validaCpf(row.getString("eo_cpf_cidadao"))) {
      arrayAtendOdonto.setCpfCidadao(row.getString("eo_cpf_cidadao"));
    }
    arrayAtendOdonto.setTurno((row.getLong("turno") != 0L ? row.getLong("turno") : 1L));
    arrayAtendOdonto.setDataHoraInicialAtendimento(
      (row.getString("eo_data_hora_inicial") != null ? dateToEpoch(row.getDate("eo_data_hora_inicial")
      ) : null)
    );
    arrayAtendOdonto.setDataHoraFinalAtendimento(
      (row.getString("eo_data_hora_final") != null ? dateToEpoch(row.getDate("eo_data_hora_final")
      ) : null)
    );
    arrayAtendOdonto.setNumProntuario(row.getString("eo_numprontuario"));
    if (row.getLong("co_local_atend") <= 10)
      arrayAtendOdonto.setLocalAtendimento(row.getLong("co_local_atend"));
    arrayAtendOdonto.setTipoAtendimento(row.getLong("eo_tipo_atendimento"));
    arrayAtendOdonto.setSexo(Long.valueOf(row.getString("eo_sexo").replace(" L", "")));
    arrayAtendOdonto.getTiposEncamOdonto().addAll(getCondutaEncaminhamento(row.getInt("odo_pcon_codigo")));
    arrayAtendOdonto.getTiposVigilanciaSaudeBucal().addAll(getVigilanciaSaudeBucal(row.getInt("odo_pcon_codigo")));
    if (tiposConsultaOdonto > 0) {
      arrayAtendOdonto.getTiposConsultaOdonto().add(tiposConsultaOdonto);
    }
    arrayAtendOdonto.getProcedimentosRealizados().addAll(listaProcedimentosSigtap(row.getInt("odo_pcon_codigo")));

    return arrayAtendOdonto;
  }

  public List<ProcedimentoQuantidadeTransport> listaProcedimentosSigtap(int odoPconCodigo) throws SQLException {
    BancoOdonto bancoOdonto = new BancoOdonto();
    ResultSet dadosProcedimentosSigtap = bancoOdonto.getProcedimentos(odoPconCodigo);
    List<ProcedimentoQuantidadeTransport> arrayGeral = new ArrayList<>();
    while (dadosProcedimentosSigtap.next()) {
      ProcedimentoQuantidadeTransport array = new ProcedimentoQuantidadeTransport();
      array.setCoMsProcedimento(dadosProcedimentosSigtap.getString("proc_codigo_sus"));
      array.setQuantidade(1);
      arrayGeral.add(array);
    }
    dadosProcedimentosSigtap.close();
    return arrayGeral;
  }

  public List<Long> getCondutaEncaminhamento(int odoPconCodigo) throws SQLException {
    BancoOdonto bancoOdonto = new BancoOdonto();
    ResultSet dadosEncaminhamento = bancoOdonto.getCondutaEncaminhamento(odoPconCodigo);
    List<Long> procsRea = new ArrayList<>();
    while (dadosEncaminhamento.next()) {
      procsRea.add(dadosEncaminhamento.getLong("tp_cds_encam_odonto"));
    }
    dadosEncaminhamento.close();
    return procsRea;
  }

  public List<Long> getVigilanciaSaudeBucal(int odoPconCodigo) throws SQLException {
    BancoOdonto bancoOdonto = new BancoOdonto();
    ResultSet dadosVigilancia = bancoOdonto.getVigilanciaSaudeBucal(odoPconCodigo);
    List<Long> procsRea = new ArrayList<>();
    if (dadosVigilancia.wasNull()) {
      procsRea.add(99L);
    }
    while (dadosVigilancia.next()) {
      procsRea.add(dadosVigilancia.getLong("tp_cds_vig_saude_bucal"));
    }
    dadosVigilancia.close();
    return procsRea;
  }

  private DadoTransporteTransportOdontoXml montaArrayEnvioDto(
    FichaAtendimentoOdontologicoMasterTransport fichaMasterSerializado, 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);
    DadoTransporteTransportOdontoXml dadoTransporteTransportXml = new DadoTransporteTransportOdontoXml();
    dadoTransporteTransportXml.setUuidDadoSerializado(uuid);
    dadoTransporteTransportXml
      .setTipoDadoSerializado(TipoDadoSerializado.ATENDIMENTOODONTOLOGICO.getValue());
    dadoTransporteTransportXml.setCnesDadoSerializado(StringUtils.leftPad(row.getString("eo_cnes"), 7, "0"));
    dadoTransporteTransportXml.setCodIbge(row.getString("eo_codigo_ibge_mun"));
    dadoTransporteTransportXml.setNumLote(eehCodigo);
    dadoTransporteTransportXml.setRemetente(remetenteOriginadora);
    dadoTransporteTransportXml.setOriginadora(remetenteOriginadora);
    dadoTransporteTransportXml.setVersao(arrayVersao);
    dadoTransporteTransportXml.setFichaAtendimentoOdontologicoMasterTransport(fichaMasterSerializado);

    return dadoTransporteTransportXml;

  }

}
