/**
 * 店小秘全自动登录 v7
 * 纯 HTTP 请求登录（不走浏览器 DOM），更稳定
 * 登录成功后把 Cookie 给浏览器用于后续导出操作
 */
import { chromium } from 'playwright';
import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
import { execSync } from 'child_process';
import sharp from 'sharp';
import https from 'https';
import http from 'http';

const COOKIE_FILE = './cookies.json';
const SCREENSHOTS_DIR = './screenshots';
const DOWNLOAD_DIR = './downloads';
const MAX_RETRIES = 20;

mkdirSync(SCREENSHOTS_DIR, { recursive: true });
mkdirSync(DOWNLOAD_DIR, { recursive: true });

// ====== HTTP 请求辅助 ======
function httpGet(url, cookies = '') {
  return new Promise((resolve, reject) => {
    const mod = url.startsWith('https') ? https : http;
    const req = mod.get(url, {
      headers: {
        'Cookie': cookies,
        'User-Agent': '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',
      },
    }, (res) => {
      const setCookies = res.headers['set-cookie'] || [];
      const chunks = [];
      res.on('data', c => chunks.push(c));
      res.on('end', () => resolve({
        status: res.statusCode,
        headers: res.headers,
        setCookies,
        body: Buffer.concat(chunks),
      }));
    });
    req.on('error', reject);
    req.setTimeout(15000, () => { req.destroy(); reject(new Error('timeout')); });
  });
}

function httpPost(url, data, cookies = '') {
  return new Promise((resolve, reject) => {
    const mod = url.startsWith('https') ? https : http;
    const body = new URLSearchParams(data).toString();
    const urlObj = new URL(url);
    const req = mod.request({
      hostname: urlObj.hostname,
      path: urlObj.pathname,
      method: 'POST',
      headers: {
        'Cookie': cookies,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(body),
        'User-Agent': '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',
        'X-Requested-With': 'XMLHttpRequest',
        'Referer': 'https://www.dianxiaomi.com/home.htm',
      },
    }, (res) => {
      const setCookies = res.headers['set-cookie'] || [];
      const chunks = [];
      res.on('data', c => chunks.push(c));
      res.on('end', () => resolve({
        status: res.statusCode,
        headers: res.headers,
        setCookies,
        body: Buffer.concat(chunks).toString('utf-8'),
      }));
    });
    req.on('error', reject);
    req.setTimeout(15000, () => { req.destroy(); reject(new Error('timeout')); });
    req.write(body);
    req.end();
  });
}

function parseCookies(setCookieHeaders) {
  const map = {};
  for (const h of setCookieHeaders) {
    const parts = h.split(';')[0].split('=');
    if (parts.length >= 2) {
      map[parts[0].trim()] = parts.slice(1).join('=').trim();
    }
  }
  return map;
}

function cookieString(map) {
  return Object.entries(map).map(([k, v]) => `${k}=${v}`).join('; ');
}

// ====== OCR ======
async function ocrCaptcha(imageBuffer) {
  const rawPath = `${SCREENSHOTS_DIR}/captcha_raw.png`;
  writeFileSync(rawPath, imageBuffer);

  const presets = [
    async (s, d) => sharp(s).grayscale().resize({ width: 468 }).normalize().sharpen({ sigma: 1.5 }).threshold(130).toFile(d),
    async (s, d) => sharp(s).grayscale().resize({ width: 468 }).normalize().threshold(100).toFile(d),
    async (s, d) => sharp(s).grayscale().resize({ width: 468 }).normalize().threshold(160).toFile(d),
    async (s, d) => sharp(s).resize({ width: 468 }).toFile(d),
    async (s, d) => sharp(s).grayscale().resize({ width: 468 }).negate().normalize().threshold(128).toFile(d),
    async (s, d) => sharp(s).grayscale().resize({ width: 600 }).normalize().sharpen({ sigma: 3 }).threshold(120).toFile(d),
  ];

  for (let i = 0; i < presets.length; i++) {
    const p = `${SCREENSHOTS_DIR}/cap_p${i}.png`;
    try { await presets[i](rawPath, p); } catch { continue; }
    for (const psm of ['7', '8']) {
      try {
        const r = execSync(
          `tesseract "${p}" stdout --psm ${psm} -c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`,
          { encoding: 'utf-8', timeout: 10000 }
        ).trim().replace(/[\s\n\r]/g, '');
        if (r && r.length === 4) return r;
      } catch {}
    }
  }
  // fallback
  for (let i = 0; i < presets.length; i++) {
    const p = `${SCREENSHOTS_DIR}/cap_p${i}.png`;
    if (!existsSync(p)) continue;
    try {
      const r = execSync(
        `tesseract "${p}" stdout --psm 7 -c tessedit_char_whitelist=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`,
        { encoding: 'utf-8', timeout: 10000 }
      ).trim().replace(/[\s\n\r]/g, '');
      if (r && r.length >= 3) return r.substring(0, 4);
    } catch {}
  }
  return null;
}

// ====== 纯 HTTP 登录 ======
async function httpLogin() {
  console.log('====== 纯 HTTP 登录 ======\n');

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

    try {
      // 1) 获取初始页面和 Session Cookie
      const homeResp = await httpGet('https://www.dianxiaomi.com/home.htm');
      const cookies = parseCookies(homeResp.setCookies);
      console.log(`  Session: ${Object.keys(cookies).join(', ')}`);

      // 2) 下载验证码图片（同一 Session）
      const captchaResp = await httpGet(
        `https://www.dianxiaomi.com/verify/code.htm?t=${Date.now()}`,
        cookieString(cookies)
      );

      // 合并新 Cookie
      Object.assign(cookies, parseCookies(captchaResp.setCookies));

      // 3) OCR 验证码
      const code = await ocrCaptcha(captchaResp.body);
      if (!code) {
        console.log('  OCR 失败，重试');
        continue;
      }
      console.log(`  验证码: "${code}"`);

      // 4) POST 登录
      const loginResp = await httpPost(
        'https://www.dianxiaomi.com/user/userLoginNew2.json',
        {
          account: 'MiLe-kf01',
          password: 'Vxdas@302',
          verifyCode: code,
          remeber: 'on',
          loginReadAndAccept: 'on',
          url: '',
        },
        cookieString(cookies)
      );

      // 合并登录后的 Cookie
      Object.assign(cookies, parseCookies(loginResp.setCookies));

      console.log(`  API 响应: ${loginResp.body.substring(0, 300)}`);

      const data = JSON.parse(loginResp.body);

      if (data.code === 0 || (data.url && !data.error)) {
        console.log('\n>> ★★★ 登录成功！★★★');
        console.log(`>> 跳转: ${data.url}`);

        // 保存 Cookie（转换为 Playwright 格式）
        const playwrightCookies = Object.entries(cookies).map(([name, value]) => ({
          name,
          value,
          domain: 'www.dianxiaomi.com',
          path: '/',
          httpOnly: false,
          secure: false,
          sameSite: 'Lax',
        }));

        // 补充 .dianxiaomi.com 域的 Cookie
        for (const [name, value] of Object.entries(cookies)) {
          playwrightCookies.push({
            name,
            value,
            domain: '.dianxiaomi.com',
            path: '/',
            httpOnly: false,
            secure: false,
            sameSite: 'Lax',
          });
        }

        writeFileSync(COOKIE_FILE, JSON.stringify(playwrightCookies, null, 2));
        console.log(`>> Cookie 已保存`);

        return { success: true, cookies, redirectUrl: data.url };
      }

      const err = data.error || '';
      console.log(`  失败: ${err}`);

      if (err.includes('密码错误') || err.includes('不存在') || err.includes('锁定') || err.includes('禁用')) {
        console.log('>> 账号/密码问题，停止');
        return { success: false };
      }

      // 验证码错误继续重试
    } catch (e) {
      console.log(`  请求错误: ${e.message}`);
    }

    // 稍等再重试
    await new Promise(r => setTimeout(r, 1000));
  }

  return { success: false };
}

// ====== 浏览器探索后台 ======
async function exploreWithBrowser(httpCookies, redirectUrl) {
  console.log('\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',
  });

  // 设置 Cookie
  const playwrightCookies = Object.entries(httpCookies).map(([name, value]) => ({
    name, value,
    domain: '.dianxiaomi.com',
    path: '/',
  }));
  await context.addCookies(playwrightCookies);

  const page = await context.newPage();

  // 跳转到后台
  const target = redirectUrl?.startsWith('/') ? `https://www.dianxiaomi.com${redirectUrl}` : 'https://www.dianxiaomi.com/saleManage/index.htm';
  console.log(`>> 打开: ${target}`);
  await page.goto(target, { waitUntil: 'networkidle', timeout: 30000 }).catch(() => {});

  console.log(`>> URL: ${page.url()}`);
  console.log(`>> 标题: ${await page.title()}`);

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

  // 获取页面文本
  const text = await page.evaluate(() => document.body?.innerText?.substring(0, 8000));
  console.log('>> 页面文本:\n', text);

  // 所有链接
  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?.includes('dianxiaomi'))
    .filter((e, i, arr) => arr.findIndex(a => a.href === e.href) === i)
  );

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

  // 尝试关键路径
  const paths = [
    '/saleManage/index.htm',
    '/purchaseManage/purchaseSuggestion.htm',
    '/purchaseManage/purchaseOrder.htm',
    '/stockManage/stockList.htm',
  ];

  for (const p of paths) {
    try {
      await page.goto(`https://www.dianxiaomi.com${p}`, { waitUntil: 'domcontentloaded', timeout: 15000 });
      const t = await page.title();
      const ok = !t.includes('Error') && !page.url().includes('/home.htm');
      console.log(`\n  ${ok ? '✓' : '✗'} ${p} [${t}]`);
      if (ok) {
        await page.screenshot({ path: `${SCREENSHOTS_DIR}/page${p.replace(/\//g, '_')}.png`, fullPage: true });
        const btns = await page.$$eval('button, a.btn, .btn', els =>
          els.map(el => ({
            tag: el.tagName, text: el.textContent.trim().substring(0, 50),
            id: el.id, cls: (el.className || '').substring(0, 60),
          })).filter(e => e.text).slice(0, 30)
        );
        if (btns.length) {
          console.log('  按钮：');
          btns.forEach(b => console.log(`    ${b.tag}#${b.id}: "${b.text}"`));
        }
      }
    } catch { console.log(`  ✗ ${p} 超时`); }
  }

  // 重新保存完整 Cookie
  const allCookies = await context.cookies();
  writeFileSync(COOKIE_FILE, JSON.stringify(allCookies, null, 2));

  await browser.close();
}

// ====== 执行 ======
const result = await httpLogin();
if (result.success) {
  await exploreWithBrowser(result.cookies, result.redirectUrl);
} else {
  console.log('\n>> 登录失败，退出');
  process.exit(1);
}
