const wppconnect = require('@wppconnect-team/wppconnect'); // Importa a biblioteca wppconnect para conectar ao WhatsApp
const mysql = require('mysql'); // Importa a biblioteca mysql para conectar ao banco de dados MySQL
const fs = require('fs'); // Importa a biblioteca fs para manipulação de arquivos
const request = require('request'); // Importa a biblioteca request para fazer requisições HTTP
const readline = require('readline'); // Importa a biblioteca readline para leitura de entrada do usuário
const SESSION_FILE_PATH = './session.json'; // Caminho do arquivo de sessão
const SENT_LIDS_FILE_PATH = './sent_lids.json'; // Caminho do arquivo para armazenar lids enviados

const SCRIPT_VERSION = '1.1'; // Declaração da versão atual do script

let sessionData; // Variável para armazenar os dados da sessão

// Tenta carregar os dados da sessão do arquivo
if (fs.existsSync(SESSION_FILE_PATH)) {
    sessionData = require(SESSION_FILE_PATH);
}

// Tenta carregar os lids enviados do arquivo
let sentLids = new Set();
if (fs.existsSync(SENT_LIDS_FILE_PATH)) {
    sentLids = new Set(JSON.parse(fs.readFileSync(SENT_LIDS_FILE_PATH, 'utf-8')));
}

// Configurações do banco de dados com suporte para emojis
const dbConfig = {
  host: "br386.hostgator.com.br",
  user: "onabet10_mastersender1",
  password: "102030Bacon!",
  database: "onabet10_brejonetwork",
  charset: 'utf8mb4' // Suporte para emojis
};

// Cria um pool de conexões com o banco de dados
let pool = mysql.createPool(dbConfig);

// Função para lidar com perda de conexão com o banco de dados
function handleDisconnect() {
  pool.on('error', err => {
    if (err.code === 'PROTOCOL_CONNECTION_LOST') {
      console.error('Conexão com o banco de dados perdida. Reconectando...');
      handleDisconnect(); // Tentar reconectar
    } else {
      throw err;
    }
  });
}

handleDisconnect(); // Chama a função para lidar com a desconexão

// Função para manter a conexão ativa
function keepAlive() {
  setInterval(() => {
    pool.query('SELECT 1', (err) => {
      if (err) {
        console.error('Erro ao manter a conexão ativa:', err);
      }
    });
  }, 10000); // Executar a cada 10 segundos
}

keepAlive(); // Chama a função para manter a conexão ativa

// Função para executar queries no banco de dados
function executeQuery(query, params, callback) {
  pool.query(query, params, (err, results) => {
    if (err) {
      console.error('Erro ao executar a query:', err);
      callback(err, null);
    } else {
      callback(null, results);
    }
  });
}

// Função para verificar a versão do script
function checkScriptVersion(callback) {
  executeQuery('SELECT version FROM software LIMIT 1', [], (err, results) => {
    if (err) {
      console.error('Erro ao verificar a versão do script:', err);
      process.exit(1);
    } else {
      const dbVersion = results[0].version;
      if (dbVersion !== SCRIPT_VERSION) {
        console.log(`O script está desatualizado. Versão atual: ${SCRIPT_VERSION}, Versão requerida: ${dbVersion}. Por favor, baixe a nova versão.`);
        process.exit(1);
      } else {
        console.log('Versão do script está atualizada.');
        callback();
      }
    }
  });
}

// Função para obter o num_secao mais recente para o user_envio
async function getLatestSection(userEnvio) {
  return new Promise((resolve, reject) => {
    executeQuery('SELECT num_secao FROM secoes WHERE nome_usuario = ? ORDER BY num_secao DESC LIMIT 1', [userEnvio], (err, results) => {
      if (err) {
        reject('Erro ao obter o num_secao: ' + err);
      } else if (results.length > 0) {
        resolve(results[0].num_secao);
      } else {
        resolve(0); // Retorna 0 se não houver nenhuma seção
      }
    });
  });
}

// Função para criar uma nova seção
async function createNewSection(userEnvio, newSectionNum) {
  return new Promise((resolve, reject) => {
    executeQuery('INSERT INTO secoes (nome_usuario, num_secao) VALUES (?, ?)', [userEnvio, newSectionNum], (err, results) => {
      if (err) {
        reject('Erro ao criar nova seção: ' + err);
      } else {
        resolve(newSectionNum);
      }
    });
  });
}

// Variável global para evitar duplicidade na criação de seções
let sectionManaged = false;

// Função para verificar e gerenciar a seção atual
async function manageCurrentSection(statusSession, userEnvio) {
  if (sectionManaged) return; // Evita duplicidade na criação de seções
  sectionManaged = true;

  try {
    const latestSectionNum = await getLatestSection(userEnvio);
    let currentSectionNum = latestSectionNum;

    if (statusSession === 'inChat' || statusSession === 'CONNECTED') {
      console.log(`Sessão logada. Usando num_secao: ${currentSectionNum}`);
    } else if (statusSession === 'notLogged' || statusSession === 'desconnectedMobile') {
      currentSectionNum = latestSectionNum + 1;
      await createNewSection(userEnvio, currentSectionNum);
      console.log(`Sessão não logada. Criando nova seção com num_secao: ${currentSectionNum}`);
    }

    return currentSectionNum;
  } catch (err) {
    console.error('Erro ao gerenciar a seção atual:', err);
    process.exit(1);
  }
}

// Configura o readline para leitura de entrada do usuário
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// Pergunta ao usuário o tempo de espera em minutos
rl.question('Por favor, insira o tempo de espera em minutos: ', (answer) => {
  let remainingTime = parseInt(answer) * 60; // Tempo restante em segundos

  // Verifica a versão do script antes de iniciar
  checkScriptVersion(() => {
    // Inicia o cliente do WhatsApp
    wppconnect.create({
      session: 'whatsapp-session', // Nome da sessão
      catchQR: (base64Qr, asciiQR) => {
        console.log('Código QR:', asciiQR);
      },
      statusFind: async (statusSession, session) => {
        console.log('Status da sessão:', statusSession);

        // Adiciona lógica para criação de seção se a sessão não estiver logada
        if (statusSession === 'notLogged' || statusSession === 'desconnectedMobile') {
          const usuario = fs.readFileSync('./user.txt', 'utf-8').trim();
          const currentSectionNum = await manageCurrentSection(statusSession, usuario);
          console.log(`Seção gerenciada. num_secao atual: ${currentSectionNum}`);
        }
      },
      sessionData: sessionData,
      autoClose: false // Mantém a sessão aberta
    })
    .then(async client => {
      const usuario = fs.readFileSync('./user.txt', 'utf-8').trim(); // Usuário a ser verificado
      const statusSession = await client.getConnectionState();
      let currentSectionNum = await manageCurrentSection(statusSession, usuario);

      client.onStateChange(state => {
        console.log('Estado da sessão:', state);
        if (state === 'DISCONNECTED' || state === 'UNPAIRED' || state === 'UNPAIRED_IDLE') {
          console.log('SESSÃO DESCONECTADA!');

          // Função para obter o número de telefone do usuário
          const getUserPhoneNumber = async (usuario) => {
            return new Promise((resolve, reject) => {
              executeQuery('SELECT telefone FROM users WHERE nome_usuario = ?', [usuario], (err, results) => {
                if (err) {
                  reject('Erro ao obter o telefone do usuário: ' + err);
                } else if (results.length > 0) {
                  resolve(results[0].telefone);
                } else {
                  reject('Telefone não encontrado para o usuário: ' + usuario);
                }
              });
            });
          };

          // Função para enviar notificação de queda de sessão
          const sendSessionDropNotification = async (usuario) => {
            try {
              const numero = await getUserPhoneNumber(usuario);
              const options = {
                method: 'POST',
                url: 'https://api.ultramsg.com/instance89506/messages/chat',
                headers: {'content-type': ' application/x-www-form-urlencoded'},
                form: {
                  "token": "1vioje43w88z2mab",
                  "to": "120363298259726056@g.us",
                  "body": `A sessão do @${numero} caiu!`,
                  "priority": 10,
                  "referenceId": "",
                  "msgId": "",
                  "mentions": numero
                }
              };

              request(options, function (error, response, body) {
                if (error) throw new Error(error);
                console.log(body);
                process.exit(1); // Encerra o script com código de erro 1
              });
            } catch (err) {
              console.error(err);
              process.exit(1);
            }
          };

          sendSessionDropNotification(usuario);
        }
      });

      console.log('Timer iniciado.');
      const countdownInterval = setInterval(async () => {
        remainingTime -= 60;
        const minutesRemaining = Math.floor(remainingTime / 60);
        if (remainingTime > 0) {
          console.log(`Tempo restante: ${minutesRemaining} minuto(s).`);
        } else {
          clearInterval(countdownInterval);
          console.log('Tempo de espera finalizado. Iniciando verificação de mensagens.');

          // Atualiza o valor de currentSectionNum
          currentSectionNum = await getLatestSection(usuario);

          startMessageChecking(client, currentSectionNum); // Inicia a verificação de mensagens
        }
      }, 60000); // Intervalo de 1 minuto
    })
    .catch(error => console.log('Erro ao iniciar o cliente do WhatsApp:', error));

    let messageCount = 0; // Contador de mensagens enviadas
    let isPaused = false; // Flag para indicar se o envio de mensagens está pausado

    // Função para iniciar a verificação de mensagens
    function startMessageChecking(client, currentSectionNum) {
      checkAndSendMessages(client, currentSectionNum);
    }

    // Função para verificar e enviar mensagens
    function checkAndSendMessages(client, currentSectionNum) {
      if (isPaused) {
        console.log('Está pausado, aguardando...');
        return;
      }

      // Lê o conteúdo do arquivo user.txt
      const usuario = fs.readFileSync('./user.txt', 'utf-8').trim(); // Usuário a ser verificado

      executeQuery('SELECT finais, texto_mensagem, terceirizado FROM users WHERE nome_usuario = ?', [usuario], (err, userResults) => {
        if (err) {
          console.error('Erro ao consultar dados:', err);
          return;
        }

        if (userResults.length > 0) {
          const finais = userResults[0].finais.split(',').map(f => f.trim()); // Obtém os finais e transforma em array
          const textoMensagem = userResults[0].texto_mensagem; // Obtém o texto da mensagem
          const terceirizado = userResults[0].terceirizado; // Verifica se é terceirizado

          let query;
          if (terceirizado === 'SIM') {
            query = `
              SELECT lid 
              FROM dados_whatsapp 
              WHERE status = 'aguardando' 
                AND data_coleta BETWEEN DATE_SUB(NOW(), INTERVAL 6 MINUTE) AND DATE_SUB(NOW(), INTERVAL 2 MINUTE)
              ORDER BY data_coleta DESC 
              LIMIT 5
            `;
          } else {
            query = `
              SELECT lid 
              FROM dados_whatsapp 
              WHERE status = 'aguardando' 
                AND data_coleta >= DATE_SUB(NOW(), INTERVAL 2 MINUTE)
              ORDER BY data_coleta DESC 
              LIMIT 5
            `;
          }

          executeQuery(query, [], (err, rows) => {
            if (err) {
              console.error('Erro ao consultar os dados:', err);
              return;
            }

            const filteredLids = rows.filter(row => {
              const lid = row.lid;
              const final = lid.split('@')[0].slice(-1); // Obtém o último dígito antes do '@'
              return finais.includes(final) && !sentLids.has(lid); // Filtra os lids
            });

            if (filteredLids.length > 0) {
              sendMessagesWithDelay(client, filteredLids, 0, usuario, textoMensagem, currentSectionNum); // Envia mensagens com atraso
            } else {
              let additionalDelay = Math.floor(Math.random() * (60000 - 55000 + 1)) + 60000;
              console.log(`Nenhum lid encontrado. Esperando ${additionalDelay / 1000} segundos antes de verificar novamente.`);
              setTimeout(() => checkAndSendMessages(client, currentSectionNum), additionalDelay); // Aguarda antes de verificar novamente
            }
          });
        } else {
          console.log('Nenhum usuário encontrado com o nome:', usuario);
        }
      });
    }

    // Variável global para contar os envios
    let totalEnvios = 0;

    // Função para enviar mensagens com atraso
    function sendMessagesWithDelay(client, filteredLids, index, usuario, textoMensagem, currentSectionNum) {
      if (index < filteredLids.length) {
        const lid = filteredLids[index].lid;

        executeQuery('SELECT status FROM dados_whatsapp WHERE lid = ?', [lid], (err, results) => {
          if (err) {
            console.error('Erro ao verificar o status do lid:', err);
            return;
          }

          if (results.length > 0 && results[0].status === 'aguardando') {
            executeQuery(`
              UPDATE dados_whatsapp 
              SET status = 'enviado', data_envio = NOW(), user_envio = ?, num_secao = ?
              WHERE lid = ? AND status = 'aguardando'
            `, [usuario, currentSectionNum, lid], (err) => {
              if (err) {
                console.error('Erro ao atualizar o banco de dados:', err);
                return;
              }

              sentLids.add(lid); // Adiciona o lid ao conjunto de lids enviados
              fs.writeFileSync(SENT_LIDS_FILE_PATH, JSON.stringify(Array.from(sentLids), null, 2)); // Salva os lids enviados no arquivo

              client.sendText(lid, textoMensagem)
                .then(result => {
                  totalEnvios++; // Incrementa o total de envios
                  const currentTime = new Date().toLocaleTimeString(); // Obtém o horário atual
                  console.log(`${currentTime} - ${totalEnvios} Enviado Para -> ${result.chatId}`);
                  messageCount++; // Incrementa o contador de mensagens enviadas
                })
                .catch(error => {
                  console.error('Erro ao enviar mensagem:', error);
                  executeQuery('UPDATE dados_whatsapp SET status = \'aguardando\' WHERE lid = ?', [lid], (err) => {
                    if (err) {
                      console.error('Erro ao reverter status para aguardando:', err);
                    }
                  });
                });

              const delay = Math.floor(Math.random() * (15000 - 10000 + 1)) + 10000;
              setTimeout(() => {
                if (messageCount >= 3 || index === filteredLids.length - 1) {
                  let additionalDelay;
                  if (messageCount === 1) {
                    additionalDelay = Math.floor(Math.random() * (70000 - 60000 + 1)) + 60000;
                  } else if (messageCount === 2) {
                    additionalDelay = Math.floor(Math.random() * (90000 - 70000 + 1)) + 70000;
                  } else if (messageCount >= 3) {
                    additionalDelay = Math.floor(Math.random() * (120000 - 110000 + 1)) + 110000;
                  }
                  console.log(`Atingiu ${messageCount} mensagens ou enviou todos os lids. Pausando por ${additionalDelay / 1000} segundos.`);
                  messageCount = 0; // Reseta o contador de mensagens enviadas
                  isPaused = true; // Define a flag de pausa como true
                  setTimeout(() => {
                    isPaused = false; // Define a flag de pausa como false após o tempo de espera
                    checkAndSendMessages(client, currentSectionNum); // Reinicia a verificação de mensagens
                  }, additionalDelay);
                } else {
                  sendMessagesWithDelay(client, filteredLids, index + 1, usuario, textoMensagem, currentSectionNum); // Envia a próxima mensagem com atraso
                }
              }, delay);
            });
          } else {
            console.log(`Lid ${lid} já foi processado. Pulando.`);
            sendMessagesWithDelay(client, filteredLids, index + 1, usuario, textoMensagem, currentSectionNum); // Pula para o próximo lid
          }
        });
      } else {
        let additionalDelay = Math.floor(Math.random() * (60000 - 55000 + 1)) + 60000;
        console.log(`Esperando ${additionalDelay / 1000} segundos antes de verificar novamente.`);
        setTimeout(() => checkAndSendMessages(client, currentSectionNum), additionalDelay); // Aguarda antes de verificar novamente
      }
    }

    // Função para encerrar a conexão com o banco de dados ao finalizar o processo
    process.on('SIGINT', () => {
      pool.end((err) => {
        if (err) {
          console.log('Erro ao encerrar a conexão com o banco de dados:', err);
        }
        console.log('Conexão com o banco de dados encerrada.');
        process.exit(0);
      });
    });

    rl.close(); // Fecha a interface readline após a entrada do usuário
  });
});
