import { ElMessage } from 'element-plus'
import type { UploadRawFile } from 'element-plus'

const ALLOWED_EXTENSIONS = new Set([
  'jpg',
  'jpeg',
  'png',
  'gif',
  'bmp',
  'webp',
  'pdf',
  'doc',
  'docx',
  'xls',
  'xlsx',
  'ppt',
  'pptx',
  'txt',
  'md',
  'csv',
  'zip',
  'rar',
  '7z',
  'mp4',
  'mp3',
  'wav',
  'ogg',
])

const BLOCKED_EXTENSIONS = new Set([
  'jsp',
  'jspx',
  'php',
  'asp',
  'aspx',
  'sh',
  'bat',
  'cmd',
  'exe',
  'dll',
  'jar',
  'war',
  'ear',
  'html',
  'htm',
  'js',
])

const MAX_FILE_SIZE = 10 * 1024 * 1024 // 10MB

export function extractExtension(filename: string): string | null {
  const lastDot = filename.lastIndexOf('.')
  if (lastDot < 0 || lastDot === filename.length - 1) return null
  return filename.substring(lastDot + 1).toLowerCase()
}

export function isAllowedFile(filename: string): boolean {
  if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
    return false
  }
  const ext = extractExtension(filename)
  if (!ext) return false
  if (BLOCKED_EXTENSIONS.has(ext)) return false
  return ALLOWED_EXTENSIONS.has(ext)
}

export function beforeFileUpload(rawFile: UploadRawFile): boolean {
  if (rawFile.size > MAX_FILE_SIZE) {
    ElMessage.error(`文件大小超过限制，最大允许 ${MAX_FILE_SIZE / 1024 / 1024}MB`)
    return false
  }
  if (!isAllowedFile(rawFile.name)) {
    ElMessage.error('不允许上传该类型文件')
    return false
  }
  return true
}

export function isSafeUrl(url: string): boolean {
  if (!url) return false
  try {
    // 允许的协议白名单
    const allowedProtocols = new Set(['http:', 'https:', 'blob:'])
    const trimmed = url.trim()
    if (!trimmed) return false
    // 相对路径（无协议）允许
    if (!/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) {
      return true
    }
    const parsed = new URL(trimmed)
    return allowedProtocols.has(parsed.protocol.toLowerCase())
  } catch {
    return false
  }
}

export function getFileUrl(url?: string): string {
  if (!url) return ''
  const trimmed = url.trim()
  if (!isSafeUrl(trimmed)) return ''
  if (/^https?:/i.test(trimmed)) return trimmed
  if (trimmed.startsWith('//')) return window.location.protocol + trimmed
  return trimmed.startsWith('/') ? trimmed : '/' + trimmed
}

function extractUploadResponse(response: unknown): string {
  if (!response) return ''
  if (typeof response === 'string') return response
  if (typeof response === 'object' && response !== null) {
    const data = (response as any).data
    if (typeof data === 'string') return data
    const url = (response as any).url
    if (typeof url === 'string') return url
  }
  return ''
}

export function getFileName(url: string): string {
  if (!url) return ''
  try {
    const parsed = new URL(url, window.location.origin)
    const pathname = parsed.pathname
    const parts = pathname.split('/')
    return parts[parts.length - 1] || url
  } catch {
    const parts = url.split('/')
    return parts[parts.length - 1] || url
  }
}

export function parseAttachments(urlsStr?: string): string[] {
  if (!urlsStr) return []
  try {
    const parsed = JSON.parse(urlsStr)
    if (Array.isArray(parsed)) {
      return parsed.filter((u): u is string => typeof u === 'string' && isSafeUrl(u))
    }
  } catch {
    if (typeof urlsStr === 'string' && urlsStr.includes(',')) {
      return urlsStr
        .split(',')
        .map((s) => s.trim())
        .filter(isSafeUrl)
    }
  }
  return isSafeUrl(urlsStr) ? [urlsStr] : []
}

export function getUploadUrl(file: any): string {
  if (!file) return ''
  const fromResponse = extractUploadResponse(file.response)
  if (fromResponse) return fromResponse
  if (typeof file.url === 'string' && !file.url.startsWith('blob:')) return file.url
  return ''
}

export function collectAttachmentUrls(fileList: any[]): string {
  const urls = fileList
    .map((f: any) => {
      const fromResponse = extractUploadResponse(f?.response)
      if (fromResponse) return fromResponse
      if (f?.url && typeof f.url === 'string' && !f.url.startsWith('blob:')) return f.url
      return null
    })
    .filter((url): url is string => !!url && isSafeUrl(url))
  return JSON.stringify(urls)
}
