import type { FileEntry } from '@/types/api'

function ownerGroupStr(v: unknown): string {
  if (v == null) return ''
  return String(v).trim()
}

/** List chip label: owner, or owner:group when different. */
export function formatOwnerChip(item: Pick<FileEntry, 'owner' | 'group' | 'type'>): string {
  if (item.type === 'symlink') return '—'
  const o = ownerGroupStr(item.owner)
  const g = ownerGroupStr(item.group)
  if (!o) return '—'
  if (!g || g === o) return o
  return `${o}:${g}`
}

export function ownerChipColor(owner: string): string | undefined {
  if (owner === 'root') return 'warning'
  return undefined
}

export function permissionTooltip(item: FileEntry): string {
  const parts: string[] = []
  if (item.permissions) parts.push(item.permissions)
  if (item.mode_octal) parts.push(item.mode_octal)
  const o = ownerGroupStr(item.owner)
  const g = ownerGroupStr(item.group)
  if (o) parts.push(g && g !== o ? `${o}:${g}` : o)
  return parts.join(' · ') || '—'
}

export const CHMOD_PRESETS = [
  { label: '文件 644', mode: '644', for: 'file' as const },
  { label: '目录 755', mode: '755', for: 'directory' as const },
  { label: '私密 600', mode: '600', for: 'file' as const },
  { label: '协作 775', mode: '775', for: 'directory' as const },
  { label: '可执行 755', mode: '755', for: 'file' as const },
] as const

const SUDOERS_DOC = 'docs/deploy/nexus-files-sudoers.example'

/** HTTP / API message hints for permission-denied reads or writes. */
export function isPermissionDeniedMessage(message: string): boolean {
  const m = message.toLowerCase()
  return (
    m.includes('permission denied')
    || m.includes('operation not permitted')
    || m.includes('无法访问')
    || m.includes('无权限')
    || m.includes('无写入权限')
    || m.includes('读取失败')
    || m.includes('chmod 失败')
  )
}

/** Heuristic: SSH user likely cannot read this file from `ls` permission bits. */
export function isEntryLikelyUnreadable(
  item: Pick<FileEntry, 'type' | 'permissions' | 'owner' | 'group'>,
  sshUser: string | null | undefined,
): boolean {
  if (!sshUser || sshUser === 'root' || item.type !== 'file') return false
  const perms = item.permissions ?? ''
  if (perms.length < 10) return false
  const owner = ownerGroupStr(item.owner)
  const group = ownerGroupStr(item.group)
  const ownerTri = perms.slice(1, 4)
  const groupTri = perms.slice(4, 7)
  const otherTri = perms.slice(7, 10)
  if (owner === sshUser) return !ownerTri.includes('r')
  if (group && group === sshUser) return !groupTri.includes('r')
  return !otherTri.includes('r') && !groupTri.includes('r')
}

/** 文件页提示末尾：仓库内 sudoers 示例路径（需运维安装到目标机）。 */
export function filesSudoersDocHint(): string {
  return `目标机安装示例：${SUDOERS_DOC}（复制到 /etc/sudoers.d/nexus-files 后执行 visudo -cf 校验）`
}

export function buildFilesAccessHint(params: {
  sshUser?: string | null
  canSudo: boolean
  whitelistOk?: boolean
  isRootSsh: boolean
  filesElevation?: 'off' | 'auto_sudo' | 'always_sudo'
  capabilityMessage?: string | null
  lastReadDeniedPath?: string | null
  unreadableCount?: number
}): { type: 'warning' | 'error'; text: string } | null {
  // root SSH 用户无需任何提示
  if (params.isRootSsh) return null

  const lines: string[] = []
  const n = params.unreadableCount ?? 0

  // 只在有实际权限问题时显示提示
  if (params.lastReadDeniedPath) {
    lines.push(`无法读取「${params.lastReadDeniedPath}」：当前 SSH 用户无权限。`)
  }
  if (n > 0 && params.sshUser) {
    lines.push(`当前目录约 ${n} 个文件对 SSH 用户「${params.sshUser}」不可读。`)
  }

  // 确认有实际错误后，再给出配置建议
  if (lines.length > 0) {
    if (params.filesElevation === 'off') {
      lines.push('此服务器「文件提权」已关闭，不会自动 sudo。')
    } else if (!params.canSudo) {
      lines.push('请配置免密 sudo（NOPASSWD）或使用「一键配置」，或改用 root SSH 用户。')
    } else if (!params.whitelistOk) {
      lines.push('已有 sudo 但白名单不完整（须含 bash、chmod、chown、tee、cat 等）。')
    } else {
      lines.push('系统已自动尝试 sudo -n 提权，如仍失败请检查 sudoers 白名单。')
    }
  }

  if (!lines.length) return null

  const needsSudoersDoc =
    params.filesElevation === 'off' || !params.canSudo || !params.whitelistOk
  const suffix = needsSudoersDoc ? ` ${filesSudoersDocHint()}` : ''
  const type: 'warning' | 'error' =
    (!params.canSudo || params.filesElevation === 'off') ? 'error' : 'warning'
  const body = lines.join(' ')
  return { type, text: `${body}${suffix}` }
}

export { SUDOERS_DOC }
