/**
 * 全自动登录店小秘 v2 - 监听网络请求，处理 AJAX 登录
 */
import { chromium } from 'playwright';
import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
import { execSync } from 'child_process';
import sharp from 'sharp';

const COOKIE_FILE = './cookies.json';
const SCREENSHOTS_DIR = './screenshots';
const MAX_RETRIES = 10;

mkdirSync(SCREENSHOTS_DIR, { recursive: true });

async function ocrCaptcha(page) {
  // 验证码图片 ID: verifyImgCode
  const captchaImg = await page.$('#verifyImgCode');
  if (!captchaImg) {
    console.log('  未找到 #verifyImgCode');
    return null;
  }

  const captchaPath = `${SCREENSHOTS_DIR}/captcha.png`;
  await captchaImg.screenshot({ path: captchaPath });

  // 预处理图片
  const processedPath = `${SCREENSHOTS_DIR}/captcha_processed.png`;
  await sharp(captchaPath)
    .grayscale()
    .resize({ width: 468, kernel: 'lanczos3' })
    .normalize()
    .sharpen({ sigma: 2 })
    .threshold(140)
    .negate() // 有时候反色效果更好
    .toFile(processedPath);

  // 同时生成一个不反色的版本
  const processedPath2 = `${SCREENSHOTS_DIR}/captcha_processed2.png`;
  await sharp(captchaPath)
    .grayscale()
    .resize({ width: 468, kernel: 'lanczos3' })
    .normalize()
    .sharpen({ sigma: 2 })
    .threshold(140)
    .toFile(processedPath2);

  // 尝试两种预处理
  for (const path of [processedPath2, processedPath]) {
    try {
      const result = execSync(
        `tesseract "${path}" stdout --psm 7 -c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`,
        { encoding: 'utf-8', timeout: 10000 }
      ).trim().replace(/\s/g, '');

      if (result && result.length >= 4 && result.length <= 6) {
        console.log(`  OCR 结果 (${path.includes('2') ? '正常' : '反色'}): "${result}"`);
        return result;
      }
    } catch (e) {}
  }

  // 如果上面都不行，直接用原图试
  try {
    const result = execSync(
      `tesseract "${captchaPath}" stdout --psm 7 -c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`,
      { encoding: 'utf-8', timeout: 10000 }
    ).trim().replace(/\s/g, '');
    console.log(`  OCR 结果 (原图): "${result}"`);
    return result;
  } catch (e) {
    console.error('  OCR 失败:', e.message);
    return null;
  }
}

async function main() {
  console.log('====== 店小秘全自动登录 v2 ======\n');

  const browser = await chromium.launch({
    headless: true,
    args: ['--no-sandbox'],
  });

  const context = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    locale: 'zh-CN',
    userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
  });

  const page = await context.newPage();

  // 监听所有网络响应
  const responses = [];
  page.on('response', async (resp) => {
    const url = resp.url();
    if (url.includes('login') || url.includes('Login') || url.includes('user') ||
        url.includes('auth') || url.includes('verify') || url.includes('check')) {
      const status = resp.status();
      let body = '';
      try {
        body = await resp.text();
        if (body.length > 500) body = body.substring(0, 500) + '...';
      } catch (e) {}
      responses.push({ url: url.substring(0, 100), status, body });
      console.log(`  [NET] ${status} ${url.substring(0, 80)}`);
      if (body) console.log(`  [BODY] ${body.substring(0, 200)}`);
    }
  });

  try {
    console.log('>> 打开登录页...');
    await page.goto('https://www.dianxiaomi.com/home.htm', { waitUntil: 'networkidle', timeout: 30000 });

    // 查看登录表单的 action 和 method
    const formInfo = await page.evaluate(() => {
      const forms = document.querySelectorAll('form');
      return Array.from(forms).map(f => ({
        id: f.id,
        action: f.action,
        method: f.method,
        className: f.className,
      }));
    });
    console.log('>> 表单信息:', JSON.stringify(formInfo, null, 2));

    // 查看登录按钮的 onclick 事件
    const btnInfo = await page.evaluate(() => {
      const btns = document.querySelectorAll('button');
      return Array.from(btns).map(b => ({
        text: b.textContent.trim().substring(0, 20),
        onclick: b.getAttribute('onclick'),
        type: b.type,
        id: b.id,
        className: b.className,
      }));
    });
    console.log('>> 按钮信息:', JSON.stringify(btnInfo, null, 2));

    // 查看是否有 JS 登录函数
    const loginFunctions = await page.evaluate(() => {
      // 查找登录相关的脚本
      const scripts = document.querySelectorAll('script:not([src])');
      const loginCode = [];
      for (const script of scripts) {
        const text = script.textContent;
        if (text.includes('login') || text.includes('Login') || text.includes('登录')) {
          // 只取包含登录逻辑的关键部分
          const lines = text.split('\n').filter(l =>
            l.includes('login') || l.includes('Login') || l.includes('ajax') ||
            l.includes('submit') || l.includes('url') || l.includes('post') ||
            l.includes('$.') || l.includes('fetch')
          );
          loginCode.push(lines.join('\n').substring(0, 800));
        }
      }
      return loginCode;
    });
    console.log('>> 登录相关JS代码:');
    loginFunctions.forEach(code => console.log(code));

    // 多次尝试
    for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
      console.log(`\n>> ===== 第 ${attempt} 次尝试 =====`);

      // 刷新验证码（非首次）
      if (attempt > 1) {
        // 点击验证码图片刷新
        const captchaImg = await page.$('#verifyImgCode');
        if (captchaImg) {
          await captchaImg.click();
          await page.waitForTimeout(1500);
        }
      }

      // 清空并填写
      await page.fill('input[name="account"]', 'MiLe-kf01');
      await page.fill('input[name="password"]', 'Vxdas@302');

      // 勾选登录协议 checkbox（如果有）
      const checkboxes = await page.$$('input[type="checkbox"]');
      for (const cb of checkboxes) {
        const checked = await cb.isChecked();
        if (!checked) {
          await cb.check().catch(() => {});
        }
      }

      // OCR 验证码
      const code = await ocrCaptcha(page);
      if (!code || code.length < 4) {
        console.log('  验证码识别太短，跳过...');
        const captchaImg = await page.$('#verifyImgCode');
        if (captchaImg) await captchaImg.click();
        await page.waitForTimeout(1000);
        continue;
      }

      // 填验证码
      await page.fill('#verifyCode', code);

      // 截图确认
      await page.screenshot({ path: `${SCREENSHOTS_DIR}/attempt-${attempt}.png` });

      // 清空响应记录
      responses.length = 0;

      // 点击登录
      console.log('  点击登录...');
      const loginBtn = await page.$('button:has-text("登录")');
      if (!loginBtn) {
        console.log('  找不到登录按钮！');
        continue;
      }

      await Promise.all([
        loginBtn.click(),
        // 同时等待可能的页面跳转或 AJAX 响应
        page.waitForTimeout(5000),
      ]);

      // 打印所有捕获的响应
      console.log(`\n  捕获 ${responses.length} 个网络响应`);

      // 检查页面状态
      const currentUrl = page.url();
      console.log(`  当前 URL: ${currentUrl}`);

      // 检查页面上是否有错误消息
      const pageText = await page.evaluate(() => {
        // 查找弹窗、错误提示
        const alerts = document.querySelectorAll('.alert, .error, .msg, .tip, .toast, [class*="error"], [class*="alert"], [class*="msg"], [class*="tip"]');
        const texts = [];
        alerts.forEach(el => {
          const t = el.textContent.trim();
          if (t) texts.push(t.substring(0, 100));
        });
        // 也检查 layer 弹窗（常用于中文网站）
        const layerContent = document.querySelector('.layui-layer-content, .layer-content');
        if (layerContent) texts.push('layer: ' + layerContent.textContent.trim().substring(0, 100));
        return texts;
      });
      if (pageText.length > 0) {
        console.log('  页面消息:', pageText);
      }

      // 检查是否出现了后台元素
      const hasBackend = await page.evaluate(() => {
        const body = document.body.textContent;
        return body.includes('退出') || body.includes('注销') || body.includes('控制台') ||
               body.includes('我的账号') || body.includes('操作中心') || body.includes('工作台');
      });

      if (hasBackend || (currentUrl !== 'https://www.dianxiaomi.com/home.htm' &&
                          currentUrl !== 'https://www.dianxiaomi.com/index.htm' &&
                          !currentUrl.includes('home.htm'))) {
        console.log('\n>> ★★★ 登录成功！★★★');
        const cookies = await context.cookies();
        writeFileSync(COOKIE_FILE, JSON.stringify(cookies, null, 2));
        console.log(`>> Cookie 已保存（${cookies.length} 条）`);

        await page.screenshot({ path: `${SCREENSHOTS_DIR}/backend.png`, fullPage: true });
        await exploreDashboard(page, context);
        await browser.close();
        return true;
      }

      // 可能 AJAX 登录后需要手动跳转
      // 检查 cookie 中是否有登录标识
      const cookies = await context.cookies();
      const sessionCookies = cookies.filter(c =>
        c.name.toLowerCase().includes('session') ||
        c.name.toLowerCase().includes('token') ||
        c.name.toLowerCase().includes('user') ||
        c.name.toLowerCase().includes('login')
      );
      console.log('  Session cookies:', sessionCookies.map(c => `${c.name}=${c.value.substring(0, 20)}...`));

      // 尝试手动跳转到后台
      console.log('  尝试手动跳转后台...');
      const backendUrls = [
        'https://www.dianxiaomi.com/saleManage/index.htm',
        'https://www.dianxiaomi.com/user/index.htm',
        'https://www.dianxiaomi.com/setting/index.htm',
        'https://www.dianxiaomi.com/purchaseManage/purchaseSuggestion.htm',
      ];

      for (const url of backendUrls) {
        await page.goto(url, { waitUntil: 'networkidle', timeout: 15000 }).catch(() => {});
        const newUrl = page.url();
        console.log(`  ${url} -> ${newUrl}`);
        if (!newUrl.includes('/home.htm') && !newUrl.includes('/index.htm')) {
          console.log('\n>> ★★★ 已进入后台！★★★');
          const cookies = await context.cookies();
          writeFileSync(COOKIE_FILE, JSON.stringify(cookies, null, 2));
          console.log(`>> Cookie 已保存（${cookies.length} 条）`);
          await page.screenshot({ path: `${SCREENSHOTS_DIR}/backend.png`, fullPage: true });
          await exploreDashboard(page, context);
          await browser.close();
          return true;
        }
      }

      console.log('  仍未进入后台，可能验证码错误，继续重试...');
    }

    console.log('\n>> 全部 ' + MAX_RETRIES + ' 次尝试失败');
    await page.screenshot({ path: `${SCREENSHOTS_DIR}/final-fail.png`, fullPage: true });
    await browser.close();
    return false;

  } catch (err) {
    console.error('致命错误:', err.message);
    await page.screenshot({ path: `${SCREENSHOTS_DIR}/error.png` }).catch(() => {});
    await browser.close();
    return false;
  }
}

async function exploreDashboard(page, context) {
  console.log('\n>> ===== 探索后台 =====');
  console.log('>> URL:', page.url());
  console.log('>> 标题:', await page.title());

  // 获取整个页面文本的前 3000 字符
  const bodyText = await page.evaluate(() => document.body?.innerText?.substring(0, 3000));
  console.log('>> 页面内容（前3000字）:\n', bodyText);

  // 所有链接
  const links = await page.$$eval('a', els =>
    els.map(el => ({
      text: el.textContent.trim().replace(/\s+/g, ' ').substring(0, 60),
      href: el.href,
    }))
    .filter(e => e.text && e.href && e.href.startsWith('http'))
    .filter((e, i, arr) => arr.findIndex(a => a.href === e.href) === i)
  );

  console.log(`\n>> 所有链接（${links.length}个）：`);
  for (const l of links) {
    const tag = (l.text.includes('采购') || l.text.includes('仓库') ||
                 l.text.includes('导出') || l.text.includes('库存') ||
                 l.text.includes('备货')) ? '★' : ' ';
    console.log(`  ${tag} [${l.text}] ${l.href}`);
  }
}

const ok = await main();
process.exit(ok ? 0 : 1);
