import { Plugin } from 'vite'
import fs from 'fs'
import path from 'path'

interface FileWatcherOptions {
  // 目标可以是文件路径或文件夹路径
  file: string;
  // 回调函数，接收变化的文件路径、内容（如果有）和变化类型
  fn: (filePath: string, content?: string, eventType?: 'add' | 'change' | 'unlink') => void;
  // 防抖延迟，默认300ms
  delay?: number;
}

export function fileWatcher(options: FileWatcherOptions): Plugin {
  const {file, fn, delay = 300} = options
  const targetPath = path.resolve(file)
  let debounceTimer: NodeJS.Timeout | null = null

  // 检查目标是否为文件夹
  const isDir = fs.existsSync(targetPath) && fs.statSync(targetPath).isDirectory()
  console.log('正在监听文件：' + targetPath)
  return {
    name: 'file-watcher-plugin',

    configureServer(server) {
      // 添加要监听的目标（文件或文件夹）
      server.watcher.add(targetPath)

      // 处理文件/文件夹变化的通用函数
      const handleChange = (filePath: string, eventType: 'add' | 'change' | 'unlink') => {
        if (isDir && !filePath.startsWith(targetPath)) {
          return
        }
        if (!isDir && filePath !== targetPath) {
          return
        }
        // 防抖处理
        if (debounceTimer) {
          clearTimeout(debounceTimer)
        }

        debounceTimer = setTimeout(async () => {
          try {
            let content: string | undefined
            if (!isDir) {
              content = fs.readFileSync(filePath, 'utf-8')
            }
            fn(filePath, content, eventType)
          } catch (error) {
            console.error('处理文件变化时出错:', error)
          }
        }, delay)
      }

      if (isDir) {
        // 监听文件新增
        server.watcher.on('add', (filePath) => {
          handleChange(filePath, 'add')
        })

        // 监听文件删除
        server.watcher.on('unlink', (filePath) => {
          handleChange(filePath, 'unlink')
        })
      }

      // 监听文件修改
      server.watcher.on('change', (filePath) => {
        handleChange(filePath, 'change')
      })

    },
  }
}
