import Dexie from 'dexie'

export class BaseStorage<T extends { id: string }> {
  protected dexie: Dexie
  protected tableName: string

  constructor(tableName: string, schema: string, version = 1) {
    this.tableName = tableName
    this.dexie = new Dexie(tableName)
    this.dexie.version(version).stores({
      [tableName]: schema
    })
  }

  async add(item: T, overwrite = false) {
    try {
      const existing = await this.get(item.id)
      if (existing && !overwrite) return

      await this.dexie.table(this.tableName).put({ ...item })
    } catch (error) {
      console.error(`Failed to add ${this.tableName} ${item.id}:`, error)
    }
  }

  async update(id: string, item: Partial<T>) {
    try {
      await this.dexie.table(this.tableName).update(id, item)
    } catch (error) {
      console.error(`Failed to update ${this.tableName} ${id}:`, error)
    }
  }

  async delete(id: string) {
    try {
      await this.dexie.table(this.tableName).delete(id)
    } catch (error) {
      console.error(`Failed to delete ${this.tableName} ${id}:`, error)
    }
  }

  async get(id: string): Promise<T | null> {
    try {
      const item = await this.dexie.table(this.tableName).get(id)
      return item || null
    } catch (error) {
      console.error(`Failed to retrieve ${this.tableName} ${id}:`, error)
      return null
    }
  }

  async getByIds(ids: string[]): Promise<T[]> {
    try {
      const items = await this.dexie.table(this.tableName).bulkGet(ids)
      return items.filter((item) => item !== null)
    } catch (error) {
      console.error(`Failed to retrieve ${this.tableName} by ids:`, error)
      return []
    }
  }

  async getAll(): Promise<T[]> {
    try {
      return await this.dexie.table(this.tableName).toArray()
    } catch (error) {
      console.error(`Failed to retrieve all ${this.tableName}:`, error)
      return []
    }
  }

  liveQuery() {
    return this.dexie.table(this.tableName).toArray()
  }

  async reset() {
    try {
      await this.dexie.table(this.tableName).clear()
    } catch (error) {
      console.error(`Failed to clear ${this.tableName}:`, error)
    }
  }

  async destroy() {
    try {
      await this.dexie.delete()
    } catch (error) {
      console.error(`Failed to destroy ${this.tableName}:`, error)
    }
  }
}
