import { Injectable } from '@nestjs/common';

interface StorageItem {
  value: any;
  expiresAt?: number;
}

@Injectable()
export class InMemoryService {
  private storage = new Map<string, StorageItem>();
  private lists = new Map<string, any[]>();
  private hashes = new Map<string, Map<string, any>>();

  async set(key: string, value: any, ttl?: number): Promise<void> {
    const expiresAt = ttl ? Date.now() + ttl * 1000 : undefined;
    this.storage.set(key, { value, expiresAt });
    
    // Очистка просроченных
    this.cleanupExpired();
  }

  async get<T>(key: string): Promise<T | null> {
    const item = this.storage.get(key);
    
    if (!item) return null;
    
    if (item.expiresAt && Date.now() > item.expiresAt) {
      this.storage.delete(key);
      return null;
    }
    
    return item.value;
  }

  async del(key: string): Promise<void> {
    this.storage.delete(key);
  }

  async exists(key: string): Promise<boolean> {
    return this.storage.has(key);
  }

  // Списки
  async pushToList(key: string, value: any, maxLength: number = 100): Promise<void> {
    if (!this.lists.has(key)) {
      this.lists.set(key, []);
    }
    
    const list = this.lists.get(key)!;
    list.unshift(value); // Добавляем в начало
    
    if (list.length > maxLength) {
      list.length = maxLength;
    }
  }

  async getList<T>(key: string, start: number = 0, end: number = -1): Promise<T[]> {
    const list = this.lists.get(key) || [];
    
    if (end === -1) {
      end = list.length - 1;
    }
    
    return list.slice(start, end + 1);
  }

  async getListLength(key: string): Promise<number> {
    const list = this.lists.get(key) || [];
    return list.length;
  }

  // Хэши
  async setHash(key: string, field: string, value: any): Promise<void> {
    if (!this.hashes.has(key)) {
      this.hashes.set(key, new Map());
    }
    
    const hash = this.hashes.get(key)!;
    hash.set(field, value);
  }

  async getHash<T>(key: string, field: string): Promise<T | null> {
    const hash = this.hashes.get(key);
    if (!hash) return null;
    
    return hash.get(field) || null;
  }

  async getAllHash<T>(key: string): Promise<Record<string, T>> {
    const hash = this.hashes.get(key);
    if (!hash) return {};
    
    const result: Record<string, T> = {};
    hash.forEach((value, field) => {
      result[field] = value;
    });
    
    return result;
  }

  // Генерация ID
  async generateId(prefix: string): Promise<string> {
    const counter = Math.floor(Math.random() * 10000);
    return `${prefix}:${Date.now()}:${counter}`;
  }

  // Паттерн ключей
  getSessionKey(sessionId: string): string {
    return `chat:session:${sessionId}`;
  }

  getMessagesKey(sessionId: string): string {
    return `chat:messages:${sessionId}`;
  }

  getUserSessionsKey(userId?: string): string {
    return userId ? `user:sessions:${userId}` : 'anonymous:sessions';
  }

  // Очистка просроченных
  private cleanupExpired(): void {
    const now = Date.now();
    
    for (const [key, item] of this.storage.entries()) {
      if (item.expiresAt && now > item.expiresAt) {
        this.storage.delete(key);
      }
    }
  }

  // Для отладки
  getStats() {
    return {
      storageSize: this.storage.size,
      listsSize: this.lists.size,
      hashesSize: this.hashes.size,
    };
  }
}