import type { RemovableRef, StorageLike } from "@vueuse/core";

interface CacheData<T> {
  value: T;
  expireTime?: number; // 过期时间戳（毫秒）
}

interface UseStorageCacheOptions {
  /**
   * 缓存过期时间（秒）
   * @default undefined 永不过期
   */
  ttl?: number;
  /**
   * 存储介质
   * @default localStorage
   */
  storage?: StorageLike;
  /**
   * 是否在过期后自动删除
   * @default true
   */
  autoRemoveOnExpire?: boolean;
}

/**
 * 使用支持过期时间的 Storage
 * @param key 存储键
 * @param initialValue 初始值
 * @param options 配置项
 * @returns 响应式存储引用
 *
 * @example
 * ```ts
 * // 创建一个 5 分钟后过期的缓存
 * const token = useStorageCache('user-token', '', { ttl: 300 })
 *
 * // 设置值
 * token.value = 'new-token'
 *
 * // 检查是否过期
 * if (isExpired(token)) {
 *   console.log('Token 已过期')
 * }
 *
 * // 刷新过期时间
 * refreshExpire(token, 600) // 延长到 10 分钟
 * ```
 */
export function useStorageCache<T>(
  key: string,
  initialValue: T,
  options: UseStorageCacheOptions = {},
): RemovableRef<T> {
  const {
    ttl,
    storage = localStorage,
    autoRemoveOnExpire = true,
  } = options;

  // 尝试从 storage 读取缓存数据
  const rawData = storage.getItem(key);
  let cachedData: CacheData<T> | null = null;

  if (rawData) {
    try {
      cachedData = JSON.parse(rawData) as CacheData<T>;

      // 检查是否过期
      if (cachedData.expireTime && Date.now() > cachedData.expireTime) {
        // 已过期
        if (autoRemoveOnExpire) {
          storage.removeItem(key);
        }
        cachedData = null;
      }
    }
    catch (error) {
      console.error(`解析缓存数据失败 [${key}]:`, error);
      cachedData = null;
    }
  }

  // 计算初始值
  const defaultValue = cachedData ? cachedData.value : initialValue;

  // 使用 useStorage 创建响应式引用
  const storageRef = useStorage<T>(
    key,
    defaultValue,
    storage,
    {
      serializer: {
        read: (raw: string) => {
          try {
            const data = JSON.parse(raw) as CacheData<T>;
            // 再次检查过期时间（防止并发问题）
            if (data.expireTime && Date.now() > data.expireTime) {
              if (autoRemoveOnExpire) {
                storage.removeItem(key);
              }
              return initialValue;
            }
            return data.value;
          }
          catch {
            return initialValue;
          }
        },
        write: (value: T) => {
          const cacheData: CacheData<T> = {
            value,
          };

          // 如果设置了 ttl，计算过期时间
          if (ttl && ttl > 0) {
            cacheData.expireTime = Date.now() + ttl * 1000;
          }

          return JSON.stringify(cacheData);
        },
      },
    },
  );

  return storageRef;
}

/**
 * 检查缓存是否过期
 * @param key 存储键或存储引用
 * @param storage 存储介质
 * @returns 是否过期
 */
export function isCacheExpired(
  key: string | RemovableRef<any>,
  storage: StorageLike = localStorage,
): boolean {
  const cacheKey = typeof key === "string" ? key : key.value;

  try {
    const rawData = storage.getItem(cacheKey);
    if (!rawData) {
      return true;
    }

    const data = JSON.parse(rawData) as CacheData<any>;
    if (!data.expireTime) {
      return false; // 没有设置过期时间，永不过期
    }

    return Date.now() > data.expireTime;
  }
  catch {
    return true;
  }
}

/**
 * 刷新缓存过期时间
 * @param key 存储键
 * @param ttl 新的过期时间（秒）
 * @param storage 存储介质
 */
export function refreshCacheExpire(
  key: string,
  ttl: number,
  storage: StorageLike = localStorage,
): void {
  try {
    const rawData = storage.getItem(key);
    if (!rawData) {
      return;
    }

    const data = JSON.parse(rawData) as CacheData<any>;
    data.expireTime = Date.now() + ttl * 1000;

    storage.setItem(key, JSON.stringify(data));
  }
  catch (error) {
    console.error(`刷新缓存过期时间失败 [${key}]:`, error);
  }
}

/**
 * 获取缓存剩余有效时间（秒）
 * @param key 存储键
 * @param storage 存储介质
 * @returns 剩余时间（秒），如果已过期返回 0，如果永不过期返回 Infinity
 */
export function getCacheRemainingTime(
  key: string,
  storage: StorageLike = localStorage,
): number {
  try {
    const rawData = storage.getItem(key);
    if (!rawData) {
      return 0;
    }

    const data = JSON.parse(rawData) as CacheData<any>;
    if (!data.expireTime) {
      return Infinity; // 永不过期
    }

    const remaining = Math.max(0, data.expireTime - Date.now());
    return Math.floor(remaining / 1000);
  }
  catch {
    return 0;
  }
}

/**
 * 清除指定键的过期缓存
 * @param keys 要检查的键列表
 * @param storage 存储介质
 * @returns 被删除的键数量
 */
export function clearExpiredCaches(
  keys: string[],
  storage: StorageLike = localStorage,
): number {
  let removedCount = 0;

  keys.forEach((key) => {
    try {
      const rawData = storage.getItem(key);
      if (!rawData) {
        return;
      }

      const data = JSON.parse(rawData) as CacheData<any>;

      // 检查是否过期
      if (data.expireTime && Date.now() > data.expireTime) {
        storage.removeItem(key);
        removedCount++;
      }
    }
    catch {
      // 忽略解析错误
    }
  });

  return removedCount;
}
