/**
 * 店小秘自动导出脚本 - 生产版
 *
 * 流程：
 *   1. 复用 Cookie 登录（Cookie 由 login.mjs 手动登录获取）
 *   2. 采购建议 → 导出全部
 *   3. 自营仓库 → 按所有页导出
 *   4. 文件保存到 downloads/
 *
 * 首次使用：先运行 node login.mjs 手动登录获取 Cookie
 * 定时运行：crontab 每 4 小时执行 run-export.sh
 * Cookie 过期：重新运行 node login.mjs
 */
import { chromium } from 'playwright';
import { writeFileSync, readFileSync, existsSync, mkdirSync, readdirSync, appendFileSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const COOKIE_FILE = path.join(__dirname, 'cookies.json');
const SCREENSHOTS_DIR = path.join(__dirname, 'screenshots');
const DOWNLOAD_DIR = path.join(__dirname, 'downloads');
const LOG_FILE = path.join(__dirname, 'export.log');
const BASE_URL = 'https://www.dianxiaomi.com';

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

function log(msg) {
  const ts = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
  const line = `[${ts}] ${msg}`;
  console.log(line);
  try { appendFileSync(LOG_FILE, line + '\n'); } catch {}
}

function dateTag() {
  const d = new Date();
  return `${d.getFullYear()}${String(d.getMonth()+1).padStart(2,'0')}${String(d.getDate()).padStart(2,'0')}_${String(d.getHours()).padStart(2,'0')}${String(d.getMinutes()).padStart(2,'0')}`;
}

// ====== 登录（仅 Cookie 复用，过期需手动 node login.mjs）======
async function doLogin(browser) {
  log('检查登录状态...');

  if (!existsSync(COOKIE_FILE)) {
    log('✗ Cookie 不存在！请先运行: node login.mjs');
    return null;
  }

  const ctx = 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 pg = await ctx.newPage();
  await ctx.addCookies(JSON.parse(readFileSync(COOKIE_FILE, 'utf-8')));

  try {
    await pg.goto(`${BASE_URL}/home.htm`, { waitUntil: 'load', timeout: 30000 });
    const isLogged = await pg.evaluate(() =>
      document.body.innerText.includes('MiLe-kf01') || document.body.innerText.includes('待办事项')
    );
    if (isLogged) {
      log('Cookie 有效！');
      return { page: pg, context: ctx };
    }
  } catch {}

  await ctx.close();
  log('✗ Cookie 已过期！请重新运行: node login.mjs');
  return null;
}

// ====== 关闭页面上的所有弹窗/公告 ======
async function closeModals(page) {
  // 关闭 ant-modal 弹窗、公告、通知
  await page.evaluate(() => {
    // 关闭所有 ant-modal
    document.querySelectorAll('.ant-modal-wrap, .bullet-layer, .comm-modal').forEach(el => {
      el.style.display = 'none';
      el.remove();
    });
    // 关闭遮罩层
    document.querySelectorAll('.ant-modal-mask, .modal-backdrop, .v-modal').forEach(el => {
      el.style.display = 'none';
      el.remove();
    });
    // 点击所有可见的关闭按钮
    document.querySelectorAll('.ant-modal-close, .close, [class*="close-btn"]').forEach(btn => {
      if (btn.offsetHeight > 0) btn.click();
    });
  }).catch(() => {});
  await page.waitForTimeout(500);
}

// ====== 下载辅助 ======
async function doExport(page, clickAction, label) {
  log(`导出: ${label}`);
  try {
    const downloadPromise = page.waitForEvent('download', { timeout: 120000 });
    await clickAction();
    const download = await downloadPromise;
    const tag = dateTag();
    const saveName = `${tag}_${label}_${download.suggestedFilename()}`;
    const savePath = path.join(DOWNLOAD_DIR, saveName);
    await download.saveAs(savePath);
    log(`✓ 下载完成: ${saveName}`);
    return true;
  } catch (e) {
    log(`✗ 下载失败(${label}): ${e.message}`);
    await page.screenshot({ path: path.join(SCREENSHOTS_DIR, `fail-${label}.png`) }).catch(() => {});
    return false;
  }
}

// ====== 直接 URL 下载 ======
async function downloadUrl(page, url, label) {
  log(`直接下载: ${label} -> ${url.substring(0, 80)}...`);
  try {
    const downloadPromise = page.waitForEvent('download', { timeout: 60000 });
    // 通过创建 <a> 标签触发下载，避免 page.goto 的问题
    await page.evaluate((href) => {
      const a = document.createElement('a');
      a.href = href;
      a.download = '';
      document.body.appendChild(a);
      a.click();
      a.remove();
    }, url);
    const download = await downloadPromise;
    const tag = dateTag();
    const saveName = `${tag}_${label}_${download.suggestedFilename()}`;
    const savePath = path.join(DOWNLOAD_DIR, saveName);
    await download.saveAs(savePath);
    log(`✓ 下载完成: ${saveName}`);
    return true;
  } catch (e) {
    log(`✗ URL下载失败(${label}): ${e.message}`);
    return false;
  }
}

// ====== 处理采购建议导出对话框（字段选择 → 点导出 → 等下载链接）======
async function handlePurchaseExportDialog(page, label) {
  await page.waitForTimeout(2000);
  await page.screenshot({ path: path.join(SCREENSHOTS_DIR, `dialog-${label}.png`) });

  // 对话框里的"导出"按钮（蓝色按钮，和"关闭"并列）
  // 用 JavaScript 直接点，避免被其他元素挡住
  const clicked = await page.evaluate(() => {
    const btns = Array.from(document.querySelectorAll('button'));
    const exportBtn = btns.find(b =>
      b.textContent.trim() === '导出' && b.offsetHeight > 0 &&
      b.closest('.ant-modal, [class*="dialog"], [class*="modal"]')
    );
    if (exportBtn) { exportBtn.click(); return true; }
    return false;
  });

  if (!clicked) {
    log(`✗ 未找到对话框"导出"按钮 (${label})`);
    return false;
  }

  log(`  点击了对话框"导出"按钮`);
  // 等待处理（可能生成文件，可能弹出下载链接，可能直接下载）
  await page.waitForTimeout(10000);
  await page.screenshot({ path: path.join(SCREENSHOTS_DIR, `after-export-${label}.png`) });

  // 检查是否有下载链接出现
  return await clickDownloadLinks(page, label);
}

// ====== 处理仓库导出对话框（字段选择 → 点导出 → 进度条 → 下载链接）======
async function handleWarehouseExportDialog(page, label) {
  await page.waitForTimeout(2000);
  await page.screenshot({ path: path.join(SCREENSHOTS_DIR, `dialog-${label}.png`) });

  // 1. 先点对话框里的"导出"按钮
  const clicked = await page.evaluate(() => {
    const btns = Array.from(document.querySelectorAll('button'));
    const exportBtn = btns.find(b =>
      b.textContent.trim() === '导出' && b.offsetHeight > 0 &&
      b.closest('.ant-modal, [class*="dialog"], [class*="modal"]')
    );
    if (exportBtn) { exportBtn.click(); return true; }
    return false;
  });

  if (!clicked) {
    log(`✗ 仓库对话框未找到"导出"按钮`);
    return false;
  }
  log('  已点击仓库对话框"导出"按钮');

  // 2. 等进度条完成（最多等 300 秒，6000+商品需要时间）
  log('  等待仓库导出处理（6000+商品）...');
  for (let i = 0; i < 150; i++) {
    await page.waitForTimeout(2000);
    const state = await page.evaluate(() => {
      const text = document.body.innerText;
      // 精确检测：完成状态有"已导出 X 个商品"和"下载"链接
      const hasCompleted = text.includes('已导出') && text.match(/已导出.*?\d+.*?商品/);
      // 仍在处理
      const isProcessing = text.includes('导出中') && text.includes('正在导出');
      return {
        done: !!hasCompleted,
        processing: isProcessing,
        text: text.substring(text.indexOf('导出'), text.indexOf('导出') + 100),
      };
    }).catch(() => ({ done: false }));

    if (state.done) {
      log(`  仓库导出完成！ ${state.text}`);
      break;
    }
    if (i % 15 === 0 && i > 0) {
      log(`  仍在处理...（${i * 2}秒）${state.text || ''}`);
      await page.screenshot({ path: path.join(SCREENSHOTS_DIR, `progress-${label}-${i}.png`) });
    }
  }

  await page.screenshot({ path: path.join(SCREENSHOTS_DIR, `after-export-${label}.png`) });

  // 3. 查找下载链接（仓库导出完成后有"下载单品/加工SKU文件"等链接）
  const downloadLinks = await page.evaluate(() => {
    const links = Array.from(document.querySelectorAll('a'));
    return links
      .filter(a => a.textContent.includes('下载') && a.offsetHeight > 0)
      .map(a => ({ text: a.textContent.trim(), href: a.href }));
  });

  log(`  找到 ${downloadLinks.length} 个下载链接`);
  let downloaded = 0;

  for (const link of downloadLinks) {
    if (!link.href || link.href === 'null' || (!link.href.includes('.xls') && !link.href.includes('temp/'))) continue;
    log(`  下载: "${link.text}" -> ${link.href.substring(0, 80)}`);
    const ok = await downloadUrl(page, link.href, `${label}_${link.text.substring(0, 10)}`);
    if (ok) downloaded++;
    await page.waitForTimeout(1000);
  }

  // 如果没找到 <a> 链接，尝试点击按钮
  if (downloaded === 0) {
    const btns = await page.locator('a:visible:has-text("下载"), button:visible:has-text("下载")').all();
    for (let i = 0; i < btns.length; i++) {
      const text = await btns[i].textContent().catch(() => '');
      if (text.includes('下载') && !text.includes('自定导出')) {
        log(`  点击下载按钮: "${text.trim()}"`);
        const ok = await doExport(page, () => btns[i].click(), `${label}_btn${i}`);
        if (ok) downloaded++;
      }
    }
  }

  // 最后尝试用 JS 查找隐藏的下载 URL
  if (downloaded === 0) {
    const hiddenLinks = await page.evaluate(() => {
      const all = Array.from(document.querySelectorAll('a[href*=".xls"], a[href*="temp/"], a[href*="download"]'));
      return all.map(a => ({ text: a.textContent.trim(), href: a.href }));
    });
    for (const l of hiddenLinks) {
      if (l.href.includes('.xls') || l.href.includes('temp/')) {
        log(`  隐藏链接: "${l.text}" -> ${l.href.substring(0, 80)}`);
        const ok = await downloadUrl(page, l.href, `${label}_hidden`);
        if (ok) downloaded++;
      }
    }
  }

  return downloaded > 0;
}

// ====== 点击所有"下载"链接 ======
async function clickDownloadLinks(page, label) {
  let downloaded = 0;

  // 查找所有包含"下载"文字的链接/按钮
  const downloadLinks = await page.locator('a:has-text("下载"), button:has-text("下载")').all();
  log(`  找到 ${downloadLinks.length} 个下载链接`);

  for (let i = 0; i < downloadLinks.length; i++) {
    const link = downloadLinks[i];
    if (!(await link.isVisible().catch(() => false))) continue;
    const text = await link.textContent().catch(() => '');
    const href = await link.getAttribute('href').catch(() => '');
    log(`  下载: "${text.trim()}" href="${href}"`);

    if (href && (href.includes('.xls') || href.includes('.csv') || href.includes('temp/'))) {
      // 直接 URL 下载
      const fullUrl = href.startsWith('http') ? href : `${BASE_URL}${href}`;
      const ok = await downloadUrl(page, fullUrl, `${label}_${i + 1}`);
      if (ok) downloaded++;
    } else {
      // 点击按钮下载
      const ok = await doExport(page, () => link.click(), `${label}_${i + 1}`);
      if (ok) downloaded++;
    }
    await page.waitForTimeout(2000);
  }

  if (downloaded === 0) {
    log(`  未成功下载任何文件，尝试用 JS 查找隐藏链接...`);
    // 有些下载链接可能是通过 window.open 或 location.href
    const links = await page.evaluate(() => {
      const els = document.querySelectorAll('a[href*="download"], a[href*="export"], a[href*=".xls"], a[href*=".csv"]');
      return Array.from(els).map(a => ({ text: a.textContent.trim(), href: a.href }));
    });
    if (links.length) {
      log('  找到直接下载链接:');
      links.forEach(l => log(`    ${l.text} -> ${l.href}`));
      for (const l of links) {
        // 跳过非文件链接
        if (!l.href.includes('.xls') && !l.href.includes('.csv') && !l.href.includes('.zip') &&
            !l.href.includes('download') && !l.href.includes('temp/')) continue;
        const ok = await downloadUrl(page, l.href, `${label}_${l.text.substring(0, 10)}`);
        if (ok) downloaded++;
      }
    }
  }

  return downloaded > 0;
}

// ====== 采购建议页面 ======
async function exportPurchase(page) {
  log('\n===== 采购建议 =====');

  // --- 导出全部 ---
  await page.goto(`${BASE_URL}/purchasingProposal/index.htm?state=3`, { waitUntil: 'load', timeout: 30000 });
  await page.waitForTimeout(5000);
  await closeModals(page);

  const dropdown1 = await page.locator('text=导出建议').first();
  if (await dropdown1.isVisible().catch(() => false)) {
    await dropdown1.click();
    await page.waitForTimeout(1500);

    const exportAllItem = await page.locator('text=导出全部').first();
    if (await exportAllItem.isVisible().catch(() => false)) {
      await exportAllItem.click(); // 弹出字段选择对话框
      await handlePurchaseExportDialog(page, '采购_导出全部');
    } else {
      log('✗ 未找到"导出全部"菜单项');
    }
  } else {
    log('✗ 未找到"导出建议"按钮');
  }

  await page.waitForTimeout(3000);

  // --- 导出建议 ---
  await page.goto(`${BASE_URL}/purchasingProposal/index.htm?state=3`, { waitUntil: 'load', timeout: 30000 });
  await page.waitForTimeout(5000);
  await closeModals(page);

  const dropdown2 = await page.locator('text=导出建议').first();
  if (await dropdown2.isVisible().catch(() => false)) {
    await dropdown2.click();
    await page.waitForTimeout(1500);

    const exportSuggItem = await page.locator('text=导出勾选项').first();
    if (await exportSuggItem.isVisible().catch(() => false)) {
      await exportSuggItem.click();
      await handlePurchaseExportDialog(page, '采购_导出勾选项');
    }
  }
}

// ====== 自营仓库页面 ======
async function exportWarehouse(page) {
  log('\n===== 自营仓库 =====');
  await page.goto(`${BASE_URL}/warehouseProduct/index.htm`, { waitUntil: 'load', timeout: 30000 });
  await page.waitForTimeout(5000);
  await closeModals(page);
  await page.screenshot({ path: path.join(SCREENSHOTS_DIR, 'page-仓库.png'), fullPage: true });

  // 1. 点击"导入/导出"展开下拉
  const importExportBtn = await page.locator('text=导入/导出').first();
  if (!(await importExportBtn.isVisible().catch(() => false))) {
    log('✗ 未找到"导入/导出"按钮');
    return;
  }

  await importExportBtn.click();
  await page.waitForTimeout(1500);

  // 2. 点"按所有页导出"
  const allPagesBtn = await page.locator('text=按所有页导出').first();
  if (!(await allPagesBtn.isVisible().catch(() => false))) {
    log('✗ 未找到"按所有页导出"');
    return;
  }

  await allPagesBtn.click();
  await page.waitForTimeout(2000);

  // 3. 等进度条完成，下载文件
  await handleWarehouseExportDialog(page, '仓库_全部导出');
}

// ====== 主流程 ======
async function main() {
  log('========================================');
  log('店小秘自动导出 启动');
  log('========================================\n');

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

  try {
    const session = await doLogin(browser);
    if (!session) { log('登录失败'); await browser.close(); return false; }

    const { page, context } = session;

    await exportPurchase(page);
    await exportWarehouse(page);

    // 统计
    const tag = dateTag().substring(0, 8);
    const files = readdirSync(DOWNLOAD_DIR).filter(f => f.startsWith(tag));
    log(`\n今日已下载 ${files.length} 个文件:`);
    files.forEach(f => log(`  📄 ${f}`));

    await context.close();
    await browser.close();
    log('\n✓ 导出完成\n');
    return true;
  } catch (e) {
    log(`致命错误: ${e.message}`);
    await browser.close();
    return false;
  }
}

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