/**
 * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
 */
import moment, {DurationInputArg2, Moment, unitOfTime} from 'moment';
import AuthService from 'services/Authentication.service';
import userStore from 'services/user-store';
import {DataValueType} from 'components/table';

let delta = 0;

export enum TimeFormats {
  Utc = 'utc',
  LocalTime = 'localTime'
}

export const defaultTimeFormat = `MM-DD-YYYY HH:mm:ss`;
export const isoTimeFormat = `YYYY-MM-DD HH:mm:ss`;
export const shortTimeFormat = `YYYY-MM-DD`;

export const getDuration = (start: Date, end: Date, unitOfTime: unitOfTime.Diff): number => {
  return moment.utc(end).diff(moment.utc(start), unitOfTime);
};

export const fetchPlatformTimeFromServer = async (): Promise<void> => {
  let platformTime;
  const localTimeBeforeCall = moment.utc().utc().valueOf();
  const headers = new Headers();

  headers.set('Authorization', `Basic ${await userStore.get(AuthService.token, '')}`);

  const response = await fetch('https://phenixrts.com/video/dash/time.txt', {headers});
  const localTimeAfterCall = moment.utc().utc().valueOf();
  const localTime = localTimeBeforeCall + (localTimeAfterCall - localTimeBeforeCall) / 2;
  const dateHeader = response.headers.get('date');

  if (dateHeader) {
    platformTime = moment.utc(dateHeader).utc();
    delta = moment.duration(platformTime.diff(localTime)).asMilliseconds();
  }
};

export const getAdjustedTime = (): Moment => {
  return moment.utc().add(delta, 'milliseconds').milliseconds(0);
};

export const getTimezoneAbbreviation = (date: Date): string => {
  const timezone = date
    .toString()
    .match(/\(.+\)/g)[0]
    .replace('(', '')
    .replace(')', '');
  let abbreviation = '';

  timezone.split(' ').forEach(word => {
    abbreviation += word.split('')[0];
  });

  return abbreviation;
};

export const formatDate = (date: Moment | string | Date, format: TimeFormats): string => {
  const isUTC = format === TimeFormats.Utc;
  const utcDate = moment.utc(date).format(`${isoTimeFormat} UTC`);
  const localDate = `${moment.utc(date).format(isoTimeFormat)} ${getTimezoneAbbreviation(moment.utc(date).toDate())}`;

  return isUTC ? utcDate : localDate;
};

export const getFormattedDate = (val: boolean | string | number, format: string = defaultTimeFormat): string => {
  // TODO: Change table component, as value type in this function should not be a boolean type
  if (!!val && (typeof val === 'number' || typeof val === 'string')) {
    return moment.utc(val).format(format);
  }

  return '';
};

export const getDateFromNow = (value: DataValueType): string => {
  return value ? moment.utc(value).fromNow() : '';
};

export const getDurationFromNow = (val: number, type: DurationInputArg2 = 'seconds'): number => {
  const now = moment.utc(new Date());
  const end = moment.utc(val);
  const duration = end.diff(now, type);

  return duration;
};

export const getMinAndMaxFromArrayOfObject = (
  // TODO: move out this function, as it is not related to dates
  arr: Record<string, any>[], // eslint-disable-line
  prop: string,
  mutate?: (val) => string | number
): {min: string | number; max: string | number} | null => {
  const arrLength = arr.length;

  if (arrLength) {
    let min = mutate ? mutate(arr[0][prop]) : arr[0][prop];
    let max = mutate ? mutate(arr[0][prop]) : arr[0][prop];
    let minIdx = 0;
    let maxIdx = 0;
    let tmp;

    for (let i = 0; i < arrLength; i += 1) {
      tmp = mutate ? mutate(arr[i][prop]) : arr[i][prop];

      if (tmp < min) {
        min = tmp;
        minIdx = i;
      }

      if (tmp > max) {
        max = tmp;
        maxIdx = i;
      }
    }

    return {
      min: arr[minIdx][prop],
      max: arr[maxIdx][prop]
    };
  }

  return {
    min: null,
    max: null
  };
};
