# -*- coding: utf-8 -*-
import io, os, subprocess, time, html as H

SRC = r"D:\workbbbbbb\排班工具.html"
OUT = r"D:\workbbbbbb\build\_fx2_e2e.html"
DOM = r"D:\workbbbbbb\build\_fx2_dom.html"
TXT = r"D:\workbbbbbb\build\_fx2_out.txt"

ERRTRAP = '<script>window.__ERRS=[];window.addEventListener("error",function(e){window.__ERRS.push((e.message||"")+" @"+e.lineno);});</script>'

TEST = r"""
<div id="E2E">PENDING</div>
<script>
(function () {
  var out = [], done = false;
  function push(s) { out.push(s); }
  function flush() { document.getElementById('E2E').textContent = out.join(' || '); }
  function run() {
    if (done) return; done = true;
    try {
      var st = window.__PB.state();
      // 1. 勾选弹性模式
      var fm = document.getElementById('flexMode');
      push('flexBox=' + !!fm);
      fm.checked = true;
      fm.dispatchEvent(new Event('change', { bubbles: true }));
      push('addBtn=' + document.getElementById('btnAddPlan').textContent);
      // 2. 只选周三、周四、周五
      function chipOf(d) { return document.querySelector('#dayChips .chip[data-day="' + d + '"]'); }
      function onDays() {
        var a = [];
        Array.prototype.forEach.call(document.querySelectorAll('#dayChips .chip[data-day]'), function (c) {
          if (c.classList.contains('on')) a.push(parseInt(c.getAttribute('data-day'), 10));
        });
        return a.sort();
      }
      [0, 1, 5, 6].forEach(function (d) {
        var c = chipOf(d);
        if (c && c.classList.contains('on')) c.click();
      });
      [2, 3, 4].forEach(function (d) {
        var c = chipOf(d);
        if (c && !c.classList.contains('on')) c.click();
      });
      push('daysOn=' + onDays().join(','));
      // 3. 选机构 拱宸桥支行
      var inp = document.getElementById('orgInput');
      inp.value = '拱宸桥';
      inp.dispatchEvent(new Event('input', { bubbles: true }));
      var sug = document.querySelector('#orgSug div[data-i]');
      push('sug=' + (sug ? sug.textContent : 'none'));
      if (sug) sug.click();
      push('picked=' + document.getElementById('pickedName').textContent);
      document.getElementById('btnAddPlan').click();
      var pl = st.plans[st.plans.length - 1];
      push('plans=' + st.plans.length);
      push('plFlex=' + (pl && pl.flex));
      push('plCands=' + (pl && pl.cands ? pl.cands.join(',') : 'none'));
      // 4. 生成
      document.getElementById('btnGen').click();
      var r = st.lastResult;
      push('rows=' + (r.rows || []).length);
      var fr = (r.rows || []).filter(function (x) { return x.flex; })[0];
      push('flexRow=' + (fr ? 'yes' : 'none'));
      if (fr) {
        push('fday=' + fr.day);
        push('finCands=' + (fr.cands || []).join(','));
        push('onlyWorkday=' + (fr.day <= 4));
        push('members=' + fr.members.join(','));
      }
      var sameOrgRows = (r.rows || []).filter(function (x) { return x.org.indexOf('拱宸桥') >= 0; });
      push('orgRows=' + sameOrgRows.length);
      push('orgDays=' + sameOrgRows.map(function (x) { return x.day; }).join(','));
      // 5. 结果表里有黄色标记与"就这天"
      var wrap = document.getElementById('resultWrap');
      push('flexTagInUi=' + (wrap.innerHTML.indexOf('弹性·候选') >= 0));
      push('okBtn=' + (wrap.innerHTML.indexOf('data-flexok') >= 0));
      push('selBox=' + (wrap.innerHTML.indexOf('data-flexsel') >= 0));
      // 6. 导出表（确认前，应标「弹性任务」）
      var tb0 = window.__PB.resultTable ? window.__PB.resultTable() : null;
      push('tblBefore=' + (tb0 ? tb0.length : 'none'));
      if (tb0) {
        var fr0 = tb0.filter(function (r) { return r[0] === '弹性任务'; });
        push('tblFlexRows=' + fr0.length);
        if (fr0.length) push('tblFlexDay=' + fr0[0][1]);
      }
      // 7. 点"就这天"确认
      var ok = wrap.querySelector('button[data-flexok]');
      if (ok) ok.click();
      var pl2 = st.plans[st.plans.length - 1];
      push('afterOkFlex=' + pl2.flex);
      push('afterOkDay=' + pl2.day);
      push('afterOkCands=' + (pl2.cands ? 'still' : 'gone'));
      var r2 = st.lastResult;
      push('afterRows=' + (r2.rows || []).length);
      push('afterFlexRow=' + ((r2.rows || []).filter(function (x) { return x.flex; }).length));
      // 7. 导出表
      var tb = window.__PB.resultTable ? window.__PB.resultTable() : null;
      push('tbl=' + (tb ? tb.length : 'none'));
      if (tb && tb.length > 1) push('tblType=' + tb[tb.length - 1][0]);
      push('ERRS=' + ((window.__ERRS || []).join(' ; ') || 'none'));
    } catch (e) { push('ERR ' + e.message); push('ERRS=skip'); }
    flush();
  }
  if (document.readyState === 'complete') run(); else window.addEventListener('load', function () { setTimeout(run, 300); });
  setTimeout(function () { if (!done) { run(); } }, 4000);
})();
</script>
"""


def main():
    with io.open(SRC, encoding='utf-8') as f:
        h = f.read()
    i = h.find('<script>window.__PAIBAN_DATA__')
    h = h[:i] + ERRTRAP + h[i:]
    e = h.rfind('</body>')
    h = h[:e] + TEST + h[e:]
    with io.open(OUT, 'w', encoding='utf-8') as f:
        f.write(h)
    print('built', os.path.getsize(OUT))

    edge = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
    subprocess.run(['taskkill', '/F', '/IM', 'msedge.exe'], capture_output=True)
    time.sleep(2)
    prof = 'C:/Windows/Temp/e2eFX%d' % (int(time.time()) % 100000)
    r = subprocess.run([edge, '--headless=new', '--disable-gpu', '--user-data-dir=' + prof,
                        '--virtual-time-budget=15000', '--dump-dom', OUT], capture_output=True)
    with io.open(DOM, 'wb') as f:
        f.write(r.stdout)
    print('dom', len(r.stdout))

    with io.open(DOM, encoding='utf-8', errors='replace') as f:
        s = f.read()
    k = s.find('id="E2E"')
    if k < 0:
        txt = 'NO_E2E dom=%d' % len(s)
    else:
        b = s.find('>', k) + 1
        e2 = s.find('</div>', b)
        txt = H.unescape(s[b:e2]).strip()
    with io.open(TXT, 'w', encoding='utf-8') as f:
        f.write(txt)
    print('extracted', len(txt))


main()
