import { RestDay } from '@/openapi/idm';
import { convertDateFormat, DateFormat } from '@/utils/format-date';
import IdmServiceDomains from '@services/idm/domains';

export type WorkCalendarDay = Pick<RestDay, 'name' | 'description' | 'workDay'>;

export class WorkCalendarForDomain {

  private domainId: string;

  restDaysCalendar: Record<string, RestDay> = {};
  private restDaysOfWeek: Record<string, RestDay> = {};
  private restDaysOfMonth: Record<string, RestDay> = {};

  private default: WorkCalendarDay = {
    workDay: true,
    name: '',
    description: '',
  }

  constructor(domainId: string) {
    this.domainId = domainId;
  }

  getDomainId() {
    return this.domainId;
  }

  async fetch(): Promise<void> {
    const days = await IdmServiceDomains.getDomainRestDays({ id: this.domainId });
    days.forEach((day) => {
      const longDate = day.longDate || 0;
      if (longDate === 0) {
        if (day.numDayOfWeek) {
          this.restDaysOfWeek[day.numDayOfWeek] = day;
        }
        if (day.numDayOfMonth) {
          this.restDaysOfMonth[day.numDayOfMonth] = day;
        }
      } else {
        const dateNumber = convertDateFormat(new Date(longDate * 1000), '', DateFormat.dateNumber);
        this.restDaysCalendar[dateNumber] = day;
      }
    });
  }

  private mergeDays(...days: WorkCalendarDay[]): WorkCalendarDay  {
    return days
      .filter((day) => !!day)
      .reduce((res, day): WorkCalendarDay => {
        if (day == null) return res;

        return {
          name: res.name ? `${res.name}, ${day.name || ''}` : day.name,
          description: res.description ? `${res.description}, ${day.description || ''}` : day.description,
          workDay: res.workDay && day.workDay
        };
      }, this.default);
  }

  public getDayofAWeek(dayOfWeek: string | number): WorkCalendarDay {
    return this.mergeDays(this.restDaysOfWeek[dayOfWeek]);
  }

  public getDayofAMonth(dayOfMonth: string | number): WorkCalendarDay {
    return this.mergeDays(this.restDaysOfMonth[dayOfMonth]);
  }

  public getDay(date: Date): WorkCalendarDay {
    const dayOfWeek = date.getDay() + 1; // Приводим к серверному формату 1-7
    const dayOfMonth = date.getDate();
    const indexKey = convertDateFormat(date, '', DateFormat.dateNumber);

    return this.mergeDays(
      this.restDaysOfWeek[dayOfWeek],
      this.restDaysOfMonth[dayOfMonth],
      this.restDaysCalendar[indexKey],
    );
  }
}
