// 字段控件覆盖机制
// 约定：/src/views/pagetype/<pagetype>/form/controls/<fieldtype>.vue

// 由 Vite define 注入，用于 apps 优先级（靠后优先）
declare const __APPS_ORDER__: string[]

type AsyncComponentLoader = () => Promise<any>

// 跨应用 + 本地扫描（与 pagetypeOverride 保持一致）
const globAllApps = import.meta.glob('@apps/*/frontend/src/views/pagetype/**/form/controls/**.vue')
const globLocal = import.meta.glob('/src/views/pagetype/**/form/controls/**.vue')

type Entry = {
  loader: AsyncComponentLoader
  appName: string
  fullPath: string
  entity: string
  fieldtype: string
}

const allEntries: Entry[] = []

function appsOrder(): string[] {
  return Array.isArray(__APPS_ORDER__) && __APPS_ORDER__.length > 0 ? __APPS_ORDER__ : ['jingrow']
}

function rankByAppsOrder(appName: string): number {
  const order = appsOrder()
  const idx = order.indexOf(appName)
  return idx >= 0 ? idx : -1
}

function extractAppName(p: string): string {
  const s = p.replace(/\\/g, '/').replace(/^\/@fs\//, '/')
  // 本地 src 明确视为 jingrow
  if (s.startsWith('/src/')) return 'jingrow'
  // 1) (apps|@apps)/<app>/frontend
  const reApps1 = /(?:^|\/)apps\/([^/]+)\/frontend\//
  const reApps2 = /(?:^|\/)@apps\/([^/]+)\/frontend\//
  const m1 = s.match(reApps1)
  if (m1 && m1[1]) return m1[1]
  const m2 = s.match(reApps2)
  if (m2 && m2[1]) return m2[1]
  // 2) 相对路径 ../../<app>/frontend/src/
  const reRel = /(?:^|\/)\.\.\/([^/]+)\/frontend\/src\//
  const m3 = s.match(reRel)
  if (m3 && m3[1] && m3[1] !== 'jingrow') return m3[1]
  // 3) 基于分段查找（同时识别 'apps' 与 '@apps'）
  const parts = s.split('/').filter(Boolean)
  let i = parts.indexOf('apps')
  if (i < 0) i = parts.indexOf('@apps')
  if (i >= 0 && i + 1 < parts.length) return parts[i + 1]
  return 'jingrow'
}

function parseEntityAndFieldtype(p: string): { entity: string; fieldtype: string } | null {
  const segs = p.split('/').filter(Boolean)
  // 形如 .../views/pagetype/<entity>/form/controls/<fieldtype>.vue
  const idxPagetype = segs.indexOf('pagetype')
  const idxControls = segs.lastIndexOf('controls')
  if (idxPagetype < 0 || idxControls < 0 || idxPagetype + 1 >= segs.length || idxControls + 1 >= segs.length) return null
  const entity = segs[idxPagetype + 1]
  const fieldFile = segs[idxControls + 1]
  const fieldtype = fieldFile.replace(/\.vue$/i, '')
  return { entity, fieldtype }
}

function pushEntries(map: Record<string, any>) {
  for (const [p, loader] of Object.entries(map)) {
    const parsed = parseEntityAndFieldtype(p)
    if (!parsed) continue
    allEntries.push({
      loader: loader as AsyncComponentLoader,
      appName: extractAppName(p),
      fullPath: p,
      entity: parsed.entity,
      fieldtype: parsed.fieldtype
    })
  }
}

pushEntries(globAllApps)
pushEntries(globLocal)

// 预构建索引：(entity, fieldtype) -> 已排序候选列表
const indexedByKey: Record<string, Entry[]> = {}

for (const e of allEntries) {
  const key = `${e.entity}:${e.fieldtype}`
  if (!indexedByKey[key]) indexedByKey[key] = []
  indexedByKey[key].push(e)
}

// 预排序所有索引
for (const key of Object.keys(indexedByKey)) {
  indexedByKey[key].sort((a, b) => {
    const ra = rankByAppsOrder(a.appName)
    const rb = rankByAppsOrder(b.appName)
    if (ra !== rb) return rb - ra
    const aIsExternal = a.fullPath.includes('/apps/') || a.fullPath.includes('@apps/')
    const bIsExternal = b.fullPath.includes('/apps/') || b.fullPath.includes('@apps/')
    if (aIsExternal !== bIsExternal) return aIsExternal ? -1 : 1
    if (a.fullPath.length !== b.fullPath.length) return a.fullPath.length - b.fullPath.length
    return a.fullPath.localeCompare(b.fullPath)
  })
}

/**
 * 解析控件覆盖：优先级 其他app > jingrow/pagetype > 核心通用
 */
export async function resolveControlOverride(entity: string, fieldtype: string): Promise<any | null> {
  if (!entity || !fieldtype) return null
  const k = `${entity.toLowerCase().replace(/-/g, '_')}:${String(fieldtype).replace(/\s+/g, '')}`
  let bucket = indexedByKey[k]
  // 全局控件兜底
  if (!bucket || bucket.length === 0) {
    bucket = indexedByKey[`_global:${String(fieldtype).replace(/\s+/g, '')}`]
  }
  if (!bucket || bucket.length === 0) return null
  try {
    const mod = await bucket[0].loader()
    return mod?.default ?? mod
  } catch {
    return null
  }
}
