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 manifest = JSON.parse(fs.readFileSync(path.join(root, 'manifest.json'), 'utf8'));

assert.strictEqual(manifest.version, '2.3.8.276');
assert.strictEqual(manifest.version_name, '2.3.8.276');
assert.ok(side.includes('const IGBLUE_PACKAGE_VERSION = "v276";'));

// tab_id remains unique and is placed before the Top sorted count, not between auto controls.
assert.strictEqual((html.match(/<span class="igblue-tab-id-badge/g) || []).length, 1);
const topTitle = html.indexOf('다운로드 방식 3 · Top sorted 자동');
const tabBadge = html.indexOf('igblue-auto-tab-id-badge', topTitle);
const topCount = html.indexOf('개수:', tabBadge);
const autoLabel = html.indexOf('<span>자동실행 사용</span>');
const startButton = html.indexOf('id="igblue_auto_py_start"');
assert.ok(topTitle >= 0 && tabBadge > topTitle && topCount > tabBadge);
assert.ok(autoLabel >= 0 && startButton > autoLabel);
assert.ok(!html.slice(autoLabel, startButton).includes('igblue-auto-tab-id-badge'));
assert.ok(side.includes('function teAutoPyDisplayTabId()'));
assert.ok(side.includes('자동실행 tab_id: ${id || "-"}'));

// 0/N on a non-Instagram page must not enter the running/wait loop.
assert.ok(side.includes('const indexedUrlStart = !!('));
assert.ok(side.includes('현재 페이지가 Instagram 페이지가 아닙니다. Instagram 페이지에서 시작을 눌러주세요.'));
assert.ok(side.includes('return { ok: false, error: "start_instagram_tab_required" };'));

// Stop cleanup is bounded; no permanent stopping=true state.
const stopStart = side.indexOf('async function teAutoPyStop(reason)');
const stopEnd = side.indexOf('function teAutoPyStopReasonKo', stopStart);
assert.ok(stopStart >= 0 && stopEnd > stopStart);
const stopBlock = side.slice(stopStart, stopEnd);
assert.ok(stopBlock.includes('await Promise.race(['));
assert.ok(stopBlock.includes('teSleep(900)'));
assert.ok(stopBlock.includes('teAutoPyStopping = false;'));
assert.ok(stopBlock.includes('teAutoPyStatsFinish("user_stop_complete")'));

// Automatic end keeps Auto PY enabled so Start becomes usable after finally cleanup.
const endStart = side.indexOf('function teAutoPyFinalizeAutomaticEnd(reason, meta)');
const endEnd = side.indexOf('function teAutoPyFinishAccountQueue', endStart);
assert.ok(endStart >= 0 && endEnd > endStart);
const endBlock = side.slice(endStart, endEnd);
assert.ok(endBlock.includes('teAutoEtaPersist("automatic_end")'));
assert.ok(!endBlock.includes('cb.checked = false'));
assert.ok(!endBlock.includes('teLocalSet("download/auto_py", "0")'));

// Whole queue ETA uses current account remainder plus all later account targets.
const remainStart = side.indexOf('function teAutoPyRemainingPostsForEta');
const remainEnd = side.indexOf('function teAutoPyAveragePostDownloadMs', remainStart);
assert.ok(remainStart >= 0 && remainEnd > remainStart);
const remainCode = side.slice(remainStart, remainEnd) + '\nthis.remaining = teAutoPyRemainingPostsForEta;';
const context = { Math, Number };
vm.runInNewContext(remainCode, context, { filename: 'auto_eta_v274.js' });
assert.strictEqual(context.remaining(11, 44, 3, 1), 101);
assert.strictEqual(context.remaining(3, 3, 3, 3), 0);
assert.strictEqual(context.remaining(0, 44, 3, 0), 132);
assert.strictEqual(context.remaining(0, 0, 3, 1), 2);

assert.ok(side.includes('const TE_AUTO_ETA_STATS_KEY = "download/auto_eta_stats_v274";'));
assert.ok(side.includes('schema: "ig_auto_eta_v274"'));
assert.ok(side.includes('teAutoEtaRecordCompletedPost(directSummary, "direct_pair_complete")'));
assert.ok(side.includes('return remain * (averageDownloadMs + delayMs);'));

console.log('OK test_ext_auto_control_eta_v274');
