// 无头 E2E: 非标档位在线生成 (二期) — 按钮升级/立即命中下载/排队轮询下载
// 前置: 站点 config.js 的 api 已指向本地 GenServer (匿名模式); GenServer 已启动
// 用法: node e2e-gen.js <siteUrl> <jobsDir> <outputDir>
const fs = require('fs');
const path = require('path');
let chromium;
try { chromium = require('playwright-core').chromium; }
catch (e) { chromium = require('C:/Users/ruigu/AppData/Local/Temp/nds3dtest/node_modules/playwright-core').chromium; }
const edge = 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe';

(async () => {
  const url = process.argv[2] || 'http://localhost:8080/';
  const jobsDir = process.argv[3];
  const outputDir = process.argv[4];
  const browser = await chromium.launch({ executablePath: edge, headless: true });
  const context = await browser.newContext({ acceptDownloads: true, viewport: { width: 1600, height: 900 } });
  const page = await context.newPage();
  const errs = [];
  page.on('pageerror', e => errs.push(e.message));
  await page.goto(url, { waitUntil: 'domcontentloaded' });
  await page.waitForTimeout(2500);

  let pass = 0, fail = 0;
  const out = [];
  const check = (name, ok) => { out.push((ok ? 'PASS ' : 'FAIL ') + name); if (ok) pass++; else fail++; };

  // KC 系列
  const names = await page.$$eval('.tree .series', els => els.map(e => e.textContent.trim()));
  await (await page.$$('.tree .series'))[names.findIndex(n => n.indexOf('KC') === 0)].click();
  await page.waitForTimeout(500);

  const setSel = async (code, val) => { await page.selectOption('#sel-' + code, val); await page.waitForTimeout(250); };
  const setStroke = async (v) => { await page.fill('#sel-stroke', String(v)); await page.dispatchEvent('#sel-stroke', 'change'); await page.waitForTimeout(400); };
  const btn = async () => page.$eval('#btnDownload', el => ({ text: el.textContent, disabled: el.disabled, hidden: el.classList.contains('hidden') }));

  // 1) 非标 87 (输出目录已预置) → 按钮=在线生成数模; 点击 → immediate → 触发下载
  await setSel('type', '00'); await setSel('bore', '32'); await setStroke(87);
  await setSel('magnet', '__EMPTY__'); await setSel('mount', '__EMPTY__'); await page.waitForTimeout(400);
  var b = await btn();
  check('非标按钮 = 在线生成数模 且可用 (实际: ' + b.text + (b.disabled ? '/disabled' : '/enabled') + ')',
    b.text.indexOf('在线生成') >= 0 && !b.disabled);
  var dlEvent = null;
  page.waitForEvent('download', { timeout: 10000 }).then(d => { dlEvent = d; }).catch(() => { });
  await page.click('#btnDownload');
  await page.waitForTimeout(2500);
  check('立即命中 → 触发全格式 zip 下载', dlEvent !== null);
  var st = await page.$eval('#status', el => el.textContent);
  check('状态含 就绪/下载 (实际: ' + st.trim() + ')', st.indexOf('就绪') >= 0 || st.indexOf('下载') >= 0);

  // 2) 非标 88 (无输出) → 点击 → 排队/生成中 → 外部模拟 worker 完成 → 触发下载
  await setStroke(88); await page.waitForTimeout(400);
  b = await btn();
  check('非标 88 按钮可用', b.text.indexOf('在线生成') >= 0 && !b.disabled);
  dlEvent = null;
  page.waitForEvent('download', { timeout: 30000 }).then(d => { dlEvent = d; }).catch(() => { });
  await page.click('#btnDownload');
  await page.waitForTimeout(4000);
  b = await btn();
  check('点击后进入生成/排队态 (实际: ' + b.text + ')', b.text.indexOf('生成') >= 0 || b.text.indexOf('队列') >= 0);
  // 模拟 worker: 认领 .json → .running → 造输出 → 写 .done
  const jobs = fs.readdirSync(jobsDir).filter(f => f.startsWith('job_') && f.endsWith('.json'));
  if (jobs.length) {
    const jf = path.join(jobsDir, jobs[0]);
    const rf = jf.replace(/\.json$/, '.running');
    fs.renameSync(jf, rf);
    const o = path.join(outputDir, 'KC', 'KC0032-88');
    fs.mkdirSync(o, { recursive: true });
    ['KC0032-88.stp', 'KC0032-88.x_t', 'KC0032-88.igs', 'KC0032-88.stl'].forEach(f => fs.writeFileSync(path.join(o, f), 'FAKE ' + f));
    fs.writeFileSync(jf.replace(/\.json$/, '.done'), JSON.stringify({
      ok: true, error: '',
      items: [{ series: 'KC', code: 'KC0032-88', ok: true, hit: false, files: ['KC0032-88.stp', 'KC0032-88.x_t', 'KC0032-88.igs', 'KC0032-88.stl'] }]
    }));
    fs.unlinkSync(rf);
    check('模拟 worker 完成写入', true);
  } else {
    check('任务已入队 (jobs 目录可见)', jobs.length > 0);
  }
  await page.waitForTimeout(12000);   // 轮询间隔 3s, 等状态刷新并触发下载
  check('排队轮询 → 完成后触发下载', dlEvent !== null);

  // 3) 标准档位回归: stroke=10 → 按钮回 下载 STEP 可用
  await setStroke(10); await page.waitForTimeout(400);
  b = await btn();
  check('标准档位按钮回 下载 STEP (实际: ' + b.text + ')', b.text.indexOf('下载 STEP') >= 0 && !b.disabled && !b.hidden);

  console.log(out.join('\n'));
  console.log('结果: ' + pass + ' 通过, ' + fail + ' 失败 | 页面错误: ' + (errs.length ? errs.join(' | ') : '无'));
  await browser.close();
  process.exit(fail ? 1 : 0);
})().catch(e => { console.error('FAIL:', e.message); process.exit(1); });
