interface CacheEntry {
  data: unknown
  timestamp: Date
}

export class WailsCache {
  private cache = new Map<string, CacheEntry>()
  private subscribers = new Map<string, Set<() => void>>()

  /** Generar key string desde array */
  private getKey(queryKey: string[]): string {
    return queryKey.join(':')
  }

  /** Obtener dato del cache */
  get<T>(queryKey: string[]): T | null {
    const entry = this.cache.get(this.getKey(queryKey))
    return (entry?.data as T) ?? null
  }

  /** Guardar dato en cache */
  set<T>(queryKey: string[], data: T): void {
    const key = this.getKey(queryKey)
    this.cache.set(key, { data, timestamp: new Date() })
    this.notifySubscribers(key)
  }

  /** Verificar si existe en cache */
  has(queryKey: string[]): boolean {
    return this.cache.has(this.getKey(queryKey))
  }

  /** Obtener timestamp de última actualización */
  getTimestamp(queryKey: string[]): Date | null {
    const entry = this.cache.get(this.getKey(queryKey))
    return entry?.timestamp ?? null
  }

  /** Verificar si los datos están stale */
  isStale(queryKey: string[], staleTime: number): boolean {
    const entry = this.cache.get(this.getKey(queryKey))
    if (!entry) return true
    return Date.now() - entry.timestamp.getTime() > staleTime
  }

  /** Invalidar cache (esta key y todas las que empiezan igual) */
  invalidate(queryKey: string[]): void {
    const prefix = this.getKey(queryKey)
    const keysToDelete: string[] = []

    for (const key of this.cache.keys()) {
      if (key === prefix || key.startsWith(prefix + ':')) {
        keysToDelete.push(key)
      }
    }

    keysToDelete.forEach((key) => {
      this.cache.delete(key)
      this.notifySubscribers(key)
    })
  }

  /** Limpiar todo el cache */
  clear(): void {
    this.cache.clear()
    this.subscribers.forEach((_, key) => this.notifySubscribers(key))
  }

  /** Subscribirse a cambios en una key */
  subscribe(queryKey: string[], callback: () => void): () => void {
    const key = this.getKey(queryKey)
    if (!this.subscribers.has(key)) {
      this.subscribers.set(key, new Set())
    }
    this.subscribers.get(key)!.add(callback)

    return () => {
      this.subscribers.get(key)?.delete(callback)
    }
  }

  /** Notificar a subscribers */
  private notifySubscribers(key: string): void {
    this.subscribers.get(key)?.forEach((callback) => callback())
  }

  /** Obtener tamaño del cache */
  get size(): number {
    return this.cache.size
  }

  /** Obtener todas las keys */
  keys(): string[] {
    return Array.from(this.cache.keys())
  }
}

// Singleton global
export const wailsCache = new WailsCache()
