
import { IDataAdapter } from './IDataAdapter';
import { AppError, ErrorCodes } from '../../utils/AppError';
import { INITIAL_DATA } from './seedData';

export class DemoDataAdapter implements IDataAdapter {
  private dataStore: Map<string, any[]> = new Map();
  private settingsStore: any;

  constructor() {
    this.initializeData();
  }

  private initializeData() {
    // Load initial data from seedData into Map
    Object.keys(INITIAL_DATA).forEach(key => {
      if (key === 'settings') {
        this.settingsStore = JSON.parse(JSON.stringify(INITIAL_DATA[key])); // Deep copy
      } else {
        this.dataStore.set(key, JSON.parse(JSON.stringify(INITIAL_DATA[key]))); // Deep copy array
      }
    });
  }

  async connect(): Promise<void> {
    // Simulate connection delay
    return new Promise(resolve => setTimeout(resolve, 50));
  }

  async disconnect(): Promise<void> {
    return Promise.resolve();
  }

  async find<T>(collection: string, filter?: any): Promise<T[]> {
    if (collection === 'settings') return [this.settingsStore] as unknown as T[];
    
    const items = this.dataStore.get(collection) || [];
    if (!filter) return items as T[];

    return items.filter(item => {
      let match = true;
      for (const key in filter) {
        if (item[key] !== filter[key]) {
          match = false;
          break;
        }
      }
      return match;
    }) as T[];
  }

  async findOne<T>(collection: string, filter: any): Promise<T | null> {
    const items = await this.find<T>(collection, filter);
    return items.length > 0 ? items[0] : null;
  }

  async create<T>(collection: string, data: any): Promise<T> {
    if (collection === 'settings') {
        throw new AppError('Cannot create settings, update only', 400);
    }

    const items = this.dataStore.get(collection) || [];
    const newItem = { 
        ...data, 
        _id: data._id || `id-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
    };
    
    items.unshift(newItem); // Add to beginning
    this.dataStore.set(collection, items);
    
    return newItem as T;
  }

  async update<T>(collection: string, filter: any, data: Partial<T>): Promise<T> {
    if (collection === 'settings') {
        this.settingsStore = { ...this.settingsStore, ...data };
        return this.settingsStore as T;
    }

    const items = this.dataStore.get(collection) || [];
    const index = items.findIndex(item => {
        let match = true;
        for (const key in filter) {
            if (item[key] !== filter[key]) {
                match = false;
                break;
            }
        }
        return match;
    });

    if (index === -1) {
        throw new AppError('Document not found', 404, ErrorCodes.NOT_FOUND);
    }

    const updatedItem = { ...items[index], ...data };
    items[index] = updatedItem;
    this.dataStore.set(collection, items);

    return updatedItem as T;
  }

  async delete(collection: string, filter: any): Promise<boolean> {
    const items = this.dataStore.get(collection) || [];
    const initialLength = items.length;
    
    const filteredItems = items.filter(item => {
        let match = true;
        for (const key in filter) {
            if (item[key] !== filter[key]) {
                match = false;
                break;
            }
        }
        return !match; // Keep items that DON'T match
    });

    this.dataStore.set(collection, filteredItems);
    return filteredItems.length < initialLength;
  }

  async count(collection: string, filter?: any): Promise<number> {
    const items = await this.find(collection, filter);
    return items.length;
  }
}
