/**
 * 全自动登录店小秘（含验证码 OCR）
 * 登录成功后保存 Cookie + 截图后台页面结构
 */
import { chromium } from 'playwright';
import { writeFileSync, readFileSync, existsSync, mkdirSync, unlinkSync } from 'fs';
import { execSync } from 'child_process';
import sharp from 'sharp';

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

mkdirSync(SCREENSHOTS_DIR, { recursive: true });

// ====== 验证码 OCR ======
async function solveCaptcha(page) {
  // 找到验证码图片
  const captchaImg = await page.$('#verifyCodeImg, img[id*="verify"], img[id*="captcha"], img[src*="verify"], img[src*="captcha"], .verify-code img, img[onclick*="verify"]');

  if (!captchaImg) {
    // 如果没有独立 img 标签，可能是 canvas 或背景图，尝试找验证码区域
    console.log('  未找到验证码 img 标签，尝试其他方式...');

    // 尝试通过验证码输入框附近的图片
    const codeInput = await page.$('#verifyCode, input[name="verifyCode"]');
    if (codeInput) {
      const parent = await codeInput.evaluateHandle(el => el.parentElement);
      const nearbyImg = await page.evaluateHandle(
        el => el.querySelector('img') || el.nextElementSibling?.querySelector('img') || el.parentElement?.querySelector('img'),
        parent
      );
      if (nearbyImg) {
        const captchaPath = `${SCREENSHOTS_DIR}/captcha.png`;
        await nearbyImg.asElement()?.screenshot({ path: captchaPath });
        if (existsSync(captchaPath)) {
          return await ocrImage(captchaPath);
        }
      }
    }

    // 最后尝试：截图整个验证码区域
    console.log('  尝试截图验证码区域...');
    // 找到 "点击刷新" 按钮附近的图片
    const refreshBtn = await page.$('button:has-text("点击刷新"), a:has-text("点击刷新"), span:has-text("点击刷新")');
    if (refreshBtn) {
      // 验证码可能在刷新按钮的兄弟元素中
      const captchaArea = await page.evaluateHandle(
        btn => btn.previousElementSibling || btn.parentElement,
        refreshBtn
      );
      const imgEl = await captchaArea.asElement();
      if (imgEl) {
        const captchaPath = `${SCREENSHOTS_DIR}/captcha.png`;
        await imgEl.screenshot({ path: captchaPath });
        return await ocrImage(captchaPath);
      }
    }

    return null;
  }

  // 截图验证码图片
  const captchaPath = `${SCREENSHOTS_DIR}/captcha.png`;
  await captchaImg.screenshot({ path: captchaPath });
  console.log('  验证码图片已截图');

  return await ocrImage(captchaPath);
}

async function ocrImage(imagePath) {
  try {
    // 预处理：灰度 + 高对比度 + 放大 + 二值化
    const processedPath = imagePath.replace('.png', '_processed.png');
    await sharp(imagePath)
      .grayscale()
      .resize({ width: 400, kernel: 'lanczos3' }) // 放大
      .normalize()                                  // 增强对比
      .sharpen({ sigma: 2 })                        // 锐化
      .threshold(128)                                // 二值化
      .toFile(processedPath);

    // 调用 Tesseract OCR
    const result = execSync(
      `tesseract "${processedPath}" 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 refreshCaptcha(page) {
  // 尝试点击刷新按钮或验证码图片本身
  const refreshBtn = await page.$('button:has-text("点击刷新")');
  if (refreshBtn) {
    await refreshBtn.click();
    await page.waitForTimeout(1000);
    return;
  }

  // 点击验证码图片刷新
  const captchaImg = await page.$('#verifyCodeImg, img[id*="verify"], img[src*="verify"], img[src*="captcha"]');
  if (captchaImg) {
    await captchaImg.click();
    await page.waitForTimeout(1000);
  }
}

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

  const browser = await chromium.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-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();

  try {
    // 尝试用已有 Cookie 直接访问后台
    if (existsSync(COOKIE_FILE)) {
      console.log('>> 发现已有 Cookie，尝试复用...');
      const cookies = JSON.parse(readFileSync(COOKIE_FILE, 'utf-8'));
      await context.addCookies(cookies);
      await page.goto('https://www.dianxiaomi.com/saleManage/index.htm', { waitUntil: 'networkidle', timeout: 30000 });

      if (!page.url().includes('/home.htm') && !page.url().includes('/index.htm')) {
        console.log('>> Cookie 有效，已直接进入后台！URL:', page.url());
        await exploreDashboard(page);
        await browser.close();
        return true;
      }
      console.log('>> Cookie 已过期，需要重新登录\n');
    }

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

    // 分析页面上的验证码结构
    console.log('>> 分析验证码结构...');
    const pageInfo = await page.evaluate(() => {
      const imgs = Array.from(document.querySelectorAll('img'));
      return imgs.map(img => ({
        id: img.id,
        src: img.src?.substring(0, 100),
        className: img.className,
        width: img.width,
        height: img.height,
        alt: img.alt,
      }));
    });
    console.log('  页面图片:', JSON.stringify(pageInfo, null, 2));

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

      // 填写账号密码
      await page.fill('input[name="account"]', '');
      await page.fill('input[name="account"]', 'MiLe-kf01');
      await page.fill('input[type="password"]', '');
      await page.fill('input[type="password"]', 'Vxdas@302');

      // 勾选记住我
      const rememberCheckbox = await page.$('input[name="remeber"]');
      if (rememberCheckbox) {
        await rememberCheckbox.check().catch(() => {});
      }

      // 刷新验证码（确保是新的）
      if (attempt > 1) {
        await refreshCaptcha(page);
      }

      // OCR 验证码
      const captchaCode = await solveCaptcha(page);
      if (!captchaCode || captchaCode.length < 3) {
        console.log(`  验证码识别结果太短 ("${captchaCode}")，刷新重试...`);
        await refreshCaptcha(page);
        continue;
      }

      // 填入验证码
      await page.fill('#verifyCode, input[name="verifyCode"]', '');
      await page.fill('#verifyCode, input[name="verifyCode"]', captchaCode);

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

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

      // 等待页面响应
      await page.waitForTimeout(3000);

      // 检查是否登录成功
      const currentUrl = page.url();
      console.log(`  登录后 URL: ${currentUrl}`);

      // 检查是否有错误提示
      const errorMsg = await page.$eval('.error-msg, .alert-danger, .login-error, .msg-error, .text-danger', el => el.textContent.trim()).catch(() => null);
      if (errorMsg) {
        console.log(`  登录失败: ${errorMsg}`);
        await refreshCaptcha(page);
        continue;
      }

      // 检查 URL 是否变化（离开登录页 = 成功）
      if (!currentUrl.includes('/home.htm')) {
        console.log('>> 登录成功！');

        // 保存 Cookie
        const cookies = await context.cookies();
        writeFileSync(COOKIE_FILE, JSON.stringify(cookies, null, 2));
        console.log(`>> Cookie 已保存（${cookies.length} 条）`);

        await page.screenshot({ path: `${SCREENSHOTS_DIR}/05-login-success.png`, fullPage: true });

        // 探索后台
        await exploreDashboard(page);

        await browser.close();
        return true;
      }

      console.log('  仍在登录页，验证码可能错误，重试...');
      await refreshCaptcha(page);
    }

    console.log('\n>> 登录失败：验证码识别 ' + MAX_CAPTCHA_RETRIES + ' 次均未成功');
    await page.screenshot({ path: `${SCREENSHOTS_DIR}/login-failed.png`, fullPage: true });
    await browser.close();
    return false;

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

// ====== 探索后台页面结构 ======
async function exploreDashboard(page) {
  console.log('\n>> ===== 探索后台页面 =====');
  console.log('>> 当前 URL:', page.url());

  // 截图
  await page.screenshot({ path: `${SCREENSHOTS_DIR}/dashboard.png`, fullPage: true });

  // 收集所有链接
  const allLinks = await page.$$eval('a', els =>
    els.map(el => ({
      text: el.textContent.trim().replace(/\s+/g, ' ').substring(0, 50),
      href: el.href,
    }))
    .filter(e => e.text && e.href && e.href.includes('dianxiaomi.com'))
    .filter((e, i, arr) => arr.findIndex(a => a.href === e.href) === i)
  );

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

  // 尝试直接访问常见的采购管理页面路径
  const possiblePaths = [
    '/saleManage/index.htm',
    '/purchaseManage/purchaseSuggestion.htm',
    '/purchaseManage/index.htm',
    '/warehouse/index.htm',
    '/stockManage/index.htm',
    '/inventory/index.htm',
  ];

  console.log('\n>> 尝试常见后台路径：');
  for (const path of possiblePaths) {
    const url = `https://www.dianxiaomi.com${path}`;
    const resp = await page.goto(url, { waitUntil: 'networkidle', timeout: 15000 }).catch(() => null);
    if (resp) {
      const finalUrl = page.url();
      const title = await page.title();
      const status = resp.status();
      console.log(`  ${status === 200 && !finalUrl.includes('/home.htm') ? '✓' : '✗'} ${path} -> ${finalUrl} [${title}]`);

      if (status === 200 && !finalUrl.includes('/home.htm')) {
        await page.screenshot({ path: `${SCREENSHOTS_DIR}/page-${path.replace(/\//g, '_')}.png`, fullPage: true });

        // 在这个页面上找导出按钮
        const exportBtns = await page.$$eval(
          'button, a, span, div',
          els => els
            .filter(el => el.textContent.includes('导出') || el.textContent.includes('下载'))
            .map(el => ({
              tag: el.tagName,
              text: el.textContent.trim().substring(0, 40),
              id: el.id,
              className: el.className?.substring(0, 60),
            }))
            .slice(0, 20)
        );
        if (exportBtns.length > 0) {
          console.log(`    导出相关按钮：`);
          for (const btn of exportBtns) {
            console.log(`      ${btn.tag}#${btn.id}.${btn.className}: "${btn.text}"`);
          }
        }
      }
    }
  }
}

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