import type { KbxNavigationResolvedEntry } from '@kbx/contracts'

const MAX_WORKSPACE_URL_LENGTH=2048
function normalizePathname(value:string){const clean=value.replace(/\/+$/,'')||'/';return clean.startsWith('/')?clean:`/${clean}`}
function hasUnsafeEncodedPath(value:string){return value.length>MAX_WORKSPACE_URL_LENGTH || /[\u0000-\u001f\u007f]|\\|%2f|%5c|%00|%0d|%0a|%09|%2e%2e/i.test(value)}

/** Match a Vue-Router-style path pattern without trusting persisted route strings. */
export function matchKbxRoutePattern(pattern:string,candidatePath:string){
  if(hasUnsafeEncodedPath(candidatePath))return false
  const p=normalizePathname(pattern).split('/').filter(Boolean)
  const c=normalizePathname(candidatePath).split('/').filter(Boolean)
  if(p.length!==c.length)return false
  return p.every((segment,index)=>segment.startsWith(':') ? Boolean(c[index]) : segment===c[index])
}

/**
 * Re-resolve an in-memory workspace path against the screen's declared route capabilities.
 * Query/hash are retained only for the current in-memory workspace after the pathname passes the capability check.
 */
export function resolveKbxSafeWorkspacePath(patterns:readonly string[],candidatePath:string,fallbackPath:string){
  try{
    if(hasUnsafeEncodedPath(candidatePath))return fallbackPath
    const candidate=new URL(candidatePath,'https://kbx.local')
    if(candidate.origin!=='https://kbx.local'||candidate.username||candidate.password)return fallbackPath
    const allowed=patterns.some(pattern=>matchKbxRoutePattern(pattern,candidate.pathname))
    return allowed?`${candidate.pathname}${candidate.search}${candidate.hash}`:fallbackPath
  }catch{return fallbackPath}
}

/**
 * Re-resolve untrusted persisted recent navigation against the current authorized catalog entry.
 * Query/hash are deliberately stripped before persistence/replay so transient filters, tokens, and sensitive
 * values do not leak into local preference storage. Dynamic route path persistence remains explicit opt-in.
 */
export function resolveKbxSafeRecentPath(entry:KbxNavigationResolvedEntry, storedPath:string){
  if(entry.recentPolicy!=='route')return entry.path
  try{
    if(hasUnsafeEncodedPath(storedPath))return entry.path
    const base=new URL(entry.path,'https://kbx.local')
    const candidate=new URL(storedPath,'https://kbx.local')
    if(candidate.origin!==base.origin||candidate.username||candidate.password)return entry.path
    const basePath=base.pathname.replace(/\/$/,'')||'/'
    const candidatePath=candidate.pathname.replace(/\/$/,'')||'/'
    const within=candidatePath===basePath || (basePath!=='/' && candidatePath.startsWith(`${basePath}/`))
    return within?candidate.pathname:entry.path
  }catch{return entry.path}
}
