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.BancoAvaliacaoElegibilidadeAdmissao;
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.DadoTransporteTransportAvaliacaoElegibilidadeXml;
import br.ufsc.esus.dadotransporte.ObjectFactoryAvaliacaoElegibilidade;
import br.ufsc.esus.enderecolocalpermanencia.EnderecoLocalPermanenciaTransport;
import br.ufsc.esus.fichaavaliacaoelegibilidade.FichaAvaliacaoElegibilidadeTransport;
import br.ufsc.esus.lotacaoheader.LotacaoHeaderTransport;
import br.ufsc.esus.variaslotacoesheader.VariasLotacoesHeaderTransport;
import br.ufsc.esus.versao.VersaoTransport;

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;
import static br.com.elotech.websaude.integracao.esus.util.Util.emptyWhenNull;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.leftPad;
import static org.apache.commons.lang3.StringUtils.trimToNull;

public class AvaliacaoElegibilidadeAdmissao extends BD {

  BancoAvaliacaoElegibilidadeAdmissao bdAvaliacaoElegibilidade = new BancoAvaliacaoElegibilidadeAdmissao();
  private String ineProfissionalPrincipal;

  public void executeMain(int eehCodigo, DadoInstalacaoTransport remetenteOriginadora)
    throws SQLException, JAXBException, IOException {

    EsusHistoricoItens bdEsusHistoricoItens = new EsusHistoricoItens();
    ResultSet dadosAvaliacaoElegibilidade = bdAvaliacaoElegibilidade.getDados();

    while (dadosAvaliacaoElegibilidade.next()) {
      String uuid = getGUID();
      FichaAvaliacaoElegibilidadeTransport transport = gerarFichaAvaliacaoElegibilidadeTransport(uuid,
        dadosAvaliacaoElegibilidade);
      DadoTransporteTransportAvaliacaoElegibilidadeXml arrayEnvio = montaArrayEnvioDto(transport, uuid,
        dadosAvaliacaoElegibilidade, eehCodigo, remetenteOriginadora);
      zipWriter(arrayEnvio, uuid);
      bdEsusHistoricoItens.registratHistoricoItens(eehCodigo, uuid, 11);
      bdAvaliacaoElegibilidade.atualizaStatus(uuid, dadosAvaliacaoElegibilidade.getInt("ae_codigo"));
    }
    dadosAvaliacaoElegibilidade.close();

  }

  private void zipWriter(DadoTransporteTransportAvaliacaoElegibilidadeXml xml, String uuid)
    throws JAXBException, IOException {
    String arquivo = uuid + ".esus.xml";
    ObjectFactoryAvaliacaoElegibilidade factoryAvaliacaoElegibilidade = new ObjectFactoryAvaliacaoElegibilidade();
    JAXBContext context = JAXBContext.newInstance(ObjectFactoryAvaliacaoElegibilidade.class);
    JAXBElement<DadoTransporteTransportAvaliacaoElegibilidadeXml> element = factoryAvaliacaoElegibilidade
      .createDadoTransporteTransportAvaliacaoElegibilidadeXml(xml);
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
    marshaller.marshal(element, new FileWriter("arqs/" + arquivo));
    Compactador.ARQUIVOS.add(arquivo);
  }

  public DadoTransporteTransportAvaliacaoElegibilidadeXml montaArrayEnvioDto(
    FichaAvaliacaoElegibilidadeTransport transport, String uuid, ResultSet dadosAvaliacao, int eehCodigo,
    DadoInstalacaoTransport remetenteOriginadora) throws SQLException {

    VersaoTransport versaoTransport = new VersaoTransport(3, 2, 4);

    DadoTransporteTransportAvaliacaoElegibilidadeXml dadoTransporteTransportXml = new DadoTransporteTransportAvaliacaoElegibilidadeXml();
    dadoTransporteTransportXml.setUuidDadoSerializado(uuid);
    dadoTransporteTransportXml.setTipoDadoSerializado(TipoDadoSerializado.AVALIACAOELEGIBILIDADE.getValue());
    dadoTransporteTransportXml.setCnesDadoSerializado(leftPad(dadosAvaliacao.getString("cnes"), 7, "0"));
    dadoTransporteTransportXml.setCodIbge(dadosAvaliacao.getString("ibge_unidade"));
    dadoTransporteTransportXml.setNumLote(eehCodigo);
    dadoTransporteTransportXml.setIneDadoSerializado(ineProfissionalPrincipal);
    dadoTransporteTransportXml.setRemetente(remetenteOriginadora);
    dadoTransporteTransportXml.setOriginadora(remetenteOriginadora);
    dadoTransporteTransportXml.setVersao(versaoTransport);
    dadoTransporteTransportXml.setFichaAvaliacaoElegibilidadeTransport(transport);
    return dadoTransporteTransportXml;
  }

  private FichaAvaliacaoElegibilidadeTransport gerarFichaAvaliacaoElegibilidadeTransport(String uuid, ResultSet row)
    throws SQLException {
    FichaAvaliacaoElegibilidadeTransport fichaTransport = new FichaAvaliacaoElegibilidadeTransport();
    fichaTransport.setUuidFicha(uuid);
    fichaTransport.setTpCdsOrigem(3);
    Long aeCodigo = row.getLong("ae_codigo");
    Long usuCodigo = row.getLong("usu_codigo");

    resolveCpfCnsCidadao(row, fichaTransport);

    fichaTransport.setNomeCidadao(row.getString("nome_cidadao"));
    fichaTransport.setNomeSocialCidadao(emptyWhenNull(row.getString("nome_social_cidadao")));
    fichaTransport.setDataNascimentoCidadao(dateToEpoch(row.getDate("data_nascimento_cidadao")));
    fichaTransport.setSexoCidadao(retornaSexo(row.getString("sexo_cidadao")));
    fichaTransport.setRacaCorCidadao(row.getLong("raca_cidadao"));

    resolveNomeMae(row, fichaTransport);
    resolveNomePai(row, fichaTransport);
    resolveNacionalidade(row, fichaTransport);

    fichaTransport.setEmailCidadao(row.getString("email_cidadao"));
    fichaTransport.setNumeroNisPisPasep(row.getString("pis_pasep_cidadao"));

    fichaTransport.setAtencaoDomiciliarProcedencia(row.getLong("procedencia"));
    fichaTransport.setAtencaoDomiciliarModalidade(row.getLong("modalidade"));
    fichaTransport.setCondicoesAvaliadas(gerarCondicoesAvaliadas(aeCodigo));

    resolveConclusoesElegiveisInelegiveis(fichaTransport, aeCodigo);
    gerarEnderecoLocalPermanenciaTransport(fichaTransport, usuCodigo);

    fichaTransport.setCid10Principal(trimToNull(row.getString("cid10")));
    fichaTransport.setCid10SecundarioUm(trimToNull(row.getString("cid10s")));
    fichaTransport.setCid10SecundarioDois(trimToNull(row.getString("cid10t")));

    fichaTransport.setCuidadorCidadao(row.getLong("cuidador_cidadao"));
    fichaTransport.setTurno(row.getLong("ae_turno"));
    fichaTransport.setHeaderTransport(gerarVariasLotacoesHeaderTransport(row));

    resolveEtniaCidadao(row, fichaTransport);
    resolveCpfCnsCidadaoCuidador(row, fichaTransport);

    return fichaTransport;
  }

  private void resolveEtniaCidadao(ResultSet row, FichaAvaliacaoElegibilidadeTransport fichaTransport)
    throws SQLException {
    if (fichaTransport.getRacaCorCidadao() == 5) {
      fichaTransport.setEtnia(row.getLong("codigo_etnia_cidadao"));
    }
  }

  private void resolveCpfCnsCidadao(ResultSet row, FichaAvaliacaoElegibilidadeTransport fichaTransport)
    throws SQLException {
    if (isNotBlank(row.getString("cartao_sus_cidadao"))) {
      fichaTransport.setCnsCidadao(row.getString("cartao_sus_cidadao"));
    } else {
      fichaTransport.setCpfCidadao(row.getString("cpf_cidadao"));
    }
  }

  private void resolveCpfCnsCidadaoCuidador(ResultSet row, FichaAvaliacaoElegibilidadeTransport fichaTransport)
    throws SQLException {
    if (fichaTransport.getCuidadorCidadao() != 1) {
      if (isNotBlank(row.getString("cartao_sus_cuidador"))) {
        fichaTransport.setCnsCuidador(row.getString("cartao_sus_cuidador"));
      } else {
        fichaTransport.setCpfCuidador(row.getString("cpf_cuidador"));
      }
    }
  }

  private void resolveConclusoesElegiveisInelegiveis(FichaAvaliacaoElegibilidadeTransport fichaTransport,
    Long aeCodigo) throws SQLException {
    if (fichaTransport.getAtencaoDomiciliarModalidade() != 4) { // CONCLUSÕES ELEGÍVEIS
      ResultSet rsConclusaoElegivel = bdAvaliacaoElegibilidade.getConclusoesDestino(aeCodigo);
      if (rsConclusaoElegivel.next()) {
        fichaTransport.setConclusaoDestinoElegivel(rsConclusaoElegivel.getLong("codigo"));
      }
      rsConclusaoElegivel.close();
    } else { // CONCLUSÃO INELEGÍVEL
      ResultSet rsConclusaoInelegivel = bdAvaliacaoElegibilidade.getConclusoesDestino(aeCodigo);
      List<Long> conclusoesInelegiveis = new ArrayList<>();
      while (rsConclusaoInelegivel.next()) {
        conclusoesInelegiveis.add(rsConclusaoInelegivel.getLong("codigo"));
      }
      rsConclusaoInelegivel.close();
      fichaTransport.setConclusaoDestinoInelegivel(conclusoesInelegiveis);
    }
  }

  private void resolveNacionalidade(ResultSet row, FichaAvaliacaoElegibilidadeTransport fichaTransport)
    throws SQLException {
    Long nacionalidade = retornaNacionalidade(row.getString("nacionalidade_cidadao"));
    fichaTransport.setNacionalidadeCidadao(nacionalidade);
    if (nacionalidade != null) {
      if (nacionalidade == 1) {
        fichaTransport.setCodigoIbgeMunicipioNascimento(row.getString("codigo_ibge_cidadao"));
        fichaTransport.setPaisNascimento(31L);
      } else if (nacionalidade == 2) {
        fichaTransport.setDtNaturalizacao(dateToEpoch(row.getDate("data_naturalizacao_cidadao")));
        fichaTransport
          .setPortariaNaturalizacao(row.getString("portaria_naturalizacao_cidadao").replaceAll("[^a-zA-Z0-9]+", ""));
      } else if (nacionalidade == 3) {
        fichaTransport.setDtEntradaBrasil(dateToEpoch(row.getDate("data_entrada_pais_cidadao")));
        fichaTransport.setPaisNascimento(row.getLong("codigo_pais_cidadao"));
      }
    }
  }

  private void resolveNomePai(ResultSet row, FichaAvaliacaoElegibilidadeTransport fichaTransport)
    throws SQLException {
    if (isBlank(row.getString("nome_pai_cidadao"))) {
      fichaTransport.setDesconheceNomePai(true);
    } else {
      fichaTransport.setNomePaiCidadao(row.getString("nome_pai_cidadao"));
    }
  }

  private void resolveNomeMae(ResultSet row, FichaAvaliacaoElegibilidadeTransport fichaTransport)
    throws SQLException {
    if (isBlank(row.getString("nome_mae_cidadao"))) {
      fichaTransport.setDesconheceNomeMae(true);
    } else {
      fichaTransport.setNomeMaeCidadao(row.getString("nome_mae_cidadao"));
    }
  }

  private void gerarEnderecoLocalPermanenciaTransport(FichaAvaliacaoElegibilidadeTransport fichaTransport,
    Long usuCodigo) throws SQLException {
    if (fichaTransport.getAtencaoDomiciliarModalidade() != 4 && fichaTransport.getConclusaoDestinoElegivel() != null) {
      EnderecoLocalPermanenciaTransport enderecoTransport = new EnderecoLocalPermanenciaTransport();
      ResultSet rsEndereco = bdAvaliacaoElegibilidade.getEnderecoLocalPermanencia(usuCodigo);
      if (rsEndereco.next()) {
        enderecoTransport.setBairro(rsEndereco.getString("bairro"));
        enderecoTransport.setCep(rsEndereco.getString("cep").replace("-", ""));
        enderecoTransport.setCodigoIbgeMunicipio(rsEndereco.getString("codigoIbgeMunicipio"));
        enderecoTransport.setComplemento(rsEndereco.getString("complemento"));
        enderecoTransport.setNomeLogradouro(rsEndereco.getString("nomeLogradouro"));
        enderecoTransport.setNumero(rsEndereco.getString("numero"));
        enderecoTransport.setNumeroDneUf(rsEndereco.getString("numeroDneUf"));
        enderecoTransport.setTelefoneContato(rsEndereco.getString("telefoneContato"));
        enderecoTransport.setTelefoneResidencia(rsEndereco.getString("telefoneResidencia"));
        enderecoTransport.setTipoLogradouroNumeroDne(rsEndereco.getString("tipoLogradouroNumeroDne"));
        enderecoTransport.setStSemNumero(isBlank(enderecoTransport.getNumero()));
        enderecoTransport.setPontoReferencia(rsEndereco.getString("pontoReferencia"));
        fichaTransport.setEndereco(enderecoTransport);
      }
      rsEndereco.close();
    }
  }

  private List<Long> gerarCondicoesAvaliadas(Long aeCodigo) throws SQLException {
    ResultSet rsCondicoesAvaliadas = bdAvaliacaoElegibilidade.getCondicoesAvaliadas(aeCodigo);
    List<Long> condicoesAvaliadas = new ArrayList<>();
    while (rsCondicoesAvaliadas.next()) {
      condicoesAvaliadas.add(rsCondicoesAvaliadas.getLong("codigo"));
    }
    rsCondicoesAvaliadas.close();
    return condicoesAvaliadas;
  }

  private VariasLotacoesHeaderTransport gerarVariasLotacoesHeaderTransport(ResultSet rs) throws SQLException {
    VariasLotacoesHeaderTransport headerTransport = new VariasLotacoesHeaderTransport();

    headerTransport.setLotacaoFormPrincipal(gerarLotacaoFormPrincipal(rs));
    if (rs.getString("ae_compartilhado").equalsIgnoreCase("S")) {
      headerTransport.setLotacaoFormAtendimentoCompartilhado(gerarLotacaoFormAtendimentoCompartilhado(rs));
    }

    headerTransport.setDataAtendimento(dateToEpoch(rs.getDate("ae_data")));
    headerTransport.setCodigoIbgeMunicipio(rs.getString("ibge_unidade"));

    return headerTransport;
  }

  private LotacaoHeaderTransport gerarLotacaoFormPrincipal(ResultSet rs) throws SQLException {
    LotacaoHeaderTransport lotacaoHeaderTransport = new LotacaoHeaderTransport();

    ResultSet rsProfissional = bdAvaliacaoElegibilidade.getProfissionalPrincipal(rs.getLong("ae_codigo"));
    if (rsProfissional.next()) {
      lotacaoHeaderTransport.setProfissionalCNS(rsProfissional.getString("cnes_cod_cns"));
      lotacaoHeaderTransport.setCboCodigo2002(rsProfissional.getString("cod_cbo"));
      lotacaoHeaderTransport.setCnes(rsProfissional.getString("uni_cnes"));
      lotacaoHeaderTransport.setIne(rsProfissional.getString("nu_ine"));
      ineProfissionalPrincipal = rsProfissional.getString("nu_ine");
    }
    rsProfissional.close();
    return lotacaoHeaderTransport;
  }

  private LotacaoHeaderTransport gerarLotacaoFormAtendimentoCompartilhado(ResultSet rs) throws SQLException {
    LotacaoHeaderTransport lotacaoHeaderTransport = new LotacaoHeaderTransport();

    ResultSet rsProfissional = bdAvaliacaoElegibilidade.getProfissionalAuxiliar(rs.getLong("ae_codigo"));
    if (rsProfissional.next()) {
      lotacaoHeaderTransport.setProfissionalCNS(rsProfissional.getString("cnes_cod_cns"));
      lotacaoHeaderTransport.setCboCodigo2002(rsProfissional.getString("cod_cbo"));
      lotacaoHeaderTransport.setCnes(rsProfissional.getString("uni_cnes"));
      lotacaoHeaderTransport.setIne(rsProfissional.getString("nu_ine"));
    }
    rsProfissional.close();
    return lotacaoHeaderTransport;
  }

  private long retornaSexo(String sexo) {
    if (isBlank(sexo)) {
      return 4;
    }
    return sexo.equalsIgnoreCase("M") ? 0 : 1;
  }

  private Long retornaNacionalidade(String nacionalidade) {
    if (nacionalidade != null) {
      switch (nacionalidade) {
      case "B":
        return 1L;
      case "N":
        return 2L;
      case "E":
        return 3L;
      }
    }
    return null;
  }
}
