import { DBSchema, IDBPDatabase } from 'idb';
import { IIndexedDbService } from './storage.interface';
import { decryptData, encryptData } from '@pos/base';
import { StorageActiveAccount } from './index';

export type IndexedDbValueEntity = any;

export class IndexedDbService implements IIndexedDbService<IndexedDbValueEntity> {
  dbPromise: IDBPDatabase<DBSchema> | any;
  dbTableName: string | any;

  constructor(dbPromise: IDBPDatabase<DBSchema> | any, dbTableName: string | any) {
    this.dbPromise = dbPromise;
    this.dbTableName = dbTableName;
  }

  async create(payload: IndexedDbValueEntity): Promise<void> {
    const id = StorageActiveAccount.get();
    const dataIsExist = await this.get();
    if (!dataIsExist && id) {
      const d = encryptData(JSON.stringify(payload));
      const item = { id, d };

      const db = await this.dbPromise;
      const tx = db?.transaction(this.dbTableName, 'readwrite');
      const store = tx?.objectStore(this.dbTableName);

      await store?.add(item);
    } else {
      this.update(payload);
    }
  }

  async get(): Promise<IndexedDbValueEntity> {
    const id = StorageActiveAccount.get();
    if (!id) return undefined;

    const db = await this.dbPromise;
    const tx = db.transaction(this.dbTableName, 'readwrite');
    const store = tx.objectStore(this.dbTableName);
    const result = await store.get(id);

    if (!result) return undefined;

    const d = JSON.parse(decryptData(result.d));
    return d;
  }

  async getAll(): Promise<IndexedDbValueEntity> {
    const db = await this.dbPromise;
    const tx = db.transaction(this.dbTableName, 'readwrite');
    const store = tx.objectStore(this.dbTableName);
    const result = await store.getAll();

    if (!result) return undefined;

    const newResult = result.map((item: any) => {
      return {
        ...item,
        d: JSON.parse(decryptData(item.d)),
      };
    });

    return newResult;
  }

  async update(payload: IndexedDbValueEntity): Promise<void> {
    const id = StorageActiveAccount.get();

    if (id) {
      const d = encryptData(JSON.stringify(payload));
      const item = { id, d };

      const db = await this.dbPromise;
      const tx = db.transaction(this.dbTableName, 'readwrite');
      const store = tx.objectStore(this.dbTableName);

      await store.put(item);
    }
  }

  async delete(): Promise<void> {
    const id = StorageActiveAccount.get();

    if (id) {
      const db = await this.dbPromise;
      const tx = db.transaction(this.dbTableName, 'readwrite');
      const store = tx.objectStore(this.dbTableName);
      await store.delete(id);
    }
  }
}
