/**
 * 文件预览 Composable
 * 提供文件预览 URL 生成、媒体元数据获取等功能
 */

import { ref } from 'vue'
import { FILE_EXTENSIONS, FILE_SIZE_THRESHOLDS } from '@/utils/constants'
import { normalizeFilePath, getExt } from '@/utils/fileUtils'
import { detectFileTypeByContent } from '@/api/system'
import { connectionManager } from '@/api/connection-manager'
import { SftpTransport } from '@/api/sftp-transport'
import { getFileServerBaseURL } from '@/api/file-server'
import {
  isImageFile, isVideoFile, isAudioFile, isPdfFile,
  isHtmlFile, isMarkdownFile, isPreviewable as isPreviewableType,
  isTextEditable, isConfigFile
} from '@/utils/fileTypeHelpers'
import type { FilePreviewMetadata, FileType } from '@/types/file-system'

// 内容检测大小限制（与后端一致）
const CONTENT_DETECT_MAX_SIZE = 500 * 1024 // 500KB

// 缓存检测结果
const contentDetectCache = new Map<string, { timestamp: number; result: any }>()
const CACHE_TTL = 60000 // 1分钟缓存

export interface UseFilePreviewOptions {
  filePath?: string
  isBrowsingZip?: boolean
}

function getLocalServerURL(): string {
  return getFileServerBaseURL()
}

function resolveFileServerBase(): string {
  // 单一数据源：从 connectionManager 实时读取，不缓存
  if (!connectionManager.isRemote()) return getLocalServerURL()
  const base = connectionManager.getFileServerBaseURL()
  if (!base) return getLocalServerURL()
  // 远程模式需要完整代理路径前缀 /api/v1/proxy/localfs
  return base.replace(/\/$/, '') + '/api/v1/proxy/localfs'
}

export function useFilePreview(options: UseFilePreviewOptions = {}) {
  const { filePath = ref(''), isBrowsingZip = ref(false) } = options

  // 预览 URL
  const previewUrl = ref('')

  // 媒体加载状态
  const imageLoading = ref(false)
  const currentImageDimensions = ref('')

  /**
   * 获取预览 URL（本地/远程/SFTP 自适应，每次实时计算）
   * 本地: {fileServerBaseURL}/localfs/{encoded_path}
   * 远程(HTTP): {baseUrl}/api/v1/proxy/localfs/{raw_path}
   * SFTP: 下载到本地临时目录 → {fileServerBaseURL}/localfs/{temp_path}
   */
  const getPreviewUrl = (path: string): string => {
    if (!path) return ''
    const isSftp = connectionManager.isSftp()
    const isRemote = connectionManager.isRemote()

    // SFTP 模式：需要先下载到本地临时目录
    // 注意：这里返回的是同步路径，实际下载在 updatePreviewUrl 中异步完成
    // 对于 SFTP 模式，getPreviewUrl 返回的 URL 会在 updatePreviewUrl 中被覆盖为临时文件路径
    if (isSftp) {
      const base = getLocalServerURL()
      let normalized = normalizeFilePath(path, true)
      const sep = base.endsWith('/') ? '' : '/'
      return `${base}${sep}localfs/${normalized}`
    }

    const base = resolveFileServerBase()
    let normalized = normalizeFilePath(path, true)
    if (isRemote && normalized.startsWith('/')) normalized = normalized.slice(1)
    const sep = base.endsWith('/') ? '' : '/'
    return `${base}${sep}${isRemote ? '' : 'localfs/'}${normalized}`
  }

  /**
   * 通过内容检测文件类型（用于小文件）
   */
  const detectByContent = async (path: string, fileSize?: number): Promise<{ category: string; ext: string } | null> => {
    // 如果文件太大，跳过内容检测
    if (fileSize !== undefined && fileSize > CONTENT_DETECT_MAX_SIZE) {
      return null
    }

    // 检查缓存
    const cached = contentDetectCache.get(path)
    if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
      return cached.result
    }

    try {
      const result = await detectFileTypeByContent(path)
      const data = { category: result.category, ext: result.extension }
      contentDetectCache.set(path, { timestamp: Date.now(), result: data })
      return data
    } catch {
      return null
    }
  }

  /**
   * 更新预览 URL（SFTP 模式会先下载到本地临时目录）
   */
  const updatePreviewUrl = async (path: string) => {
    if (!path) { previewUrl.value = ''; return }

    // SFTP 模式：下载到本地临时目录后用本地文件服务器预览
    if (connectionManager.isSftp()) {
      const transport = connectionManager.getTransport()
      if (transport instanceof SftpTransport) {
        try {
          const tempPath = await transport.downloadForPreview(path)
          previewUrl.value = getPreviewUrl(tempPath)
          return
        } catch {
          // 下载失败，回退显示原始路径（会无法预览但不会崩溃）
        }
      }
    }

    previewUrl.value = getPreviewUrl(path)
  }

  /**
   * 获取文件类型
   */
  const getFileType = (filename: string): FileType => {
    if (!filename || typeof filename !== 'string') return 'Binary' as FileType

    if (isImageFile(filename)) return 'Image' as FileType
    if (isVideoFile(filename)) return 'Video' as FileType
    if (isAudioFile(filename)) return 'Audio' as FileType
    if (isPdfFile(filename)) return 'Pdf' as FileType
    if (isHtmlFile(filename)) return 'Html' as FileType
    if (isMarkdownFile(filename)) return 'Markdown' as FileType
    if (FILE_EXTENSIONS.CODE.includes(getExt(filename))) return 'Code' as FileType
    if (isConfigFile(filename)) return 'Code' as FileType
    if (isTextEditable(filename)) return 'Text' as FileType

    return 'Binary' as FileType
  }

  /**
   * 判断文件是否可预览
   */
  const isPreviewable = (filename: string): boolean => {
    if (!filename || typeof filename !== 'string') return false
    return isPreviewableType(filename)
  }

  /**
   * 判断文件是否可编辑
   */
  const isEditable = (filename: string, fileSize: number): boolean => {
    if (fileSize > FILE_SIZE_THRESHOLDS.BIG_FILE) {
      return false
    }

    if (!filename || typeof filename !== 'string') return false
    const ext = getExt(filename)
    return FILE_EXTENSIONS.CODE.includes(ext) ||
           isTextEditable(filename) ||
           isConfigFile(filename) ||
           isHtmlFile(filename) ||
           isMarkdownFile(filename)
  }

  /**
   * 图片加载完成
   */
  const onImageLoad = (event: Event) => {
    const img = event.target as HTMLImageElement
    if (img.naturalWidth && img.naturalHeight) {
      currentImageDimensions.value = `${img.naturalWidth} × ${img.naturalHeight}`
    }
    imageLoading.value = false
  }

  /**
   * 图片加载失败
   */
  const onImageError = () => {
    imageLoading.value = false
    currentImageDimensions.value = ''
  }

  /**
   * 开始加载图片
   */
  const startImageLoad = () => {
    imageLoading.value = true
    currentImageDimensions.value = ''
  }

  /**
   * 获取媒体元数据
   */
  const getMediaMetadata = async (url: string): Promise<FilePreviewMetadata> => {
    const metadata: FilePreviewMetadata = {}

    // 对于图片，使用 Image 对象
    if (url.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)) {
      return new Promise((resolve) => {
        const img = new Image()
        img.onload = () => {
          metadata.width = img.naturalWidth
          metadata.height = img.naturalHeight
          resolve(metadata)
        }
        img.onerror = () => resolve(metadata)
        img.src = url
      })
    }

    // 对于视频/音频，可以使用 Video/Audio 对象
    // 但由于跨域等问题，这里简化处理
    return metadata
  }

  return {
    // 状态
    previewUrl,
    imageLoading,
    currentImageDimensions,

    // URL 相关
    getPreviewUrl,
    updatePreviewUrl,

    // 文件类型判断（同步，基于扩展名）
    getFileType,
    isPreviewable,
    isEditable,

    // 内容检测（异步，基于文件内容）
    detectByContent,

    // 事件处理
    onImageLoad,
    onImageError,
    startImageLoad,

    // 工具方法
    getMediaMetadata
  }
}
