package br.com.elotech.saude.scripts;

import br.com.elotech.Main;
import br.com.elotech.enuns.TipoRelEnum;
import br.com.elotech.saude.model.filters.agendamento.AgendamentoExternoMedicoFilter;
import br.com.elotech.saude.model.filters.agendamento.AgendamentoExternoUnidadeFilter;
import br.com.elotech.saude.model.filters.agendamento.AgendamentoPorProfissionalFilter;
import br.com.elotech.saude.model.filters.agendamento.AgendamentoPorUnidadeFilter;
import br.com.elotech.saude.model.filters.agendamento.ConsultasAgendadasFilter;

public abstract class AgendamentoScript {

    private static StringBuilder sb;

    //Agendamento por unidade
    public static String getSqlAgendamentoPorUnidade(AgendamentoPorUnidadeFilter filter){

        sb = new StringBuilder();
        if(filter.getTpRel().equals(TipoRelEnum.SINTETICO)){
            sb.append("SELECT uni.uni_desc AS unidade,")
              .append("       COUNT(age.age_codigo) AS quantidade")
              .append("  FROM unidade AS uni")
              .append("  JOIN agendamento AS age ON age.uni_codigo=uni.uni_codigo AND age.age_atendido='N'")
              .append("  JOIN usuarios AS usr ON usr.usr_codigo=age.med_codigo")
              .append("  JOIN usuario AS usu ON usu.usu_codigo=age.usu_codigo")
              .append(" WHERE age.age_data BETWEEN :dt_inicial AND :dt_final")
              .append(" AND CASE ")
              .append("         WHEN 1=(SELECT 1 FROM usuarios where usr_acesso_unidades = 'S' and usr_codigo = "+Main.usrLogado+") THEN 1 = 1")
              .append("         ELSE uni.uni_codigo IN (SELECT unu.uni_codigo FROM unidade_usuarios unu WHERE unu.usr_codigo = "+Main.usrLogado+") END");
            if(filter.getUnidade() != null){
                sb.append(" AND uni.uni_codigo = :uni_codigo");
            }
            sb.append(" GROUP BY uni.uni_codigo, uni.uni_desc")
              .append(" ORDER BY uni.uni_desc");
        }else{
            sb.append(" SELECT uni.uni_desc AS unidade,")
              .append("        usr.usr_nome AS medico,")
              .append("        usu.usu_nome AS paciente,")
              .append("        usu.usu_fone AS telefone,")
              .append("        TO_CHAR(age.age_data,'dd/MM/YYYY') AS data,")
              .append("        age_horario AS hora")
              .append("  FROM unidade AS uni")
              .append("  JOIN agendamento AS age ON age.uni_codigo=uni.uni_codigo AND age.age_atendido='N'")
              .append("  JOIN usuarios    AS usr ON usr.usr_codigo=age.med_codigo")
              .append("  JOIN usuario     AS usu ON usu.usu_codigo=age.usu_codigo")
              .append(" WHERE age.age_data BETWEEN :dt_inicial AND :dt_final")
              .append(" AND CASE ")
              .append("         WHEN 1=(SELECT 1 FROM usuarios where usr_acesso_unidades = 'S' and usr_codigo = "+Main.usrLogado+") THEN 1 = 1")
              .append("         ELSE uni.uni_codigo IN (SELECT unu.uni_codigo FROM unidade_usuarios unu WHERE unu.usr_codigo = "+Main.usrLogado+") END");
            if(filter.getUnidade() != null){
                sb.append(" AND uni.uni_codigo = :uni_codigo");
            }
            sb.append(" GROUP BY uni.uni_codigo, uni.uni_desc,")
              .append("          usr.usr_nome, age.age_data,")
              .append("          usu.usu_nome, usu.usu_fone, age_horario")
              .append(" ORDER BY uni.uni_desc, usr.usr_nome, age.age_data, usu.usu_nome");
        }
        return sb.toString();
    }

    //Agendamento por médico

    public static String getSqlAgendamentoPorProfissionalSintetico(AgendamentoPorProfissionalFilter filter) {
        sb = new StringBuilder();

        sb.append(" SELECT")
          .append("     uni.uni_desc          AS unidade,")
          .append("     usr.usr_nome          AS profissional,")
          .append("     COUNT(CASE WHEN age.age_atendido = 'N' then 1 END) AS qtd_agendado,")
          .append("     COUNT(CASE WHEN age.age_atendido = 'A' then 1 END) AS qtd_atendido,")
          .append("     COUNT(CASE WHEN age.age_atendido = 'F' then 1 END) AS qtd_faltoso,")
          .append("     COUNT(CASE WHEN age.age_atendido = 'M' then 1 END) AS qtd_falta_medica,")
          .append("     COUNT(CASE WHEN age.age_atendido not in ('N','A', 'F', 'M' ) then 1 END) AS qtd_outros,")
          .append("     COUNT(age.age_codigo) AS qtd_total")
          .append("   FROM agendamento age")
          .append("   JOIN usuarios usr ON age.med_codigo = usr.usr_codigo")
          .append("   JOIN usuario usu ON age.usu_codigo = usu.usu_codigo")
          .append("   JOIN unidade uni ON age.uni_codigo = uni.uni_codigo")
          .append(" WHERE age.coni_codigo IS NOT NULL AND age.age_data BETWEEN :dt_inicial AND :dt_final")
          .append(" AND CASE ")
          .append("         WHEN 1=(SELECT 1 FROM usuarios where usr_acesso_unidades = 'S' and usr_codigo = "+Main.usrLogado+") THEN 1 = 1")
          .append("         ELSE uni.uni_codigo IN (SELECT unu.uni_codigo FROM unidade_usuarios unu WHERE unu.usr_codigo = "+Main.usrLogado+") END");
          if(filter.getUnidade() != null){
              sb.append(" AND uni.uni_codigo = :uni_codigo");
          }
          if(filter.getProfissional() != null){
              sb.append(" AND usr.usr_codigo = :usr_codigo");
          }
        sb.append("  GROUP BY uni.uni_desc, usr.usr_nome")
          .append("  ORDER BY uni.uni_desc, usr.usr_nome");
        return sb.toString();
    }

    public static String getSqlAgendamentoPorProfissionalAnalitico(AgendamentoPorProfissionalFilter filter) {
        sb = new StringBuilder();
        sb.append(" SELECT")
          .append("     uni.uni_desc      AS unidade,")
          .append("     usr.usr_nome      AS profissional,")
          .append("     usu.usu_nome      AS cidadao,")
          .append("     usu.usu_datanasc  AS dt_nascimento,")
          .append("     EXTRACT(YEAR FROM AGE(usu.usu_datanasc))  AS idade,")
          .append("     COALESCE(usu.usu_cartao_sus, 'Não informado') AS cartao_sus,")
          .append("     age.age_data      AS dt_agendamento,")
          .append("     age.age_horario   AS hr_agendamento,")
          .append("     CASE age.age_atendido")
          .append("        WHEN 'N' THEN 'AGENDADO'")
          .append("        WHEN 'A' THEN 'ATENDIDO'")
          .append("        WHEN 'F' THEN 'FALTOSO'")
          .append("        WHEN 'M' THEN 'FALTA MÉDICA'")
          .append("        ELSE 'OUTROS'")
          .append("      END AS status,")
          .append("     age.age_transferido")
          .append("   FROM agendamento age")
          .append("   JOIN usuarios usr ON age.med_codigo = usr.usr_codigo")
          .append("   JOIN usuario usu ON age.usu_codigo = usu.usu_codigo")
          .append("   JOIN unidade uni ON age.uni_codigo = uni.uni_codigo")
          .append(" WHERE age.coni_codigo IS NOT NULL AND age.age_data BETWEEN :dt_inicial AND :dt_final")
          .append(" AND CASE ")
          .append("         WHEN 1=(SELECT 1 FROM usuarios where usr_acesso_unidades = 'S' and usr_codigo = "+Main.usrLogado+") THEN 1 = 1")
          .append("         ELSE uni.uni_codigo IN (SELECT unu.uni_codigo FROM unidade_usuarios unu WHERE unu.usr_codigo = "+Main.usrLogado+") END");
        if(filter.getUnidade() != null){
            sb.append(" AND uni.uni_codigo = :uni_codigo");
        }
        if(filter.getProfissional() != null){
            sb.append(" AND usr.usr_codigo = :usr_codigo");
        }
        if(filter.getSituacao() != null){
            sb.append(" AND age.age_atendido = :age_atendido");
        }
        sb.append("  ORDER BY uni.uni_desc, usr.usr_nome, age.age_data, ")
          .append("         CASE age.age_atendido")
          .append("             WHEN 'N' THEN 1")
          .append("             WHEN 'A' THEN 2")
          .append("             WHEN 'F' THEN 3")
          .append("             WHEN 'M' THEN 4")
          .append("             ELSE 5")
          .append("          END, usu.usu_nome");
        return sb.toString();
    }

    public static String getSqlConsultasAgendadas(ConsultasAgendadasFilter filter) {
        sb = new StringBuilder();
        sb.append(" SELECT")
                .append("     uni.uni_desc          AS unidade,")
                .append("     usr.usr_nome          AS profissional,")
                .append("     usu.usu_nome          AS cidadao,")
                .append("     usu.usu_datanasc      AS dt_nascimento,")
                .append("     usu.usu_prontuario    AS prontuario,")
                .append("     usu.usu_fone          AS telefone,")
                .append("     usu.usu_celular       AS celular,")
                .append("     age.age_data          AS dt_agendamento,")
                .append("     age.age_horario       AS hr_agendamento")
                .append("   FROM agendamento age")
                .append("   JOIN usuarios usr ON age.med_codigo = usr.usr_codigo")
                .append("   JOIN usuario usu ON age.usu_codigo = usu.usu_codigo")
                .append("   JOIN unidade uni ON age.uni_codigo = uni.uni_codigo")
                .append(" WHERE age.coni_codigo IS NOT NULL AND age.age_data BETWEEN :dt_inicial AND :dt_final")
                .append(" AND CASE ")
                .append("         WHEN 1=(SELECT 1 FROM usuarios where usr_acesso_unidades = 'S' and usr_codigo = "+Main.usrLogado+") THEN 1 = 1")
                .append("         ELSE uni.uni_codigo IN (SELECT unu.uni_codigo FROM unidade_usuarios unu WHERE unu.usr_codigo = "+Main.usrLogado+") END");
        if(filter.getUnidade() != null){
            sb.append(" AND uni.uni_codigo = :uni_codigo");
        }
        if(filter.getProfissional() != null){
            sb.append(" AND usr.usr_codigo = :usr_codigo");
        }

        sb.append("  ORDER BY uni.uni_desc, usr.usr_nome, age.age_data, age.age_horario");

        return sb.toString();
    }

    public static String getSqlAgendamentoExternoMedico(AgendamentoExternoMedicoFilter filter){
        sb = new StringBuilder();
        sb.append(" SELECT ")
          .append(" uni.uni_desc      AS unidade, ")
          .append(" coalesce(esp.esp_nome, 'NÃO INFORMADO') AS especialidade, ")
          .append(" CASE agee_situacao ")
          .append(" WHEN '1' THEN 'AGENDADO' ")
          .append(" WHEN '2' THEN 'CANCELADO' ")
          .append(" WHEN '3' THEN 'ENTREGUE' ")
          .append(" WHEN '4' THEN 'ESPERA' ")
          .append(" WHEN '5' THEN 'FALTA' ")
          .append(" WHEN '6' THEN 'NÃO LOCALIZADO PACIENTE' ")
          .append(" ELSE 'NÃO INFORMADO' ")
          .append(" END               AS situacao, ")
          .append(" coalesce(newmed.med_nome, 'NÃO INFORMADO') AS medico_destino, ")
          .append(" coalesce(usr.usr_nome, 'NÃO INFORMADO') AS medico_solicitante, ")
          .append(" CASE agee.grau_risco ")
          .append(" WHEN 'B' THEN 'BAIXA' ")
          .append(" WHEN 'M' THEN 'MÉDIA' ")
          .append(" WHEN 'A' THEN 'ALTA' ")
          .append(" ELSE 'NÃO INFORMADA' ")
          .append(" END  AS prioridade, ");
        if(filter.getTpRel().equals(TipoRelEnum.SINTETICO)){
          sb.append(" count(agee.usu_codigo) as total ");
        } else{
          sb.append(" agee.agee_data                       AS data,")
            .append(" usu.usu_nome                         AS paciente,")
            .append(" usu.usu_fone                         AS telefone,")
            .append(" usu.usu_celular                      AS celular");
        }
        sb.append(" FROM agendamento_externo agee ")
          .append(" JOIN unidade AS uni ON agee.uni_codigo = uni.uni_codigo ")
          .append(" LEFT JOIN especialidade AS esp ON esp.esp_codigo = agee.esp_codigo ")
          .append(" LEFT JOIN medico AS newmed ON newmed.med_codigo = agee.med_codigo ")
          .append(" LEFT JOIN medico AS prestador ON prestador.med_codigo = agee.med_codigo_prestador ")
          .append(" LEFT JOIN usuarios AS usr ON usr.usr_codigo = agee.usr_codigo_solicitante ")
          .append(" JOIN usuario AS usu ON usu.usu_codigo = agee.usu_codigo")
          .append("  LEFT JOIN domicilio                 AS dom   ON usu.dom_codigo = dom.dom_codigo OR usu.usu_codigo = dom.usu_codigo_responsavel ")
          .append("  LEFT JOIN rua                       AS rua   ON dom.rua_codigo = rua.rua_codigo ")
          .append("  LEFT JOIN tb_ms_tipo_logradouro     AS tplog ON rua.co_tipo_logradouro = tplog.co_tipo_logradouro ")
          .append("  LEFT JOIN bairro                    AS bai   ON rua.bai_codigo = bai.bai_codigo ")
          .append("  LEFT JOIN cidade                    AS cid   ON bai.cid_codigo = cid.cid_codigo ")
          .append(" WHERE agee.agee_data BETWEEN :dtInicial AND :dtFinal");
        if(filter.getUnidade()!=null){
            sb.append(" AND agee.uni_codigo = :unidade");
        }
        if(filter.getEspecialidade()!= null){
            sb.append(" AND agee.esp_codigo =:especialidade");
        }
        if(filter.getMedicoSolicitante()!= null){
            sb.append(" AND agee.med_codigo_solicitante =:medicoSolicitante");
        }
        if(filter.getMedicoDestino()!=null){
            sb.append(" AND agee.med_codigo =:medicoDestino");
        }
        if (filter.getPrestador() != null) {
            sb.append(" AND agee.med_codigo_prestador =:prestador");
        }
        if(filter.getSituacao()!= null){
            sb.append(" AND agee.agee_situacao =:situacao");
        }
        if(filter.getGrauRisco()!= null){
            sb.append(" AND agee.grau_risco =:grauRisco");
        }
        if(filter.getTpRel().equals(TipoRelEnum.SINTETICO)){
            sb.append(" GROUP BY uni.uni_codigo, agee_situacao,esp.esp_nome, newmed.med_nome,usr.usr_nome,grau_risco");
            sb.append(" ORDER BY uni.uni_codigo,agee_situacao, usr.usr_nome, newmed.med_nome, esp.esp_nome, grau_risco");
        } else{
            sb.append(" ORDER BY uni.uni_codigo,agee_situacao, usr.usr_nome, newmed.med_nome, esp.esp_nome, usu.usu_nome, agee.agee_data, usu.usu_nome");
        }

        return sb.toString();
    }

    public static String getSqlAgendamentoExternoUnidade (AgendamentoExternoUnidadeFilter filter){
      sb = new StringBuilder();
      sb.append("  SELECT")
        .append("  uni.uni_desc                         AS unidade,")
        .append("    esp.esp_nome                         AS especialidade,")
        .append("  CASE agee_situacao")
        .append(" WHEN '1' THEN 'AGENDADO'")
        .append(" WHEN '2' THEN 'CANCELADO'")
        .append(" WHEN '3' THEN 'ENTREGUE'")
        .append(" WHEN '4' THEN 'ESPERA'")
        .append(" WHEN '5' THEN 'FALTA'")
        .append(" WHEN '6' THEN 'NÃO LOCALIZADO PACIENTE'")
        .append(" ELSE 'NÃO INFORMADO'")
        .append("  END AS situacao,")
        .append("    proc.proc_nome                       AS procedimento,")
        .append("  newmed.med_nome                      AS medico_destino,")
        .append("    CASE agee.grau_risco")
        .append(" WHEN 'B' THEN 'BAIXA'")
        .append(" WHEN 'M' THEN 'MÉDIA'")
        .append(" WHEN 'A' THEN 'ALTA'")
        .append(" ELSE 'NÃO INFORMADA'")
        .append("  END                    AS prioridade,");
      if(filter.getTpRel().equals(TipoRelEnum.SINTETICO)){
        sb.append("    count(agee.usu_codigo)   AS total");
      } else{
        sb.append(" agee.agee_data              AS data,")
          .append(" usu.usu_nome                AS paciente,")
          .append(" usu.usu_fone                AS telefone,")
          .append(" usu.usu_celular             AS celular,")
          .append(" usu.usu_cartao_sus          AS cns,")
          .append(" tplog.ds_tipo_logradouro    AS tipoLogradouro,")
          .append(" rua.rua_nome                AS rua,")
          .append(" dom.dom_numero              AS numero,")
          .append(" bai.bai_nome                AS bairro,")
          .append(" cid.cid_nome                AS cidade,")
          .append(" cid.uf_sigla                AS sigla");
      }
      sb.append(" FROM agendamento_externo agee")
        .append("  LEFT JOIN procedimento AS proc ON proc.proc_codigo = agee.proc_codigo")
        .append("  JOIN unidade AS uni ON agee.uni_codigo = uni.uni_codigo")
        .append("  LEFT JOIN especialidade AS esp ON esp.esp_codigo = agee.esp_codigo")
        .append("  LEFT JOIN medico AS newmed ON newmed.med_codigo = agee.med_codigo_prestador")
        .append("  LEFT JOIN usuarios AS usr ON usr.usr_codigo = agee.usr_codigo_solicitante")
        .append("  JOIN usuario AS usu ON usu.usu_codigo = agee.usu_codigo")
        .append("  LEFT JOIN domicilio                 AS dom   ON usu.dom_codigo = dom.dom_codigo OR usu.usu_codigo = dom.usu_codigo_responsavel ")
        .append("  LEFT JOIN rua                       AS rua   ON dom.rua_codigo = rua.rua_codigo ")
        .append("  LEFT JOIN tb_ms_tipo_logradouro     AS tplog ON rua.co_tipo_logradouro = tplog.co_tipo_logradouro ")
        .append("  LEFT JOIN bairro                    AS bai   ON rua.bai_codigo = bai.bai_codigo ")
        .append("  LEFT JOIN cidade                    AS cid   ON bai.cid_codigo = cid.cid_codigo ")
        .append(" WHERE agee.agee_data BETWEEN :dtInicial AND :dtFinal");
      if(filter.getUnidade()!=null){
        sb.append(" AND agee.uni_codigo = :unidade");
      }
      if(filter.getEspecialidade()!= null){
        sb.append(" AND agee.esp_codigo = :especialidade");
      }

      if(filter.getProcedimento()!=null){
        sb.append(" AND agee.proc_codigo = :procedimento");
      }
      if(filter.getSituacao()!= null){
        sb.append(" AND agee.agee_situacao = :situacao");
      }
      if(filter.getGrauRisco()!= null){
        sb.append(" AND agee.grau_risco = :grauRisco");
      }
      if(filter.getPrestadorServicos() != null){
        sb.append(" AND newmed.med_codigo = :prestadorServicos");
      }
      if(filter.getTpRel().equals(TipoRelEnum.SINTETICO)){
        sb.append("  GROUP BY uni.uni_desc, esp.esp_nome, proc.proc_nome, newmed.med_nome, agee.agee_situacao, agee.grau_risco")
          .append("  ORDER BY uni.uni_desc, esp.esp_nome, proc.proc_nome, newmed.med_nome, agee.agee_situacao, agee.grau_risco");
      } else{
        sb.append(" ORDER BY uni.uni_desc, esp.esp_nome, proc.proc_nome, newmed.med_nome, agee.agee_situacao, agee.grau_risco, agee.agee_data, usu.usu_nome");
      }
      return sb.toString();
    }

}
