/**
 * localStorage 响应式封装
 *
 * @module composables/useLocalStorage
 * @description 提供响应式的 localStorage 数据持久化能力，自动同步数据变化
 */

import { ref, watch, onMounted } from 'vue'

/**
 * 创建响应式的 localStorage 绑定
 * @param {string} key - localStorage 键名
 * @param {*} defaultValue - 默认值
 * @param {Object} [options] - 配置选项
 * @param {boolean} [options.deep=true] - 是否深度监听对象变化
 * @param {boolean} [options.immediate=true] - 是否立即加载
 * @returns {UseLocalStorageReturn} 响应式数据和操作方法
 *
 * @example
 * // 基础用法
 * const { storedValue, load, save, clear } = useLocalStorage('app-user-name', 'Guest')
 *
 * // 对象用法
 * const { storedValue } = useLocalStorage('app-settings', { theme: 'light' })
 *
 * @see {@link https://vueuse.org/core/useLocalStorage/} 参考 VueUse 的实现
 */
export function useLocalStorage(key, defaultValue, options = {}) {
  const {
    deep = true, // 深度监听
    immediate = true, // 立即加载
    serializer = JSON, // 序列化器
    onError = (error) => console.error('localStorage操作失败:', error),
  } = options

  // 响应式数据
  const storedValue = ref(defaultValue)

  /**
   * 从 localStorage 加载数据
   * @returns {boolean} 是否加载成功
   */
  const load = () => {
    try {
      const item = localStorage.getItem(key)
      if (item === null || item === undefined) {
        storedValue.value = defaultValue
        return false
      }

      // 解析数据
      const parsed = serializer.parse(item)
      storedValue.value = parsed
      return true
    } catch (error) {
      onError(error)
      storedValue.value = defaultValue
      return false
    }
  }

  /**
   * 保存数据到 localStorage
   * @param {*} value - 要保存的值
   * @returns {boolean} 是否保存成功
   */
  const save = (value) => {
    try {
      const serialized = serializer.stringify(value)
      localStorage.setItem(key, serialized)
      return true
    } catch (error) {
      onError(error)
      return false
    }
  }

  /**
   * 清除 localStorage 中的数据
   * @returns {boolean} 是否清除成功
   */
  const clear = () => {
    try {
      localStorage.removeItem(key)
      storedValue.value = defaultValue
      return true
    } catch (error) {
      onError(error)
      return false
    }
  }

  // 监听数据变化自动保存
  watch(
    storedValue,
    (newValue) => {
      save(newValue)
    },
    { deep }
  )

  // 组件挂载时加载数据
  if (immediate) {
    onMounted(() => {
      load()
    })
  }

  return {
    /**
     * 响应式数据值
     * @type {Ref<any>}
     */
    storedValue,

    /**
     * 手动加载数据
     * @type {() => boolean}
     */
    load,

    /**
     * 手动保存数据
     * @type {(value: any) => boolean}
     */
    save,

    /**
     * 清除数据
     * @type {() => boolean}
     */
    clear,
  }
}

/**
 * @typedef {Object} UseLocalStorageReturn
 * @property {Ref<any>} storedValue - 响应式数据
 * @property {() => boolean} load - 手动加载函数
 * @property {(value: any) => boolean} save - 手动保存函数
 * @property {() => boolean} clear - 清除数据函数
 */

/**
 * 批量管理多个 localStorage 键
 * @param {Object} config - 配置对象，键为localStorage键名，值为默认值
 * @returns {Object} 响应式数据对象
 *
 * @example
 * const {
 *   theme: themeRef,
 *   language: languageRef,
 *   settings: settingsRef
 * } = useMultiLocalStorage({
 *   'app-theme': 'light',
 *   'app-language': 'zh-CN',
 *   'app-settings': { fontSize: 14 }
 * })
 */
export function useMultiLocalStorage(config) {
  const result = {}

  Object.keys(config).forEach(key => {
    const { storedValue } = useLocalStorage(key, config[key])
    result[key] = storedValue
  })

  return result
}

/**
 * localStorage 辅助工具函数
 */
export const localStorageHelpers = {
  /**
   * 检查 localStorage 是否可用
   * @returns {boolean}
   */
  isAvailable() {
    try {
      const test = '__localStorage_test__'
      localStorage.setItem(test, test)
      localStorage.removeItem(test)
      return true
    } catch {
      return false
    }
  },

  /**
   * 获取 localStorage 使用大小（近似值）
   * @returns {number} 大小（字节）
   */
  getSize() {
    let total = 0
    for (let key in localStorage) {
      if (localStorage.hasOwnProperty(key)) {
        total += localStorage[key].length + key.length
      }
    }
    return total
  },

  /**
   * 清空所有 localStorage 数据（谨慎使用）
   * @param {string[]} [excludeKeys] - 要排除的键名列表
   */
  clearAll(excludeKeys = []) {
    const keysToRemove = []
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i)
      if (!excludeKeys.includes(key)) {
        keysToRemove.push(key)
      }
    }
    keysToRemove.forEach(key => localStorage.removeItem(key))
  },

  /**
   * 导出所有 localStorage 数据为 JSON
   * @returns {string} JSON 字符串
   */
  exportToJSON() {
    const data = {}
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i)
      data[key] = localStorage.getItem(key)
    }
    return JSON.stringify(data, null, 2)
  },

  /**
   * 从 JSON 导入 localStorage 数据
   * @param {string} jsonString - JSON 字符串
   * @param {boolean} [merge=false] - 是否合并（false则清空后导入）
   * @returns {number} 导入的键数量
   */
  importFromJSON(jsonString, merge = false) {
    try {
      const data = JSON.parse(jsonString)

      if (!merge) {
        localStorageHelpers.clearAll()
      }

      let count = 0
      Object.keys(data).forEach(key => {
        localStorage.setItem(key, data[key])
        count++
      })

      return count
    } catch (error) {
      console.error('导入失败:', error)
      return 0
    }
  },
}
