
const { Client } = require('pg');
const mysql = require('mysql2/promise');
const dotenv = require('dotenv');
const fs = require('fs');
const moment = require('moment');

dotenv.config();

const envData = fs.readFileSync('conecta.env', 'utf8');
const envVariables = dotenv.parse(envData);

function printProgressBar(completed, total, barLength = 40) {
  const progress = completed / total;
  const filledLength = Math.round(barLength * progress);
  const emptyLength = barLength - filledLength;

  const bar = '█'.repeat(filledLength) + '░'.repeat(emptyLength);
  const percent = (progress * 100).toFixed(1).padStart(5, ' ');
  const status = `${completed}/${total}`.padEnd(15, ' ');
  const now = new Date();
  const time = now.toLocaleTimeString('pt-BR');

  const output = `\rG-SAUDE Importacao e-SUS PEC ${bar} ${percent}% (${status}) -  ${time}`;

  process.stdout.write(output);
  if (completed === total) {
    process.stdout.write('\n'); 
  }
}

const {
  DB_PG_SERVER, DB_PG_PORT, DB_PG_USERNAME, DB_PG_PASSWORD, DB_PG_NAME,
  DB_MYSQL_SERVER, DB_MYSQL_USERNAME, DB_MYSQL_PASSWORD, DB_MYSQL_NAME
} = envVariables;

const cachePacientes = new Map();
const cacheProfissionais = new Map();
const cacheProcedimentos = new Map();
const cacheUnidades = new Map();


const chunkSize = 100;


async function main() {
  const pgClient = new Client({
    host: DB_PG_SERVER,
    port: DB_PG_PORT,
    user: DB_PG_USERNAME,
    password: DB_PG_PASSWORD,
    database: DB_PG_NAME,
  });
  await pgClient.connect();

  const mysqlConn = await mysql.createConnection({
    host: DB_MYSQL_SERVER,
    user: DB_MYSQL_USERNAME,
    password: DB_MYSQL_PASSWORD,
    database: DB_MYSQL_NAME,
    multipleStatements: true
  });

  const query = `SELECT
    t1.co_seq_atend_prof as id_atend_esus,
    t7.nu_cpf as nu_cpf,
    t7.nu_cns as nu_cns,
    t7.no_cidadao,
    TO_CHAR(t7.dt_nascimento, 'YYYY-MM-DD') as dt_nascimento,
    t7.no_mae,
    t7.no_sexo,
    t7.ds_cep,
    t7.ds_logradouro,
    t7.no_bairro,
    t7.nu_numero as numero_endereco,
    t7.nu_telefone_celular,
    TO_CHAR(t1.dt_inicio, 'YYYY-MM-DD') AS data_atendimento,
    TO_CHAR(t14.dt_requisicao, 'YYYY-MM-DD') AS data_requisicao,
    t14.ds_justificativa_procedimento,
    t16.no_proced as procedimento,
    t16.co_proced as codigo_sigtap,
    t17.nu_cid10 as co_cid_justificativa_procedimento,
    t13.nu_cpf as cpf_prof,
    t13.nu_cns as cns_prof,
    t11.nu_cnes as nu_cnes
  FROM tb_atend_prof t1
  LEFT JOIN tb_atend t2 ON t2.co_atend_prof = t1.co_seq_atend_prof
  LEFT JOIN tb_prontuario t6 ON t2.co_prontuario = t6.co_seq_prontuario
  LEFT JOIN tb_cidadao t7 ON t6.co_cidadao = t7.co_seq_cidadao
  LEFT JOIN tb_lotacao t9 ON t1.co_lotacao = t9.co_ator_papel
  LEFT JOIN tb_unidade_saude t11 ON t9.co_unidade_saude = t11.co_seq_unidade_saude
  LEFT JOIN tb_prof t13 ON t9.co_prof = t13.co_seq_prof
  LEFT JOIN tb_requisicao_exame t14 ON t1.co_seq_atend_prof = t14.co_atend_prof
  LEFT JOIN tb_exame_requisitado t15 ON t14.co_seq_requisicao_exame = t15.co_requisicao_exame
  LEFT JOIN tb_proced t16 ON t15.co_proced = t16.co_seq_proced
  LEFT JOIN tb_cid10 t17 ON t14.co_cid10 = t17.co_cid10
  LEFT JOIN tb_proced_grupo t18 ON t16.co_proced_grupo = t18.co_proced_grupo
  WHERE t7.no_cidadao IS NOT NULL 
  --AND t1.dt_inicio >= CURRENT_DATE - INTERVAL '6 months'
    AND t16.no_proced IS NOT NULL
  --AND t18.nu_ms = '09';`;

  const { rows } = await pgClient.query(query);
  console.log(`Total de registros a processar: ${rows.length}`);

  await mysqlConn.beginTransaction();
  try {
    for (let i = 0; i < rows.length; i++) {
      const r = rows[i];
      const cpf = r.nu_cpf?.replace(/\D/g, '') || null;
      const cns = r.nu_cns || null;

      const key = cpf || cns;
      let idPaciente = cachePacientes.get(key);

      if (!idPaciente) {
        const [pacienteRows] = await mysqlConn.execute(
          `SELECT id_paciente FROM tb_paciente WHERE cpf_paciente = ? OR cns_paciente = ? LIMIT 1`,
          [cpf, cns]
        );

        if (pacienteRows.length) {
          idPaciente = pacienteRows[0].id_paciente;
        } else {
          const [insertResult] = await mysqlConn.execute(
            `INSERT INTO tb_paciente (cpf_paciente, cns_paciente, nome_paciente, datanasc, sexo, nomemae, cep_paciente, endereco_paciente, numeroend_paciente, bairro_paciente, celular1, origem)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'esus')`,
            [cpf, cns, r.no_cidadao, r.dt_nascimento, r.no_sexo, r.no_mae, r.ds_cep, r.ds_logradouro, r.numero_endereco, r.no_bairro, r.nu_telefone_celular]
          );
          idPaciente = insertResult.insertId;
        }
        cachePacientes.set(key, idPaciente);
      }

      const idProf = await getIdProfissional(mysqlConn, r);

      const idUnidade = await getIdUnidade(mysqlConn, r.nu_cnes);

      const { id_procedimento, id_grupo_procedimento } = await getIdProcedimento(mysqlConn, r.codigo_sigtap);

     
      const [existe] = await mysqlConn.execute(
        `SELECT 1 FROM reg_tb_solicitacoes WHERE id_paciente = ? AND id_procedimento = ? AND data_atendimento = ? LIMIT 1`,
        [idPaciente, id_procedimento, r.data_atendimento]
      );
      if (existe.length) continue;

      const [res] = await mysqlConn.execute(
        `INSERT INTO reg_tb_solicitacoes (id_paciente, cid_solicitacao, codigoprofissional_cnes, id_grupo_procedimento, id_procedimento, observacoes_solicitacao, id_statussolicitacao, id_usuario_cadastrou, id_unidade_cadastrou, data_atendimento, datahora_cadastro)
         VALUES (?, ?, ?, ?, ?, ?, 2, 1, ?, ?, NOW())`,
        [idPaciente, r.co_cid_justificativa_procedimento, idProf, id_grupo_procedimento, id_procedimento, r.ds_justificativa_procedimento, idUnidade, r.data_atendimento]
      );

      const protocolo = `${moment().format('YYYYMM')}${res.insertId.toString().padStart(5, '0')}`;
      await mysqlConn.execute(`UPDATE reg_tb_solicitacoes SET numero_procotolo = ? WHERE id_solicitacao = ?`, [protocolo, res.insertId]);

     if ((i + 1) % chunkSize === 0 || i + 1 === rows.length) {
    printProgressBar(i + 1, rows.length);
  }
    }
    await mysqlConn.commit();
    console.log('\nImportação concluída com sucesso.');
  } catch (err) {
    await mysqlConn.rollback();
    console.error('\nErro durante processamento:', err);
  } finally {
    await pgClient.end();
    await mysqlConn.end();
  }
}

async function getIdProfissional(mysqlConn, row) {
  const chave = row.cns_prof || row.cpf_prof;
  if (cacheProfissionais.has(chave)) return cacheProfissionais.get(chave);

  const [res] = await mysqlConn.execute(
    `SELECT codigoprofissional_cnes FROM tb_profissional WHERE cns_profissional = ? OR cpf_profissional = ? LIMIT 1`,
    [row.cns_prof, row.cpf_prof]
  );

  if (res.length) {
    const id = res[0].codigoprofissional_cnes;
    cacheProfissionais.set(chave, id);
    return id;
  }
  return null;
}
async function getIdUnidade(mysqlConn, nu_cnes) {
  if (!nu_cnes) return null;
  if (cacheUnidades.has(nu_cnes)) return cacheUnidades.get(nu_cnes);

  const [res] = await mysqlConn.execute(
    `SELECT codigoestabelecimento_cnes FROM tb_estabelecimento WHERE cnes_estabelecimento = ? LIMIT 1`,
    [nu_cnes]
  );

  if (res.length) {
    const id = res[0].codigoestabelecimento_cnes;
    cacheUnidades.set(nu_cnes, id);
    return id;
  }
  return null;
}
async function getIdProcedimento(mysqlConn, codigo) {
  if (cacheProcedimentos.has(codigo)) return cacheProcedimentos.get(codigo);

  let sql, param;
  if (/^\d+$/.test(codigo)) {
    param = codigo.replace(/^0/, '');
    sql = `SELECT id_procedimento, id_grupo_procedimento FROM reg_tb_procedimento WHERE codigo_sus = ? LIMIT 1`;
  } else {
    param = codigo;
    sql = `SELECT id_procedimento, id_grupo_procedimento FROM reg_tb_procedimento WHERE codigo_integracaoesus = ? LIMIT 1`;
  }

  const [res] = await mysqlConn.execute(sql, [param]);
  if (res.length) {
    cacheProcedimentos.set(codigo, res[0]);
    return res[0];
  }
  return { id_procedimento: null, id_grupo_procedimento: null };
}

main();