import { BroadcastCreatedEvent, ClearedBroadcastEvent, ContextDeleteRecord, DeletedBroadcastEvent, IQueryResponse, IUrl } from "@api-client/core/build/browser.js";
import { StoreBroadcast } from "../StoreBroadcast.js";
import { WsHistory } from "../stores/WsHistory.js";
import { IdbStore } from "./IdbStore.js";

function setMidnight(date: Date): void {
  date.setHours(0, 0, 0, 0);
}

export class IdbWsHistory extends IdbStore implements WsHistory {
  channel = new BroadcastChannel(StoreBroadcast.wsHistory);

  async add(url: string): Promise<IUrl> {
    const tx = this.db.transaction('WsHistory', 'readwrite');
    const { store } = tx;
    let item = await store.get(url);
    const time = Date.now();
    const midnight = new Date(time);
    setMidnight(midnight);
    if (item) {
      item.cnt += 1;
      item.time = time;
      item.midnight = midnight.getTime();
    } else {
      item = {
        cnt: 1,
        time,
        key: url,
        midnight: midnight.getTime(),
      } as IUrl;
    }
    await store.put(item);
    await tx.done;

    const event: BroadcastCreatedEvent = {
      type: 'event',
      operation: 'created',
      key: url,
      data: item,
      kind: '',
      space: '',
      path: '/history/ws'
    };
    this.channel.postMessage(event);
    return item;
  }

  async query(query: string): Promise<IQueryResponse<IUrl>> {
    const q = String(query).toLowerCase();
    const tx = this.db.transaction('WsHistory', 'readonly');
    const result: IQueryResponse<IUrl> = {
      items: [],
    };
    for await (const cursor of tx.store) {
      const item = cursor.value;
      const url = String(item.key).toLowerCase();
      if (url.includes(q)) {
        result.items.push({
          doc: item,
          index: ['key'],
        });
      }
    }
    return result;
  }

  async delete(url: string): Promise<ContextDeleteRecord> {
    const tx = this.db.transaction('WsHistory', 'readwrite');
    await tx.store.delete(url);
    const event: DeletedBroadcastEvent = {
      type: 'event',
      operation: 'deleted',
      kind: '',
      key: url,
      path: '/history/ws',
      space: '',
    };
    this.channel.postMessage(event);
    return {
      key: url,
    }
  }

  async clear(): Promise<void> {
    await this.db.clear('WsHistory');
    const event: ClearedBroadcastEvent = {
      type: 'event',
      operation: 'cleared',
      path: '/history/ws',
      space: '',
      name: 'WsHistory',
    };
    this.channel.postMessage(event);
  }
}
