import fs from 'node:fs'
const read=p=>fs.readFileSync(p,'utf8')
const failures=[]

const contract=read('packages/kbx-contracts/src/grid.ts')
for(const token of ['KbxGridEditingPolicy','KbxGridPasteResult','KbxBulkSelectionRequest',"'all-filtered'",'drilldown'])if(!contract.includes(token))failures.push(`grid contract missing ${token}`)

const utility=read('packages/kbx-ui/src/grid/editing.ts')
for(const token of ['normalizeKbxGridClipboardData','normalizeKbxGridClipboardValue','toKbxBulkSelectionRequest','INVALID_NUMBER','INVALID_DATE','INVALID_BOOLEAN'])if(!utility.includes(token))failures.push(`grid editing utility missing ${token}`)

const grid=read('packages/kbx-ui/src/components/KbxDataGrid.vue')
for(const token of ['allowAllFilteredSelection','selectionStateChanged','rowAddRequested','rowDuplicateRequested','fillDownApplied','pasteProcessed','errorFocusChanged','contextRequested','drillDownRequested','processClipboardData','검색결과','첫/다음 오류'])if(!grid.includes(token))failures.push(`KbxDataGrid productivity missing ${token}`)

const fast=read('packages/kbx-ui/src/components/KbxFastEntryPage.vue')
for(const token of ['Ctrl+V','Enter','F2','오류는 Grid에서 바로 이동'])if(!fast.includes(token))failures.push(`KbxFastEntryPage guide missing ${token}`)

const orderRegister=read('apps/web/src/modules/oms/orders/register/OrderRegisterPage.vue')
for(const token of ['selection="multiple"','allowRowAdd:true','allowRowDuplicate:true','fillDown:true','paste:true','errorNavigation:true','row-add-requested','row-duplicate-requested'])if(!orderRegister.includes(token))failures.push(`OMS-ORD-002 fast-entry adoption missing ${token}`)

const orderSearchVm=read('apps/web/src/modules/oms/orders/search/useOrderSearch.ts')
for(const token of ['appliedSearch','currentBulkFilter','appliedSearch.value={...search}'])if(!orderSearchVm.includes(token))failures.push(`OMS-ORD-001 applied-filter safety missing ${token}`)

const orderList=read('apps/web/src/modules/oms/orders/search/OrderListPage.vue')
for(const token of ['allow-all-filtered-selection','selection-state','total-count','selection-state-changed'])if(!orderList.includes(token))failures.push(`OMS-ORD-001 all-filtered adoption missing ${token}`)

const searchRequest=read('backend/Modules/OMS/Orders/Search/Request.cs')
const searchHandler=read('backend/Modules/OMS/Orders/Search/Handler.cs')
if(!searchRequest.includes('bool ExceptionOnly'))failures.push('SearchOrdersRequest must carry ExceptionOnly')
if(!searchHandler.includes('@ExceptionOnly = false or o.exception_count > 0'))failures.push('SearchOrdersHandler must enforce ExceptionOnly')

const ship=read('backend/Modules/OMS/Orders/Ship/Endpoint.cs')
for(const token of ['ShipOrdersFilter','mode is not ("ids" or "filter")','oms_order_search_projection','ExcludedIds','target as materialized','accepted as materialized','audit_insert','outbox_insert'])if(!ship.includes(token))failures.push(`ship server-side bulk contract missing ${token}`)

const catalog=read('packages/kbx-ui/src/catalog/componentCatalog.ts')
for(const token of ["id:'fast-entry'","id:'all-filtered'"])if(!catalog.includes(token))failures.push(`catalog missing ${token}`)

const tests=read('tests/unit/kbx-grid-productivity.contract.spec.ts')+read('tests/e2e/kbx-grid-fast-entry.spec.ts')
for(const token of ['normalizes Excel-like pasted values','does not expand all-filtered selection','server-side whole-result selection'])if(!tests.includes(token))failures.push(`grid productivity test evidence missing ${token}`)

if(failures.length){console.error('KBX grid productivity validation failed:\n- '+failures.join('\n- '));process.exit(1)}
console.log('Grid productivity PASS: Fast Entry, paste normalization, Fill Down, error navigation, drill-down/context hooks, all-filtered server bulk selection.')
