/**
 * 缓存管理工具
 */

// 缓存项接口
interface CacheItem<T = any> {
  data: T;
  timestamp: number;
  expiry: number;
  version?: string;
  tags?: string[];
}

// 缓存配置
interface CacheConfig {
  maxSize?: number;
  defaultExpiry?: number;
  version?: string;
  enableCompression?: boolean;
}

// 内存缓存管理器
export class MemoryCache {
  private cache = new Map<string, CacheItem>();
  private config: Required<CacheConfig>;
  private accessOrder = new Map<string, number>();
  private accessCounter = 0;

  constructor(config: CacheConfig = {}) {
    this.config = {
      maxSize: config.maxSize || 100,
      defaultExpiry: config.defaultExpiry || 5 * 60 * 1000, // 5分钟
      version: config.version || '1.0.0',
      enableCompression: config.enableCompression || false
    };
  }

  /**
   * 设置缓存
   */
  set<T>(key: string, data: T, expiry?: number, tags?: string[]): void {
    const item: CacheItem<T> = {
      data,
      timestamp: Date.now(),
      expiry: expiry || this.config.defaultExpiry,
      version: this.config.version,
      tags
    };

    // 检查缓存大小限制
    if (this.cache.size >= this.config.maxSize && !this.cache.has(key)) {
      this.evictLRU();
    }

    this.cache.set(key, item);
    this.updateAccessOrder(key);
  }

  /**
   * 获取缓存
   */
  get<T>(key: string): T | null {
    const item = this.cache.get(key);
    
    if (!item) {
      return null;
    }

    // 检查是否过期
    if (this.isExpired(item)) {
      this.cache.delete(key);
      this.accessOrder.delete(key);
      return null;
    }

    // 检查版本
    if (item.version !== this.config.version) {
      this.cache.delete(key);
      this.accessOrder.delete(key);
      return null;
    }

    this.updateAccessOrder(key);
    return item.data;
  }

  /**
   * 删除缓存
   */
  delete(key: string): boolean {
    this.accessOrder.delete(key);
    return this.cache.delete(key);
  }

  /**
   * 清空缓存
   */
  clear(): void {
    this.cache.clear();
    this.accessOrder.clear();
    this.accessCounter = 0;
  }

  /**
   * 根据标签清除缓存
   */
  clearByTags(tags: string[]): void {
    for (const [key, item] of this.cache.entries()) {
      if (item.tags && item.tags.some(tag => tags.includes(tag))) {
        this.delete(key);
      }
    }
  }

  /**
   * 检查缓存是否存在且有效
   */
  has(key: string): boolean {
    return this.get(key) !== null;
  }

  /**
   * 获取缓存大小
   */
  size(): number {
    return this.cache.size;
  }

  /**
   * 获取缓存统计信息
   */
  getStats() {
    let totalSize = 0;
    let expiredCount = 0;
    
    for (const item of this.cache.values()) {
      totalSize += JSON.stringify(item.data).length;
      if (this.isExpired(item)) {
        expiredCount++;
      }
    }

    return {
      totalItems: this.cache.size,
      totalSize,
      expiredCount,
      maxSize: this.config.maxSize
    };
  }

  /**
   * 清理过期缓存
   */
  cleanup(): number {
    let cleanedCount = 0;
    
    for (const [key, item] of this.cache.entries()) {
      if (this.isExpired(item)) {
        this.delete(key);
        cleanedCount++;
      }
    }
    
    return cleanedCount;
  }

  private isExpired(item: CacheItem): boolean {
    return Date.now() - item.timestamp > item.expiry;
  }

  private updateAccessOrder(key: string): void {
    this.accessOrder.set(key, ++this.accessCounter);
  }

  private evictLRU(): void {
    let lruKey = '';
    let lruAccess = Infinity;
    
    for (const [key, access] of this.accessOrder.entries()) {
      if (access < lruAccess) {
        lruAccess = access;
        lruKey = key;
      }
    }
    
    if (lruKey) {
      this.delete(lruKey);
    }
  }
}

// 持久化缓存管理器
export class PersistentCache {
  private prefix: string;
  private config: Required<CacheConfig>;

  constructor(prefix: string = 'app_cache', config: CacheConfig = {}) {
    this.prefix = prefix;
    this.config = {
      maxSize: config.maxSize || 50,
      defaultExpiry: config.defaultExpiry || 24 * 60 * 60 * 1000, // 24小时
      version: config.version || '1.0.0',
      enableCompression: config.enableCompression || true
    };
  }

  /**
   * 设置持久化缓存
   */
  set<T>(key: string, data: T, expiry?: number, tags?: string[]): void {
    try {
      const item: CacheItem<T> = {
        data,
        timestamp: Date.now(),
        expiry: expiry || this.config.defaultExpiry,
        version: this.config.version,
        tags
      };

      const serialized = JSON.stringify(item);
      localStorage.setItem(this.getKey(key), serialized);
      
      // 更新索引
      this.updateIndex(key);
    } catch (error) {
      console.warn('Failed to set persistent cache:', error);
      // 如果存储失败，尝试清理一些空间
      this.cleanup();
    }
  }

  /**
   * 获取持久化缓存
   */
  get<T>(key: string): T | null {
    try {
      const serialized = localStorage.getItem(this.getKey(key));
      
      if (!serialized) {
        return null;
      }

      const item: CacheItem<T> = JSON.parse(serialized);

      // 检查是否过期
      if (this.isExpired(item)) {
        this.delete(key);
        return null;
      }

      // 检查版本
      if (item.version !== this.config.version) {
        this.delete(key);
        return null;
      }

      return item.data;
    } catch (error) {
      console.warn('Failed to get persistent cache:', error);
      this.delete(key);
      return null;
    }
  }

  /**
   * 删除持久化缓存
   */
  delete(key: string): void {
    localStorage.removeItem(this.getKey(key));
    this.removeFromIndex(key);
  }

  /**
   * 清空所有缓存
   */
  clear(): void {
    const keys = this.getAllKeys();
    keys.forEach(key => localStorage.removeItem(key));
    localStorage.removeItem(this.getIndexKey());
  }

  /**
   * 根据标签清除缓存
   */
  clearByTags(tags: string[]): void {
    const keys = this.getAllKeys();
    
    keys.forEach(fullKey => {
      try {
        const serialized = localStorage.getItem(fullKey);
        if (serialized) {
          const item: CacheItem = JSON.parse(serialized);
          if (item.tags && item.tags.some(tag => tags.includes(tag))) {
            const key = fullKey.replace(this.prefix + '_', '');
            this.delete(key);
          }
        }
      } catch (error) {
        // 忽略解析错误，直接删除
        localStorage.removeItem(fullKey);
      }
    });
  }

  /**
   * 清理过期缓存
   */
  cleanup(): number {
    const keys = this.getAllKeys();
    let cleanedCount = 0;
    
    keys.forEach(fullKey => {
      try {
        const serialized = localStorage.getItem(fullKey);
        if (serialized) {
          const item: CacheItem = JSON.parse(serialized);
          if (this.isExpired(item)) {
            const key = fullKey.replace(this.prefix + '_', '');
            this.delete(key);
            cleanedCount++;
          }
        }
      } catch (error) {
        // 如果解析失败，也删除这个项
        localStorage.removeItem(fullKey);
        cleanedCount++;
      }
    });
    
    return cleanedCount;
  }

  private getKey(key: string): string {
    return `${this.prefix}_${key}`;
  }

  private getIndexKey(): string {
    return `${this.prefix}_index`;
  }

  private getAllKeys(): string[] {
    const keys: string[] = [];
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (key && key.startsWith(this.prefix + '_') && key !== this.getIndexKey()) {
        keys.push(key);
      }
    }
    return keys;
  }

  private updateIndex(key: string): void {
    try {
      const indexKey = this.getIndexKey();
      const index = JSON.parse(localStorage.getItem(indexKey) || '[]');
      
      if (!index.includes(key)) {
        index.push(key);
        
        // 限制索引大小
        if (index.length > this.config.maxSize) {
          const removedKey = index.shift();
          this.delete(removedKey);
        }
        
        localStorage.setItem(indexKey, JSON.stringify(index));
      }
    } catch (error) {
      console.warn('Failed to update cache index:', error);
    }
  }

  private removeFromIndex(key: string): void {
    try {
      const indexKey = this.getIndexKey();
      const index = JSON.parse(localStorage.getItem(indexKey) || '[]');
      const newIndex = index.filter((k: string) => k !== key);
      localStorage.setItem(indexKey, JSON.stringify(newIndex));
    } catch (error) {
      console.warn('Failed to remove from cache index:', error);
    }
  }

  private isExpired(item: CacheItem): boolean {
    return Date.now() - item.timestamp > item.expiry;
  }
}

// 全局缓存实例
export const memoryCache = new MemoryCache({
  maxSize: 200,
  defaultExpiry: 5 * 60 * 1000 // 5分钟
});

export const persistentCache = new PersistentCache('app_cache', {
  maxSize: 100,
  defaultExpiry: 24 * 60 * 60 * 1000 // 24小时
});

// 缓存装饰器
export function cached(
  expiry: number = 5 * 60 * 1000,
  keyGenerator?: (...args: any[]) => string
) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = async function (...args: any[]) {
      const key = keyGenerator 
        ? keyGenerator(...args)
        : `${target.constructor.name}_${propertyKey}_${JSON.stringify(args)}`;
      
      // 尝试从缓存获取
      let result = memoryCache.get(key);
      
      if (result === null) {
        // 缓存未命中，执行原方法
        result = await originalMethod.apply(this, args);
        
        // 存入缓存
        memoryCache.set(key, result, expiry);
      }
      
      return result;
    };
    
    return descriptor;
  };
}
