import moment, { Moment } from 'moment';
import { GetConversionRequest } from '@/recruits/openapi/person-registry';
import { MilitaryCommissarDecisions } from '../openapi/decision-document';
import {
  AccountsJournalRequestV1,
  ObjectJournalRequest,
} from '@/recruits/openapi/journal-service';
import { SubpoenaByRecruitV5 } from '@/recruits/openapi/subpoena-service';

export function mask(
  inputText: string,
  mask: string,
  placeholderCharacter = '*'
): string {
  try {
    const stringArray: Array<string> = inputText?.split('') || [];

    return mask.replace(
      RegExp(`\\${placeholderCharacter}`, 'g'),
      () => stringArray.shift() || ''
    );
  } catch (e) {
    return '';
  }
}

export function formatDate(
  isoDateString: string | Moment,
  formatString = 'DD.MM.YYYY'
): string {
  if (isoDateString) {
    const momentDate = moment(isoDateString);
    return momentDate.isValid()
      ? momentDate.format(formatString)
      : String(isoDateString);
  } else {
    return '';
  }
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function callMethodOnComponent(ref: any, methodName: string) {
  if (ref && methodName in ref && typeof ref[methodName] === 'function') {
    return ref[methodName]();
  }
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function getObjDict(dict: any) {
  return dict.reduce(
    (result: Record<string, string>, value: Record<string, string>) => {
      return {
        ...result,
        [value.code]: value.value,
      };
    },
    {}
  );
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function prepareMilitaryRequestParams(ob: any) {
  return {
    pagination: {
      sortBy: ob.sortby,
      descending: ob.descending,
      page: Number(ob.page),
      rowsPerPage: Number(ob.perpage),
    },
    search: {
      search: ob.search,
      lastName: ob.lastname,
      firstName: ob.firstname,
      middleName: ob.middlename,
      birthDateFrom: ob.birthdatefrom,
      birthDateTo: ob.birthdateto,
      inn: ob.inn ? Number(ob.inn) : undefined,
      snils: ob.snils,
      idern: ob.idern,
      documentType: ob.documentType,
      documentSeries: ob.series,
      documentNumber: ob.number,
      statuses: ob.statuses,
    },
  };
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function prepareRecruitsFromListRequestParams(ob: any) {
  return {
    pagination: {
      sortBy: ob.sortby,
      descending: ob.descending,
      page: Number(ob.page),
      rowsPerPage: Number(ob.perpage),
    },
    search: {
      search: ob.search,
      lastName: ob.lastname,
      firstName: ob.firstname,
      middleName: ob.middlename,
      // address: ob.address,
      birthDateFrom: ob.birthdatefrom,
      birthDateTo: ob.birthdateto,
      snils: ob.snils,
      // status: ob.status,
      idERN: ob.idern,
      documentSeries: ob.documentseries,
      documentNumber: ob.documentnumber,
      subpoenaSeries: ob.subpoenaseries,
      subpoenaNumber: ob.subpoenanumber,
    },
  };
}

/**
 * Функция подготовки параметров для запроса списка журналирования изменения объекта
 * @param ob
 */
export function prepareLogObjectParams(ob: any): ObjectJournalRequest {
  return {
    pagination: {
      sortBy: ob.sortby,
      descending: ob.descending,
      page: Number(ob.page),
      rowsPerPage: Number(ob.perpage),
    },
    search: {
      search: ob.search,
      objectType: ob.objecttype,
      objectDescription: ob.objectdescription,
      vkFio: ob.vkfio,
      type: ob.type,
      dateFrom: ob.datefrom,
      dateTo: ob.dateto,
    },
  };
}

export function prepareConversionParams(
  ob: Record<string, any>
): GetConversionRequest {
  return {
    pagination: {
      sortBy: ob.sortby,
      descending: ob.descending,
      page: Number(ob.page),
      rowsPerPage: Number(ob.perpage),
    },
    search: {
      search: ob.search,
      firstName: ob.firstname,
      lastName: ob.lastname,
      middleName: ob.middlename,
      idERN: ob.idern,
      snils: ob.snils,
      address: ob.address,
      birthDateFrom: ob.datefrom,
      birthDateTo: ob.dateto,
      series: ob.series,
      number: ob.number,
    },
  };
}

export function prepareJournalActionsParams(
  ob: Record<string, any>
): AccountsJournalRequestV1 {
  return {
    pagination: {
      sortBy: ob.sortby,
      descending: ob.descending,
      page: Number(ob.page),
      rowsPerPage: Number(ob.perpage),
    },
    search: {
      search: ob.search,
      lastName: ob.lastName,
      firstName: ob.firstName,
      middleName: ob.middleName,
      event: ob.event,
      dateFrom: ob.dateFrom,
      dateTo: ob.dateTo,
    },
  };
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function extractNameFromS3Url(s3Url: string) {
  // убрать всякие GUID-ы из названий
  const fileName = s3Url.replace(
    /-?[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/g,
    ''
  );
  // вернуть имя файла без всяких путей
  return fileName.substring(fileName.lastIndexOf('/') + 1);
}

export const HOLYDAYS = [0, 6];

// FIXME исправить логику getNWorkDaysSince чтобы не сыпало warning
export function getNWorkDaysSince(
  days: number,
  startDate: Date | string | number
): string[] {
  const dates: string[] = [];
  let workDays = 0;
  let date = moment(startDate);
  do {
    date = date.add(1, 'day');
    if (!HOLYDAYS.includes(date.get('day'))) workDays++;
    dates.push(date.format('YYYY/MM/DD'));
  } while (workDays < (days || 0));
  return dates;
}

// функция получения и конверта словаря в формат [{value,label}]
export function getDictionaryFormatedToOptions(
  dictionary: Record<string, string>
): { label: string; value: string }[] {
  return Object.entries(dictionary).map((entry) => {
    return { value: entry[0], label: String(entry[1]) };
  });
}

// Приведение размеров к удобочитаемому формату
export function formatBytes(bytes: number, decimalSize = 2): string {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  const index = Math.floor(Math.log(bytes) / Math.log(k));
  return (
    parseFloat((bytes / Math.pow(k, index)).toFixed(decimalSize)) +
    ' ' +
    sizes[index]
  );
}

// Индикатор того, что повестка подписана
export function isSubpoenaSigned(subpoena: SubpoenaByRecruitV5): boolean {
  return subpoena?.file?.format === 'pdf';
}

// Индикатор активной повестки (для вкладки в карточке гражданина)
export const subpoenaIsActive = (subpoena: SubpoenaByRecruitV5): boolean => {
  return subpoena.status === '3.7' || subpoena.status === '3.13';
};

// Индикатор того, что решение подписано
export function isDecisionSigned(
  decision: MilitaryCommissarDecisions
): boolean {
  return decision?.status === '2' || decision?.status === '3' || false;
}

/**
 * Функция проверки наличия строковых данных
 * @param data{string}
 * @return {boolean}
 */
export const determiningDataAvailability = (data: string): boolean => !!data;
