import { format } from 'date-fns';
import { flatMap } from 'lodash-es';
import { type CompleteFile } from '@material-hu/types/attachments';

import { type FileCardType } from '@material-hu/components/design-system/FileCard/types';

import { useAuth } from 'src/contexts/JWTContext';
import useFormatDate from 'src/hooks/useFormatDate';
import usePermissions from 'src/hooks/usePermissions';
import { uploadGenericFile } from 'src/services/attachments';
import { type FileTypes } from 'src/types/attachments';
import { type Event, EventFeedPublishPolicy } from 'src/types/events';
import { type User } from 'src/types/user';
import { getHHString, getMMString, setTimeString } from 'src/utils/date';
import { preprocessImage } from 'src/utils/files';
import { type LokaliseTFunction, useLokaliseTranslation } from 'src/utils/i18n';
import { getFullLink } from 'src/utils/links';
import { UserPermissions } from 'src/utils/permissions';
import { getFullName, getInitials } from 'src/utils/userUtils';

export const hoursOptions = Array.from({ length: 24 }, (_, index) => {
  const hour = index;
  const time = `${hour.toString().padStart(2, '0')}`;
  return { value: time, label: time };
});

export const minutesOptions = Array.from({ length: 60 }, (_, index) => {
  const time = index.toString().padStart(2, '0');

  return { value: time, label: time };
});

export const useDescription = (event: Event) => {
  const { t } = useLokaliseTranslation('events');
  if (event?.liveStream) {
    return t('general:live_stream');
  }
  if (event?.location && event?.videoCallUrl) {
    return t('IN_PERSON_AND_ONLINE');
  }
  if (event?.location) {
    return t('IN_PERSON_EVENT');
  }
  return t('ONLINE_EVENT');
};

export const useCopetin = (event: Event, includeDateInCopetin?: boolean) => {
  if (!includeDateInCopetin) return '';

  const { t } = useLokaliseTranslation('events');

  const date = format(new Date(event.startDateTime), 'd MMM yyyy');
  if (!event.endDateTime) return date;

  return `${date} - ${format(new Date(event.startDateTime), 'HH:mm')} ${t('general:to')} ${format(new Date(event.endDateTime), 'HH:mm')}`;
};

export const formatInvitation = (values: any) => ({
  selectAllUsers: values.selectAllUsers,
  segmentationItemIds: flatMap(values.segmentationItemIds as number[]),

  [values.selectAllUsers ? 'excludedUserIds' : 'userIds']:
    values.excludedUserIds,
});

export const useIsEventsManager = () =>
  usePermissions([UserPermissions.MANAGE_EVENTS]).hasAll;

export const useIsEventCreator = (event: Event) => {
  const { user } = useAuth();
  return event.userId === user?.id;
};

export const userInitials = (user: User) => {
  const userFullName = user.fullName || getFullName(user);
  return getInitials(userFullName);
};

export const handleUploadFile = (
  file: Required<Omit<CompleteFile, 'attachment'>>,
  type?: FileTypes,
) =>
  uploadGenericFile(file.file, type).then(attachment => ({
    ...file,
    attachment: {
      url: attachment.url,
      name: attachment.name,
      type: attachment.type,
      size: attachment.size,
      bytes: attachment.bytes,
    },
  }));

export const getInitialFormValues = (event?: Event) => ({
  name: event?.name ?? '',
  description: event?.description ?? '',
  startDate: event?.startDateTime ? new Date(event.startDateTime) : null,
  endDate: event?.endDateTime ? new Date(event.endDateTime) : null,
  startHoursTime: event?.startDateTime ? getHHString(event.startDateTime) : '',
  startMinutesTime: event?.startDateTime
    ? getMMString(event.startDateTime)
    : '',
  endHoursTime: event?.endDateTime ? getHHString(event.endDateTime) : '',
  endMinutesTime: event?.endDateTime ? getMMString(event.endDateTime) : '',
  imagePreview: event?.imagePreview ? event.imagePreview : null,
  locationType: {
    liveStream: !!event?.liveStream,
    videocall: !!event?.videoCallUrl,
    presencial: event
      ? !!event.location && !event.videoCallUrl && !event.liveStream
      : false,
  },
  videoCallUrl: event?.videoCallUrl ?? '',
  hasLocation: !!event?.location,
  location: event?.location ?? '',
  inviteAll: false,
  visibility: {
    group: event ? !!event.groupId : false,
    allCommunity: event ? !event.groupId : false,
  },
  groupId: event?.groupId,
  segmentation: 1,
  maxInvitedUsers: event?.maxInvitedUsers?.toString() ?? 0,
  limitUsers: !!event?.maxInvitedUsers,
  feedPublishPolicy: {
    all: event
      ? event?.feedPublishPolicy === EventFeedPublishPolicy.ALL_INVITES
      : true,
    organizers:
      event?.feedPublishPolicy === EventFeedPublishPolicy.ONLY_ORGANIZERS,
  },
  coOrganizers: [],
});

export const preprocessFormData = async (values: any, eventId?: number) => {
  const processedValues = { ...values, id: eventId };

  if (processedValues.imagePreview) {
    processedValues.coverPictureUrl = await preprocessImage(
      processedValues.imagePreview,
    );
    delete processedValues.imagePreview;
  }

  if (processedValues.videoCallUrl) {
    processedValues.videoCallUrl = getFullLink({
      link: processedValues.videoCallUrl.trim(),
    });
  }

  processedValues.startDateTime = setTimeString(
    new Date(processedValues.startDate),
    `${processedValues.startHoursTime}:${processedValues.startMinutesTime}`,
  ).toISOString();

  if (processedValues.endDate) {
    processedValues.endDateTime = setTimeString(
      new Date(processedValues.endDate),
      `${processedValues.endHoursTime}:${processedValues.endMinutesTime}`,
    ).toISOString();
  }

  if (
    !processedValues.location ||
    (processedValues.locationType.videocall && !processedValues.hasLocation)
  ) {
    delete processedValues.location;
  }

  if (processedValues.visibility.allCommunity) {
    delete processedValues.groupId;
  }

  if (values.locationType.presencial) {
    delete processedValues.videoCallUrl;
  }

  if (values.locationType.liveStream) {
    processedValues.liveStream = true;
    delete processedValues.videoCallUrl;
    delete processedValues.location;
  } else {
    processedValues.liveStream = false;
  }

  if (!values.limitUsers) {
    processedValues.maxInvitedUsers = null;
  }

  if (values.limitUsers && values.maxInvitedUsers) {
    processedValues.maxInvitedUsers = Number(values.maxInvitedUsers);
  }

  if (values.feedPublishPolicy.all) {
    processedValues.feedPublishPolicy = EventFeedPublishPolicy.ALL_INVITES;
  } else if (values.feedPublishPolicy.organizers) {
    processedValues.feedPublishPolicy = EventFeedPublishPolicy.ONLY_ORGANIZERS;
  }

  return processedValues;
};

export const getInviteDefaultValues = () => ({
  selectAllUsers: false,
  excludedUserIds: [],
  segmentationItemIds: {},
  search: '',
});

export const formatEventDate = (startDateTime: string) => {
  const { t } = useLokaliseTranslation('events');
  const { formatDate } = useFormatDate();

  const formatedHour = formatDate(startDateTime, 'h:mm a');

  //we want to show the day with the first letter capitalized
  const combinationOfDate =
    formatDate(startDateTime, 'PPPP').charAt(0).toUpperCase() +
    formatDate(startDateTime, 'PPPP').slice(1);

  return `${combinationOfDate} ${t('AT')} ${formatedHour}`;
};

export const getImageFileCard = (event: Event, imageFile: File) => {
  if (event?.coverPictureUrl && imageFile) {
    return {
      file: imageFile,
      status: 'success' as FileCardType['status'],
      url: event.coverPictureUrl,
    };
  }
};

export const getEventLiveLocationWarningMessage = ({
  t,
  hasCommunityFeature,
  canCreateLivestream,
}: {
  t: LokaliseTFunction;
  hasCommunityFeature: boolean;
  canCreateLivestream: boolean;
}) => {
  if (!hasCommunityFeature) {
    return t('create_event_form.livestream_community_warning');
  }
  if (!canCreateLivestream) {
    return t('create_event_form.livestream_permission_warning');
  }
  return '';
};
