import fs from 'node:fs'
import path from 'node:path'
const root=process.cwd(); const failures=[]
const read=p=>fs.readFileSync(path.join(root,p),'utf8')
const must=(text,needles,scope)=>needles.forEach(n=>{if(!text.includes(n))failures.push(`${scope} missing ${n}`)})

const ui=read('packages/kbx-contracts/src/ui.ts')
must(ui,["export type KbxAsyncState = 'idle' | 'ready' | 'loading' | 'empty' | 'error'"],'async state contract')
const screen=read('packages/kbx-contracts/src/screen.ts')
must(screen,['export type KbxTemplateStateCapability',"| 'permission'","| 'dirty'","| 'conflict'","| 'validation'","| 'job'","| 'network'",'stateCapabilities: KbxTemplateStateCapability[]'],'template state capability contract')
const manifest=read('packages/kbx-ui/src/registry/templateManifest.ts')
for(const code of ['T01','T02','T03','T04','T05','T06','T07','T08','T09']){
  const line=manifest.split('\n').find(value=>value.includes(`code:'${code}'`))??''
  must(line,['stateCapabilities:','\'permission\''],`${code} state capability matrix`)
}
must(manifest,["const commonStates=['idle','loading','empty','error','ready']", "stateCapabilities:['idle','loading','refreshing','empty','error','permission']", "stateCapabilities:['loading','refreshing','error','permission','dirty','conflict','validation']", "stateCapabilities:['loading','refreshing','error','permission','validation','job']", "stateCapabilities:['loading','refreshing','error','permission','network']"],'state matrix applicability')

const dataState=read('packages/kbx-ui/src/components/KbxDataState.vue')
must(dataState,["idle: { title:'조회 전입니다.'", "state==='idle' ? '○'"],'idle data state')
const boundary=read('packages/kbx-ui/src/components/KbxTemplateStateBoundary.vue')
must(boundary,['idleActionLabel?: string','idleAction:[]','data-template-state','state===\'idle\'','@action="emit(\'idleAction\')"'],'template idle boundary')
for(const file of ['KbxListPage.vue','KbxMasterPage.vue','KbxMasterDetailPage.vue','KbxQueuePage.vue','KbxReconcilePage.vue']){
  const text=read(`packages/kbx-ui/src/components/${file}`)
  must(text,['idle-action-label','@idle-action'],`${file} idle recovery wiring`)
}

const host=read('packages/kbx-ui/src/permission/host.ts')
must(host,['export interface KbxPermissionHost','export const KbxPermissionHostKey'],'permission host')
const appFrame=read('apps/web/src/shell/KbxAppFrame.vue')
must(appFrame,['KbxPermissionHostKey','provide(KbxPermissionHostKey,{has:','props.grantedPermissions.includes(permission)'],'permission provider')
for(const [file,needles] of [
  ['packages/kbx-ui/src/components/KbxScreenFrame.vue',['KbxPermissionHostKey','permissionHost=inject','canPermission(permission:string)','data-access','permissionDenied','이 화면을 사용할 권한이 없습니다.',':can="canPermission"']],
  ['packages/kbx-ui/src/components/KbxCommandBar.vue',['KbxPermissionHostKey','permissionHost=inject','canPermission(permission:string)','!permission||canPermission(permission)']],
  ['packages/kbx-ui/src/components/KbxWorkflowBar.vue',['KbxPermissionHostKey','permissionHost=inject','canPermission(permission:string)','!x.permission||canPermission(x.permission)']],
  ['packages/kbx-ui/src/components/KbxBulkActionBar.vue',['KbxPermissionHostKey','permissionHost=inject','canPermission(permission:string)','!a.permission||canPermission(a.permission)']],
  ['packages/kbx-ui/src/wms/KbxWmsMobilePage.vue',['KbxPermissionHostKey','permissionHost=inject','permissionDenied','data-access','이 현장 업무를 사용할 권한이 없습니다.']],
]) must(read(file),needles,`${file} injected permission enforcement`)

for(const file of [
  'apps/web/src/modules/oms/orders/search/OrderListPage.vue',
  'apps/web/src/modules/oms/claims/ClaimsPage.vue',
  'apps/web/src/modules/erp/items/ItemMasterPage.vue',
  'apps/web/src/modules/erp/inventory/InventoryPage.vue',
  'apps/web/src/modules/common/ux-metrics/UxMetricsPage.vue',
  'apps/web/src/modules/wms/work/WmsWorkPage.vue',
]) must(read(file),["?'idle'"],`${file} initial-state adoption`)

const home=read('packages/kbx-ui/src/shell/KbxHomePage.vue')
must(home,['operationFailureCount?:number','urgentNotificationCount?:number','실패·부분완료 작업','중요 알림','regularNotificationCount','button.critical'],'Home attention workbench')
must(appFrame,['failedOperationCount','partially-completed','urgentUnreadCount','urgent-notification-count'],'runtime attention wiring')

const store=read('apps/web/src/shell/workspaceStore.ts')
must(store,["STORAGE_PREFIX='kbx.navigation.preference.v3'","LEGACY_STORAGE_PREFIX='kbx.navigation.preference.v2'",'MAX_STORED_PREFERENCE_BYTES=64_000','MAX_SCOPE_LENGTH=160','MAX_RECENT_PATH_LENGTH=1024','parseStoredPreference','Date.parse(visitedAt)','storageKey(scope,LEGACY_STORAGE_PREFIX)','normalizePreference({...preference.value,recents:'],'persisted preference hardening/migration')
const navSecurity=read('packages/kbx-ui/src/shell/navigationSecurity.ts')
must(navSecurity,['MAX_WORKSPACE_URL_LENGTH=2048','[\\u0000-\\u001f\\u007f]'],'workspace URL size/control-character hardening')

const componentManifest=read('packages/kbx-ui/src/registry/componentManifest.ts')
for(const [name,category] of [['KbxDataState','business'],['KbxHomePage','shell'],['KbxListPage','template'],['KbxWmsMobilePage','wms'],['KbxCommandBar','business'],['KbxWorkflowBar','business'],['KbxBulkActionBar','business']]){
  must(componentManifest,[`name: '${name}'`,`category: '${category}'`],`v33 component ${name}`)
}
function versionAtLeast(name,minimum){
  const line=componentManifest.split('\n').find(value=>value.includes(`name: '${name}'`))??''
  const version=line.match(/version:\s*'([0-9]+)\.([0-9]+)\.([0-9]+)'/)?.slice(1).map(Number)
  if(!version){failures.push(`v33 component ${name} missing semver`);return}
  const [a,b,c]=version;const [x,y,z]=minimum
  if(a<x || (a===x&&b<y) || (a===x&&b===y&&c<z))failures.push(`v33 component ${name} version ${version.join('.')} < ${minimum.join('.')}`)
}
versionAtLeast('KbxDataState',[1,1,0]);versionAtLeast('KbxHomePage',[1,0,0]);versionAtLeast('KbxListPage',[1,6,0]);versionAtLeast('KbxWmsMobilePage',[1,5,0]);versionAtLeast('KbxCommandBar',[1,3,0])
must(componentManifest,["KbxDataState', category: 'business', purpose: 'Idle·Loading·Empty·Error", "KbxCommandBar', category: 'business', purpose: 'Permission Host", "KbxWorkflowBar', category: 'business', purpose: 'Permission Host", "KbxBulkActionBar', category: 'business', purpose: 'Permission Host"],'v33 retained component purposes')
const catalog=read('packages/kbx-ui/src/catalog/componentCatalog.ts')
must(catalog,["id:'idle',label:'조회 전',state:'idle'","id:'attention',label:'실패 작업·중요 알림 우선',state:'error'"],'catalog state scenarios')

if(failures.length){console.error(failures.join('\n'));process.exit(1)}
console.log('v33 template/component/home navigation validation passed: explicit idle state, template state-capability matrix, injected permission enforcement, actionable Home attention, hardened preference migration/storage, and workspace URL bounds.')
