// FILE: _St/IG_StYellow/test_ext_side_operator_manual_v275.js | ROLE: IG_StYellow 회귀 테스트
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const vm = require('vm');

const root = __dirname;
const side = fs.readFileSync(path.join(root, 'side.js'), 'utf8');
const html = fs.readFileSync(path.join(root, 'side.html'), 'utf8');
const content = fs.readFileSync(path.join(root, 'content_instagram.js'), 'utf8');
const manifest = JSON.parse(fs.readFileSync(path.join(root, 'manifest.json'), 'utf8'));

assert.strictEqual(manifest.version, '2.3.8.3130');
assert.strictEqual(manifest.version_name, '2.3.8.313');
assert.ok(side.includes('const IGBLUE_PACKAGE_VERSION = IGBLUE_BUILD_TAG;'));

// Korean control labels and default enabled state.
assert.ok(html.includes('<span>자동실행 사용</span>'));
assert.ok(html.includes('id="igblue_auto_py_start" disabled>시작</button>'));
assert.ok(!html.includes('<span>Auto PY</span>'));
assert.ok(side.includes('cb.checked = "1" === teLocalGet("download/auto_py", "1");'));
assert.ok(side.includes('startBtn.textContent = "시작";'));

// tab_id belongs to mode 3 count line and settings remains right aligned.
const titlePos = html.indexOf('다운로드 방식 3 · Top sorted 자동');
const tabPos = html.indexOf('igblue-auto-tab-id-badge', titlePos);
const countPos = html.indexOf('개수:', tabPos);
const autoPos = html.indexOf('<span>자동실행 사용</span>');
assert.ok(titlePos >= 0 && tabPos > titlePos && countPos > tabPos && autoPos > countPos);
assert.strictEqual((html.match(/igblue-auto-tab-id-badge/g) || []).length, 1);
assert.ok(html.includes('.foot-changes #settings { margin-left:auto; flex:0 0 auto; }'));

// Obsolete bulk displayed-account button is removed. Clicking the Side IG label selects one target.
assert.ok(!html.includes('id="igblue_account_url_current"'));
assert.ok(!html.includes('표시계정추가'));
assert.ok(side.includes('function teSelectSideAccountAddTarget(media, element)'));
assert.ok(side.includes('teAutoPySetCurrentAccountAddTarget(account, "side_account_click", shortcode);'));
assert.ok(side.includes('accountLabel.addEventListener("click"'));
assert.ok(side.includes('teCurrentAccountAddTarget.source === "side_account_click"'));
assert.ok(!side.includes('teCurrentAccountAddManualSelectionUrl'));
assert.ok(!side.includes('teAutoPyStartCurrentAccountAddTracking'));
assert.ok(html.includes('disabled>IG 계정 선택</button>'));

// Manual click start is emitted immediately from both Side and MAIN manual buttons.
assert.ok(side.includes('function teNotifyManualDownloadStart(media, assetKind, mediaIndex = 0, meta = null)'));
assert.ok(side.includes('manual_click: true'));
assert.ok(side.includes('source_mode: "MANUAL_SINGLE"'));
assert.ok(side.includes('teNotifyManualDownloadStart(media, "image", 0, meta);'));
assert.ok(side.includes('teNotifyManualDownloadStart(media, "video", 0, meta);'));
assert.ok(!content.includes('message: "수동 다운로드 시작"'), 'v279a content relay must use the v262 single transfer start path');
assert.ok(!content.includes('manual_click: true'), 'v279a content relay must not add the later duplicate manual-start marker');

// Execute the Side helper contract: one manual start payload with exact shortcode/asset.
function extractFunction(source, name) {
  const start = source.indexOf(`function ${name}(`);
  assert.ok(start >= 0, `${name} missing`);
  const open = source.indexOf('{', start);
  let depth = 0;
  for (let i = open; i < source.length; i += 1) {
    if (source[i] === '{') depth += 1;
    else if (source[i] === '}') {
      depth -= 1;
      if (depth === 0) return source.slice(start, i + 1);
    }
  }
  throw new Error(`${name} close missing`);
}
const sent = [];
const sandbox = {
  Math, Number, String, Object,
  teSendToTargetTab(payload) { sent.push(payload); return Promise.resolve(true); }
};
vm.createContext(sandbox);
vm.runInContext(`${extractFunction(side, 'teNotifyManualDownloadStart')}; result = teNotifyManualDownloadStart({code:'ABC123'}, 'video', 0, {owner_username:'tester'});`, sandbox);
assert.strictEqual(sandbox.result, true);
assert.strictEqual(sent.length, 1);
assert.strictEqual(sent[0].status, 'start');
assert.strictEqual(sent[0].shortcode, 'ABC123');
assert.strictEqual(sent[0].asset_kind, 'video');
assert.strictEqual(sent[0].manual_click, true);
assert.strictEqual(sent[0].source_mode, 'MANUAL_SINGLE');

console.log('OK test_ext_side_operator_manual_v275');
