// FILE: _St/IG_StYellow/test_ext_auto_filter_swipe_v302.js | ROLE: v302 숨김지표·기간 Swipe·대기 UI 회귀 테스트
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const assert = require('assert');

const root = __dirname;
const side = fs.readFileSync(path.join(root, 'side.js'), 'utf8');
const manifest = JSON.parse(fs.readFileSync(path.join(root, 'manifest.json'), 'utf8'));
assert.strictEqual(manifest.version, '2.3.8.3020');
assert.strictEqual(manifest.version_name, '2.3.8.302');
assert.ok(side.includes('const IGBLUE_PACKAGE_VERSION = "v302";'));

// 일부만 숨김이면 수치 조건을 우회하지 않고, 현재 목록 전체 숨김일 때만 나머지 조건으로 판정한다.
const metricStart = side.indexOf('function teMetricNumber(e)');
const metricEnd = side.indexOf('function teShortNumber(e)', metricStart);
assert.ok(metricStart >= 0 && metricEnd > metricStart);
const inputs = {
  top_n_count: {value:'1'},
  igblue_min_comments: {value:'1'},
  igblue_min_likes: {value:'100'},
  igblue_min_reposts: {value:'0'}
};
const ctx = {
  document:{getElementById:(id)=>inputs[id]||null},
  teLocalGet:(_k,f)=>f,
  G:['like_count','comment_count','media_repost_count','created_at','play_count','','engagement_rate','share_count'],
  Z:4,
  location:{href:'https://www.instagram.com/example/'},
  teCurrentTargetUrl:()=> 'https://www.instagram.com/example/'
};
vm.createContext(ctx);
vm.runInContext(`${side.slice(metricStart, metricEnd)};
this.policy=teMetricAvailabilityPolicy;
this.pass=teMediaPassesTopConditions;
this.sort=teSortCandidateList;`, ctx);
const shown={code:'shown',play_count:20000,views_available:1,like_count:120,comment_count:2};
const hidden={code:'hidden',views_available:0,like_count:999,comment_count:9};
const mixed=ctx.policy([shown,hidden],'play_count');
assert.strictEqual(ctx.pass(shown,'play_count',10000,mixed),true);
assert.strictEqual(ctx.pass(hidden,'play_count',10000,mixed),false);
const allHidden=ctx.policy([hidden,{...hidden,code:'hidden2',like_count:50}],'play_count');
assert.strictEqual(ctx.pass(hidden,'play_count',10000,allHidden),true);
assert.strictEqual(ctx.pass({...hidden,like_count:50},'play_count',10000,allHidden),false);

// 업로드 일자 숨김은 날짜 필터에서 제거하지 않고, 숨김 날짜가 섞이면 기간 끝으로 단정하지 않는다.
assert.ok(side.includes('null == e.created_at\n                    ? (r.issue = !0, n.push(e))'));
assert.ok(side.includes('newUnknown === 0 && newValid === 0'));
assert.ok(side.includes('valid_or_unknown_date_media_present'));
assert.ok(side.includes('date_filter_range_exhausted_empty'));
assert.ok(side.includes('skip_current_account_or_finish'));

// Video OFF는 snapshot의 shortcode/owner만으로 metadata 처리가 가능하며 Main 카드 연결을 요구하지 않는다.
const snapshotStart=side.indexOf('function teAutoPyDownloadableKindsFromCache(media)');
const snapshotEnd=side.indexOf('async function teAutoPyDownloadMediaPairFromCache',snapshotStart);
assert.ok(snapshotStart>=0&&snapshotEnd>snapshotStart);
const snapCtx={Date,teDownloadVideoSave:()=>false,teMediaOwnerName:(m)=>m.username||''};
vm.createContext(snapCtx);
vm.runInContext(`${side.slice(snapshotStart,snapshotEnd)};this.ready=teAutoPySnapshotDirectReady;`,snapCtx);
const ready=snapCtx.ready({code:'META001',username:'owner'},1);
assert.strictEqual(ready.ok,true);
assert.strictEqual(ready.metadata_only,true);

// '⚠ 자동 대기중'은 사용자가 작업 Instagram 탭을 벗어난 경우에만 표시한다.
assert.ok(side.includes('const focusWait = c === "user_window_in_use"'));
assert.ok(side.includes('if (focusWait) teAutoPyRenderRuntimeNotice("wait", c, m)'));
const mainStart=side.indexOf('async function teAutoPyEnsureMainInjectionReady');
const mainEnd=side.indexOf('function teUpdateMetricThresholdCount',mainStart);
const mainBlock=side.slice(mainStart,mainEnd);
assert.ok(mainBlock.includes('for (let attempt = 1; attempt <= 5; attempt++)'));
assert.ok(!mainBlock.includes('teAutoPyEnterWait('));

console.log('OK test_ext_auto_filter_swipe_v302');
