const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const axios = require('axios');

// Adiciona o plugin Stealth para evitar detecção
puppeteer.use(StealthPlugin());

// Configurações
const url = 'https://professorvareta.eveclass.com/pt/comprar/produto/combo-apostilas-de-questoes-fuvest-unesp-unicamp';
const websiteKey = '6Lfmy38rAAAAAFrQD9XthYrWNnb_oXQqLfzfo6Wo';
const capMonsterApiKey = '5485c128aebfdfa9f378e97ab486c2a6';
const capMonsterUrl = 'https://api.capmonster.cloud';

// Função para simular espera
const waitForTimeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Função para resolver o reCAPTCHA com CapMonster
async function solveRecaptcha(pageUrl, siteKey) {
  try {
    const createTaskResponse = await axios.post(`${capMonsterUrl}/createTask`, {
      clientKey: capMonsterApiKey,
      task: {
        type: 'RecaptchaV2TaskProxyless',
        websiteURL: pageUrl,
        websiteKey: siteKey,
      },
    });

    const taskId = createTaskResponse.data.taskId;
    console.log(`Tarefa criada no CapMonster, Task ID: ${taskId}`);

    let result;
    while (true) {
      await waitForTimeout(5000);
      const getTaskResult = await axios.post(`${capMonsterUrl}/getTaskResult`, {
        clientKey: capMonsterApiKey,
        taskId: taskId,
      });

      if (getTaskResult.data.status === 'ready') {
        result = getTaskResult.data.solution.gRecaptchaResponse;
        console.log('reCAPTCHA resolvido com sucesso!');
        break;
      } else if (getTaskResult.data.status === 'failed') {
        throw new Error('Falha ao resolver o reCAPTCHA: ' + getTaskResult.data.errorId);
      }
    }

    return result;
  } catch (error) {
    console.error('Erro ao resolver o reCAPTCHA:', error.message);
    throw error;
  }
}

// Função para avaliar XPath (substitui page.waitForXPath)
async function waitForXPath(page, xpath, timeout = 20000) {
  const start = Date.now();
  while (Date.now() - start < timeout) {
    const element = await page.evaluate((xp) => {
      const result = document.evaluate(xp, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
      return result.singleNodeValue ? true : false;
    }, xpath);
    if (element) return true;
    await waitForTimeout(500);
  }
  throw new Error(`Timeout waiting for XPath: ${xpath}`);
}

// Função para simular comportamento humano
async function simulateHumanBehavior(page) {
  await page.evaluate(() => window.scrollBy(0, Math.random() * 500));
  await waitForTimeout(1500 + Math.random() * 1000);
  const x = Math.random() * 500 + 100;
  const y = Math.random() * 400 + 100;
  await page.mouse.move(x, y, { steps: 20 });
  await page.mouse.click(x, y);
  await waitForTimeout(1000 + Math.random() * 500);
}

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--disable-dev-shm-usage',
      '--window-size=1280,720',
    ],
  });

  const page = await browser.newPage();

  await page.setExtraHTTPHeaders({
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
    'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7',
  });

  await page.setViewport({ width: 1280, height: 720 });

  try {
    console.log('Navegando até a página...');
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });

    // Simula comportamento humano
    await simulateHumanBehavior(page);

    // Depuração: Lista todos os campos de input na página
    console.log('Listando campos de input na página...');
    const inputs = await page.evaluate(() => {
      const inputElements = Array.from(document.querySelectorAll('input'));
      return inputElements.map(input => ({
        id: input.id,
        name: input.name,
        placeholder: input.placeholder,
        type: input.type,
        class: input.className,
      }));
    });
    console.log('Campos encontrados:', JSON.stringify(inputs, null, 2));

    // Depuração: Captura o HTML do formulário
    const formHtml = await page.evaluate(() => {
      const form = document.querySelector('form');
      return form ? form.outerHTML.substring(0, 1000) : 'Formulário não encontrado';
    });
    console.log('HTML do formulário (primeiros 1000 caracteres):', formHtml);

    // Preenche os campos do formulário usando seletores genéricos
    console.log('Preenchendo campos do formulário...');
    
    // Campo de nome
    const nameField = await page.$('input[placeholder*="nome" i], input[name*="nome" i], input[id*="nome" i], input[type="text"]');
    if (nameField) {
      await nameField.type('Joao Campos', { delay: 100 });
      console.log('Campo de nome preenchido.');
    } else {
      console.log('Campo de nome não encontrado.');
    }

    // Campo de e-mail
    const emailField = await page.$('input[type="email"]:nth-of-type(1), input[placeholder*="email" i], input[name*="email" i], input[id*="email" i]');
    if (emailField) {
      await emailField.type('aaads@gmail.com', { delay: 100 });
      console.log('Campo de e-mail preenchido.');
    } else {
      console.log('Campo de e-mail não encontrado.');
    }

    // Campo de confirmação de e-mail
    const confirmEmailField = await page.$('input[type="email"]:nth-of-type(2), input[placeholder*="confirme" i], input[name*="confirme" i], input[id*="confirme" i]');
    if (confirmEmailField) {
      await confirmEmailField.type('aaads@gmail.com', { delay: 100 });
      console.log('Campo de confirmação de e-mail preenchido.');
    } else {
      console.log('Campo de confirmação de e-mail não encontrado.');
    }

    await waitForTimeout(1000 + Math.random() * 500);

    // Clica no botão de rádio "Sou novo aqui" (se necessário)
    console.log('Selecionando opção "Sou novo aqui"...');
    const radioButton = await page.$('form.checkout-authentication-wrapper button.radio-selected');
    if (radioButton) {
      await radioButton.click();
      console.log('Botão de rádio "Sou novo aqui" clicado.');
    } else {
      console.log('Botão de rádio "Sou novo aqui" não encontrado.');
    }

    await waitForTimeout(1000 + Math.random() * 500);

    // Clica no botão de submit ("Próximo") para acionar o reCAPTCHA
    console.log('Clicando no botão de submit ("Próximo") para acionar o reCAPTCHA...');
    await simulateHumanBehavior(page); // Adiciona comportamento humano
    const submitButtonSelector = 'form.checkout-authentication-wrapper button[type="submit"]';
    let submitButton = await page.$(submitButtonSelector);
    if (submitButton) {
      await page.waitForSelector(submitButtonSelector, { timeout: 10000 });
      await submitButton.click();
      console.log('Botão de submit (CSS) clicado.');
      await waitForTimeout(2000); // Aguarda resposta
    } else {
      console.log('Botão de submit não encontrado com CSS, usando XPath como fallback...');
      const submitButtonXPath = '//*[@id="app"]/div/div[1]/div/div/form/div[2]/button';
      await waitForXPath(page, submitButtonXPath, 10000).catch(() => {
        throw new Error('Botão de submit não encontrado com XPath.');
      });
      const [submitButtonXPathElement] = await page.$x(submitButtonXPath);
      if (submitButtonXPathElement) {
        await submitButtonXPathElement.click();
        console.log('Botão de submit (XPath) clicado.');
        await waitForTimeout(2000); // Aguarda resposta
      } else {
        throw new Error('Botão de submit não encontrado com XPath.');
      }
    }

    // Verifica mensagens de erro
    const errorMessage = await page.evaluate(() => {
      const error = document.querySelector('.error, .alert, [class*="error"], [class*="alert"]');
      return error ? error.textContent : null;
    });
    if (errorMessage) {
      console.error('Mensagem de erro detectada:', errorMessage);
      await browser.close();
      return;
    }

    // Aguarda o iframe do reCAPTCHA
    console.log('Aguardando o iframe do reCAPTCHA...');
    const recaptchaIframeSelector = 'iframe[src*="recaptcha"]';
    await page.waitForSelector(recaptchaIframeSelector, { timeout: 20000 }).catch(async () => {
      console.log('reCAPTCHA iframe não encontrado. HTML da página (primeiros 500 caracteres):');
      const pageContent = await page.content();
      console.log(pageContent.substring(0, 500));
      throw new Error('reCAPTCHA iframe não encontrado.');
    });

    // Muda para o contexto do iframe
    const recaptchaIframe = await page.$(recaptchaIframeSelector);
    const frame = await recaptchaIframe.contentFrame();

    // Aguarda o checkbox dentro do iframe
    const recaptchaCheckbox = await frame.$('#rc-anchor-container');
    if (recaptchaCheckbox) {
      await recaptchaCheckbox.click();
      await waitForTimeout(1000 + Math.random() * 500);
      console.log('Checkbox do reCAPTCHA clicado dentro do iframe.');
    } else {
      console.log('Checkbox do reCAPTCHA não encontrado dentro do iframe.');
    }

    const recaptchaPresent = await page.evaluate(() => {
      return !!document.querySelector('#rc-anchor-container, .g-recaptcha, [data-sitekey], iframe[src*="recaptcha"]');
    });

    if (!recaptchaPresent) {
      console.log('Nenhum reCAPTCHA encontrado após interação. HTML da página (primeiros 500 caracteres):');
      const pageContent = await page.content();
      console.log(pageContent.substring(0, 500));
      await browser.close();
      return;
    }

    console.log('reCAPTCHA encontrado! Resolvendo com CapMonster...');
    const recaptchaSolution = await solveRecaptcha(url, websiteKey);

    // Injeta a solução do reCAPTCHA
    await page.evaluate((solution) => {
      const textarea = document.getElementById('g-recaptcha-response');
      if (textarea) {
        textarea.value = solution;
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
      }
      // Executa callback, se presente
      if (window.___grecaptcha_cfg && window.___grecaptcha_cfg.clients[0]) {
        const callback = window.___grecaptcha_cfg.clients[0].callback;
        if (callback) callback(solution);
      }
    }, recaptchaSolution);

    // Clica novamente no botão de submit ("Próximo") para enviar o formulário
    console.log('Clicando novamente no botão de submit ("Próximo")...');
    submitButton = await page.$(submitButtonSelector);
    if (submitButton) {
      await submitButton.click();
      console.log('Botão de submit (CSS) clicado novamente.');
    } else {
      console.log('Botão de submit não encontrado com CSS, usando XPath como fallback...');
      const [submitButtonXPathElement] = await page.$x('//*[@id="app"]/div/div[1]/div/div/form/div[2]/button');
      if (submitButtonXPathElement) {
        await submitButtonXPathElement.click();
        console.log('Botão de submit (XPath) clicado novamente.');
      } else {
        throw new Error('Botão de submit não encontrado na segunda tentativa.');
      }
    }

    // Aguarda resposta do servidor
    await page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 }).catch(() => {
      console.log('Navegação concluída ou timeout atingido.');
    });

    // Retorna a chave do reCAPTCHA
    console.log('Chave do reCAPTCHA:', recaptchaSolution);

    // Verifica erros na página
    const pageContent = await page.content();
    if (pageContent.includes('Erro') || pageContent.includes('inválido') || pageContent.includes('unsecure_request')) {
      console.error('Erro detectado:', pageContent.match(/{"code":"[^"]+","pt":"[^"]+","status":\d+}/)?.[0] || 'Erro desconhecido');
      console.log('HTML da página (primeiros 500 caracteres):', pageContent.substring(0, 500));
    } else {
      console.log('Submissão realizada com sucesso!');
    }

  } catch (error) {
    console.error('Erro durante a execução:', error.message);
  } finally {
    await browser.close();
  }
})();