/* eslint-disable @typescript-eslint/no-namespace */
import { UNLIMITED } from '@app/event-emitter/consts/consts';
import { Timestamped } from '@app/event-emitter/models/timestamped';
import { TimestampNowFill } from '@app/event-emitter/utils/timestamp-now-fill';
import { Injectable } from '@nestjs/common';
import nano from 'nano';
import { DailyEccmReportsUserCommentsDatasource } from 'src/couchdb-datasources/daily-eccm-reports-user-comments.datasource';

export namespace DailyEccmUserComments {
  export namespace Models {
    export type Item = {
      userId: number;
      date: string;
      comment: string;
    };

    export type CouchDbItem = Item & Timestamped & nano.DocumentGetResponse;
  }
}

@Injectable()
export class DailyEccmUserCommentsService {
  constructor(private datasource: DailyEccmReportsUserCommentsDatasource) {}

  async setComment(
    userId: number,
    date: string,
    comment: string,
  ): Promise<void> {
    const key = this.getKey(userId, date);
    const ds = await this.datasource.getDatasource();
    let existsItem: any;
    try {
      existsItem = await ds.get(key);
    } catch (ex) {
      existsItem = null;
    }
    const item: DailyEccmUserComments.Models.CouchDbItem = TimestampNowFill({
      userId: userId,
      date: date,
      comment: comment,
      _id: key,
      _rev: existsItem?._rev,
    });
    await ds.insert(item);
  }

  async loadComment(userId: number, date: string): Promise<string | null> {
    const key = this.getKey(userId, date);
    const ds = await this.datasource.getDatasource();
    try {
      const res: any = await ds.get(key);
      return res.comment;
    } catch (ex) {
      return null;
    }
  }

  async loadComments(
    userIds: number[],
    date: string,
  ): Promise<Record<number, string>> {
    const query: nano.MangoQuery = {
      limit: UNLIMITED,
      selector: {
        userId: {
          $in: userIds,
        },
        date: {
          $eq: date,
        },
      },
    };
    const ds = await this.datasource.getDatasource();
    const resp = await ds.find(query);
    if (!resp || !resp.docs || resp.docs.length <= 0) {
      return [];
    }
    const items = resp.docs;
    const res: Record<number, string> = {};
    for (const key in items) {
      if (Object.prototype.hasOwnProperty.call(items, key)) {
        const item = items[key];
        res[item.userId] = item.comment;
      }
    }
    return res;
  }

  private getKey(userId: number, date: string): string {
    return `${date} - ${userId}`;
  }
}
