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.BancoAtendimentoIndividual;
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.ufsc.esus.dadoinstalacao.DadoInstalacaoTransport;
import br.ufsc.esus.dadotransporte.DadoTransporteTransportAteIndividualXml;
import br.ufsc.esus.exame.ExameTransport;
import br.ufsc.esus.fichaatendimentoindividualchild.FichaAtendimentoIndividualChildTransport;
import br.ufsc.esus.fichaatendimentoindividualmaster.FichaAtendimentoIndividualMasterTransport;
import br.ufsc.esus.lotacaoheader.LotacaoHeaderTransport;
import br.ufsc.esus.problemacondicaoavaliacaoai.ProblemaCondicaoAvaliacaoAITransport;
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.Arrays;
import java.util.List;

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

public class AteIndividual extends BD {

  public void executeMain(int eehCodigo, DadoInstalacaoTransport remetenteOriginadora) throws SQLException, JAXBException, IOException {
    BancoAtendimentoIndividual bdAteIndividual = new BancoAtendimentoIndividual();
    EsusHistoricoItens bdEsusHistoricoItens = new EsusHistoricoItens();
    ResultSet dadosAteIndividual = bdAteIndividual.getDados();

    while (dadosAteIndividual.next()) {

      String uuid = getGUID();
      FichaAtendimentoIndividualMasterTransport fichaMaster = fichaAtendimentoIndividualMasterThrift(uuid,
        dadosAteIndividual);
      DadoTransporteTransportAteIndividualXml arrayEnvio = montaArrayEnvioDto(fichaMaster, uuid, dadosAteIndividual,
        eehCodigo, remetenteOriginadora);
      zipWriter(arrayEnvio, uuid);
      bdEsusHistoricoItens.registratHistoricoItens(eehCodigo, uuid, 4);
      bdAteIndividual.atualizaStatus(uuid, dadosAteIndividual.getInt("ate_codigo"));
    }
    dadosAteIndividual.close();

  }

  public void zipWriter(DadoTransporteTransportAteIndividualXml xmlText, String uuid)
    throws JAXBException, IOException {
    // Define nome do arquivo
    String arquivo = uuid + ".esus.xml";
    br.ufsc.esus.dadotransporte.ObjectFactoryAteIndividual factoryCadastroIndividual = new br.ufsc.esus.dadotransporte.ObjectFactoryAteIndividual();

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

  }

  public FichaAtendimentoIndividualMasterTransport fichaAtendimentoIndividualMasterThrift(String uuid, ResultSet row)
    throws SQLException {

    VariasLotacoesHeaderTransport variasLotacoes = variasLotacoes(row);
    FichaAtendimentoIndividualChildTransport atendimentosIndividuais = fichaAtendimentoIndividualChildThrift(row);
    FichaAtendimentoIndividualMasterTransport fichaMaster = new FichaAtendimentoIndividualMasterTransport();
    fichaMaster.setUuidFicha(uuid);
    fichaMaster.getAtendimentosIndividuais().add(atendimentosIndividuais);
    fichaMaster.setHeaderTransport(variasLotacoes);
    fichaMaster.setTpCdsOrigem(3);

    return fichaMaster;
  }

  public VariasLotacoesHeaderTransport variasLotacoes(ResultSet row) throws SQLException {
    LotacaoHeaderTransport headerTransport = new LotacaoHeaderTransport();

    headerTransport.setCboCodigo2002(row.getString("eai_cbo_codigo_2002"));
    headerTransport.setCnes(StringUtils.leftPad(row.getString("eai_cnes"), 7, "0"));
    headerTransport.setProfissionalCNS((validaCnsBanco((row.getString("eai_profissional_cns")).trim()) ?
      (row.getString("eai_profissional_cns")).trim() :
      null));
    headerTransport.setIne(row.getString("nu_ine"));

    VariasLotacoesHeaderTransport variasLotacoes = new VariasLotacoesHeaderTransport();
    variasLotacoes.setCodigoIbgeMunicipio(row.getString("eai_codigo_ibge_mun"));
    variasLotacoes.setDataAtendimento(dateToEpoch(row.getDate("eai_dtatendimento")));
    variasLotacoes.setLotacaoFormPrincipal(headerTransport);

    if (row.getString("eai_compartilhado") != null && row.getString("eai_compartilhado").contains("S")) {
      BancoAtendimentoIndividual bd = new BancoAtendimentoIndividual();
      ResultSet rs = bd.getProfissionalAuxiliar(row.getInt("ate_codigo"));
      if (rs.next()) {
        LotacaoHeaderTransport headerTransportAuxiliar = new LotacaoHeaderTransport();
        headerTransportAuxiliar.setCboCodigo2002(rs.getString("cod_cbo"));
        headerTransportAuxiliar.setCnes(StringUtils.leftPad(rs.getString("uni_cnes"), 7, "0"));
        headerTransportAuxiliar.setProfissionalCNS((validaCnsBanco((rs.getString("cnes_cod_cns")).trim()) ?
          (rs.getString("cnes_cod_cns")).trim() :
          null));
        headerTransportAuxiliar.setIne(rs.getString("nu_ine"));
        variasLotacoes.setLotacaoFormAtendimentoCompartilhado(headerTransportAuxiliar);
      }
    }
    return variasLotacoes;
  }

  public FichaAtendimentoIndividualChildTransport fichaAtendimentoIndividualChildThrift(ResultSet row)
    throws SQLException {
    FichaAtendimentoIndividualChildTransport arrayAtendIndividual = new FichaAtendimentoIndividualChildTransport();
    arrayAtendIndividual.setDataNascimento(dateToEpoch(row.getDate("eai_dtnascimento")));
    arrayAtendIndividual.setLocalDeAtendimento(row.getLong("co_local_atend"));
    arrayAtendIndividual.setTipoAtendimento(row.getLong("eai_tipo_atendimento"));
    arrayAtendIndividual.getNasfs().addAll(getNasfs(row));
    arrayAtendIndividual
      .setRacionalidadeSaude((row.getLong("eai_rac_saude") != 0L ? row.getLong("eai_rac_saude") : null));
    arrayAtendIndividual.setPerimetroCefalico(
      (row.getDouble("eai_perimetro_cefalico") > 0 ? row.getDouble("eai_perimetro_cefalico") : null));
    arrayAtendIndividual
      .setVacinaEmDia(Boolean.TRUE.equals(row.getBoolean("eai_vacinacao_em_dia") ? Boolean.TRUE : null));
    arrayAtendIndividual.setAleitamentoMaterno(
      (row.getLong("eai_aleitamento_materno") != 0L ? row.getLong("eai_aleitamento_materno") : null));
    arrayAtendIndividual
      .setPesoAcompanhamentoNutricional((row.getDouble("eai_peso") > 0 ? row.getDouble("eai_peso") : null));
    arrayAtendIndividual
      .setAlturaAcompanhamentoNutricional((row.getDouble("eai_altura") > 0 ? row.getDouble("eai_altura") : null));
    arrayAtendIndividual
      .setAtencaoDomiciliarModalidade((row.getLong("eai_ate_dom_mod") != 0L ? row.getLong("eai_ate_dom_mod") : null));
    arrayAtendIndividual.setStGravidezPlanejada(
      (row.getString("eai_gravidez_planejada") != null ? row.getBoolean("eai_gravidez_planejada") : null));
    arrayAtendIndividual
      .setDumDaGestante((row.getString("eai_dum") != null ? dateToEpoch(row.getDate("eai_dum")) : null));
    arrayAtendIndividual
      .setNuGestasPrevias((row.getInt("eai_gestas_previas") > 0 ? row.getInt("eai_gestas_previas") : null));
    arrayAtendIndividual.setNuPartos((row.getInt("eai_partos") > 0 ? row.getInt("eai_partos") : null));

    arrayAtendIndividual.setProblemaCondicaoAvaliada(problemaCondicaoAvaliacaoAIThrift(row.getInt("ate_codigo"), row));

    arrayAtendIndividual.setTipoAtendimento(row.getLong("eai_tipo_atendimento"));

    arrayAtendIndividual.getCondutas().addAll(getCondutas(row.getInt("ate_codigo")));

    for (ExameTransport outros : examesThrift(row.getInt("ate_codigo"))) {
      arrayAtendIndividual.getExame().add(outros);
    }

    if ((validaCnsBanco(row.getString("eai_num_cartao_sus")))) {
      arrayAtendIndividual.setCnsCidadao(row.getString("eai_num_cartao_sus"));
    } else if (validaCpf(row.getString("eai_cpf_cidadao"))) {
      arrayAtendIndividual.setCpfCidadao(row.getString("eai_cpf_cidadao"));
    }
    arrayAtendIndividual.setNumeroProntuario(row.getString("eai_numprontuario"));
    arrayAtendIndividual.setSexo(Long.valueOf(row.getString("eai_sexo").replace(" L", "")));
    arrayAtendIndividual.setTurno((row.getLong("turno") != 0L ? row.getLong("turno") : 1L));
    arrayAtendIndividual.setDataHoraInicialAtendimento(
      (row.getString("eai_data_hora_inicial") != null ? dateToEpoch(row.getDate("eai_data_hora_inicial")
      ) : null)
    );
    arrayAtendIndividual.setDataHoraFinalAtendimento(
      (row.getString("eai_data_hora_final") != null ? dateToEpoch(row.getDate("eai_data_hora_final")
      ) : null)
    );

    return arrayAtendIndividual;
  }

  public ProblemaCondicaoAvaliacaoAITransport problemaCondicaoAvaliacaoAIThrift(int ateCodigo, ResultSet rs)
    throws SQLException {
    List<String> dadosCiaps = new ArrayList<>();
    List<String> dadosOutroCiaps = new ArrayList<>();

    getCiaps(ateCodigo, dadosCiaps, dadosOutroCiaps);

    ProblemaCondicaoAvaliacaoAITransport problemaCondicaoAvaliacaoAITransport = new ProblemaCondicaoAvaliacaoAITransport();

    if (dadosOutroCiaps.size() > 1) {
      problemaCondicaoAvaliacaoAITransport.setOutroCiap1(dadosOutroCiaps.get(0));
      problemaCondicaoAvaliacaoAITransport.setOutroCiap2(dadosOutroCiaps.get(1));
    } else {
      if (dadosOutroCiaps.size() == 1) {
        problemaCondicaoAvaliacaoAITransport.setOutroCiap1(dadosOutroCiaps.get(0));
      }
    }
    if (rs.getString("cd10_codigo") != null && rs.getString("cd10_codigo").length() > 0) {
      problemaCondicaoAvaliacaoAITransport.setCid10(rs.getString("cd10_codigo").trim());
    }
    if (rs.getString("cd10_codigos") != null && rs.getString("cd10_codigos").length() > 0) {
      problemaCondicaoAvaliacaoAITransport.setCid102(rs.getString("cd10_codigos").trim());
    }
    problemaCondicaoAvaliacaoAITransport.getCiaps().addAll(dadosCiaps);
    return problemaCondicaoAvaliacaoAITransport;
  }

  public void getCiaps(int ateCodigo, List<String> ciaps, List<String> outrosCiaps) throws SQLException {
    List<String> arrayCiaps = Arrays
      .asList("ABP009", "ABP019", "ABP008", "ABP006", "ABP010", "ABP020", "ABP018", "ABP005",
        "ABP007", "ABP001", "ABP004", "ABP002", "ABP023", "ABP022", "ABP024", "ABP015", "ABP014", "ABP003", "ABP011",
        "ABP017", "ABP012", "ABP013","R96","A77","T91","T90","R95","A78","A78","K86","T82","W78","A98","W18","K22","57",
        "P17","A70","P16","P19");
    BancoAtendimentoIndividual bdAteIndividual = new BancoAtendimentoIndividual();
    ResultSet dadosCiaps = bdAteIndividual.getCiaps(ateCodigo);

    while (dadosCiaps.next()) {
      if (arrayCiaps.contains(dadosCiaps.getString("co_ciap"))) {
        ciaps.add(dadosCiaps.getString("co_ciap"));
      } else {
        outrosCiaps.add(dadosCiaps.getString("co_ciap"));
      }
    }
    dadosCiaps.close();
  }

  public List<Long> getCondutas(int ateCodigo) throws SQLException {
    BancoAtendimentoIndividual bdAteIndividual = new BancoAtendimentoIndividual();
    ResultSet dadosConduta = bdAteIndividual.getCondutas(ateCodigo);
    List<Long> conduta = new ArrayList<>();
    while (dadosConduta.next()) {

      conduta.add(dadosConduta.getLong("co_cds_tipo_conduta"));
    }
    dadosConduta.close();
    return conduta;
  }

  public List<ExameTransport> examesThrift(int ateCodigo) throws SQLException {
    BancoAtendimentoIndividual bdAteIndividual = new BancoAtendimentoIndividual();
    ResultSet dadosProcedimentosSigtap = bdAteIndividual.getExames(ateCodigo);
    List<ExameTransport> arrayGeral = new ArrayList<>();
    while (dadosProcedimentosSigtap.next()) {
      ExameTransport ost = new ExameTransport();
      ost.setCodigoExame(dadosProcedimentosSigtap.getString("proc_codigo_sus"));
      if (dadosProcedimentosSigtap.getString("proc_solicitado") != null
        && dadosProcedimentosSigtap.getString("proc_solicitado").equals("S")) {
        ost.getSolicitadoAvaliado().add(dadosProcedimentosSigtap.getString("proc_solicitado"));
      }
      if (dadosProcedimentosSigtap.getString("proc_avaliado") != null
        && dadosProcedimentosSigtap.getString("proc_avaliado").equals("A")) {
        ost.getSolicitadoAvaliado().add(dadosProcedimentosSigtap.getString("proc_avaliado"));
      }
      arrayGeral.add(ost);
    }
    dadosProcedimentosSigtap.close();
    return arrayGeral;
  }

  public DadoTransporteTransportAteIndividualXml montaArrayEnvioDto(
    FichaAtendimentoIndividualMasterTransport 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);

    DadoTransporteTransportAteIndividualXml dadoTransporteTransportXml = new DadoTransporteTransportAteIndividualXml();
    dadoTransporteTransportXml.setUuidDadoSerializado(uuid);
    dadoTransporteTransportXml.setTipoDadoSerializado(TipoDadoSerializado.ATENDIMENTOINDIVIDUAL.getValue());
    dadoTransporteTransportXml.setCnesDadoSerializado(StringUtils.leftPad(row.getString("eai_cnes"), 7, "0"));
    dadoTransporteTransportXml.setCodIbge(row.getString("eai_codigo_ibge_mun"));
    dadoTransporteTransportXml.setNumLote(eehCodigo);
    dadoTransporteTransportXml.setIneDadoSerializado(row.getString("nu_ine"));
    dadoTransporteTransportXml.setRemetente(remetenteOriginadora);
    dadoTransporteTransportXml.setOriginadora(remetenteOriginadora);
    dadoTransporteTransportXml.setVersao(arrayVersao);
    dadoTransporteTransportXml.setFichaAtendimentoIndividualMasterTransport(fichaMasterSerializado);
    return dadoTransporteTransportXml;
  }

  public List<Long> getNasfs(ResultSet rs) throws SQLException {

    List<Long> lista = new ArrayList<>();

    if (rs.getBoolean("ate_nasf_aval")) {
      lista.add(1L);
    }
    if (rs.getBoolean("ate_nasf_proc")) {
      lista.add(2L);
    }
    if (rs.getBoolean("ate_nasf_presc")) {
      lista.add(3L);
    }

    return lista;
  }

}
