import { intervalToDuration } from 'date-fns';

import { PostErrorCodes } from 'src/pages/dashboard/feed/constants';
import { Poll } from 'src/types/posts';

import { dateIsBefore } from './date';

export const getPollDeadlineValidationErrorKey = (
  error: any,
): string | null => {
  if (error?.response?.status === 400) {
    const errorResponse = error.response.data;

    // Handles specific error format: [{"IsFutureDateAllowingNull":"poll.pollConfiguration.The poll's deadline must be in the future if specified"}]
    if (
      errorResponse &&
      Array.isArray(errorResponse) &&
      errorResponse[0]?.IsFutureDateAllowingNull
    ) {
      return 'post:poll_deadline_future_error';
    }
  }

  return null;
};

/**
 * Cannot edit post with poll that already has votes
 */
export const getPollEditWithVotesErrorKey = (error: any): string | null => {
  if (
    error?.response?.data?.code === PostErrorCodes.CANNOT_EDIT_POLL_WITH_VOTES
  ) {
    return 'post:cannot_edit_post_with_votes';
  }

  return null;
};

/**
 * Cannot vote on a poll that has ended
 */
export const getPollEndedVoteErrorKey = (error: any): string | null => {
  if (error?.response?.data?.code === PostErrorCodes.POLL_HAS_ENDED) {
    return 'post:poll_has_ended_error';
  }

  return null;
};

/**
 * Check if a poll has ended based on its deadline
 */
export const isPollEnded = (endsAt: string | null): boolean => {
  if (!endsAt) return false;
  return dateIsBefore(endsAt, new Date());
};

/**
 * Get the remaining time until poll deadline
 */
export const getPollTimeRemaining = (
  endsAt: string | null,
): {
  ended: boolean;
  days?: number;
  hours?: number;
  minutes?: number;
} => {
  if (!endsAt) return { ended: false };

  if (isPollEnded(endsAt)) {
    return { ended: true };
  }

  const now = new Date();
  const deadline = new Date(endsAt);

  const duration = intervalToDuration({
    start: now,
    end: deadline,
  });

  return {
    ended: false,
    days: duration.days || 0,
    hours: duration.hours || 0,
    minutes: duration.minutes || 0,
  };
};

/**
 * Format poll deadline message for display
 */
export const formatPollDeadlineMessage = (
  endsAt: string | null,
  t: (key: string, options?: any) => string,
): string | null => {
  if (!endsAt) return null;

  if (isPollEnded(endsAt)) {
    return t('poll_finished');
  }

  const now = new Date();
  const deadline = new Date(endsAt);

  const duration = intervalToDuration({
    start: now,
    end: deadline,
  });

  const { days = 0, hours = 0, minutes = 0 } = duration;

  if (days > 0) {
    return t('ends_in_days', { count: days });
  } else if (hours > 0) {
    return t('ends_in_hours', { count: hours });
  } else if (minutes > 0) {
    return t('ends_in_minutes', { count: minutes });
  } else {
    return t('poll_ends_soon');
  }
};

/**
 * Get poll status and permission flags for menu display
 */
export const getPollMenuFlags = (
  poll: Poll | null,
  userId: number | undefined,
  postUserId: number,
) => {
  if (!poll) {
    return {
      pollEnded: false,
      hasPollThatIsVoted: false,
      canEndPollNow: false,
      canEditPollDeadline: false,
    };
  }

  const pollEnded = isPollEnded(poll.pollConfiguration?.endsAt ?? null);
  const hasPollThatIsVoted = poll.totalAnswerCount > 0;

  const canEndPollNow = Boolean(
    poll &&
      !pollEnded &&
      poll.pollConfiguration?.endsAt &&
      userId === postUserId,
  );

  const canEditPollDeadline = Boolean(poll && userId === postUserId);

  return {
    hasPollThatIsVoted,
    canEndPollNow,
    canEditPollDeadline,
  };
};

/**
 * Create a default poll deadline that's one day from now, rounded to the hour
 */
export const createDefaultPollDeadline = (): Date => {
  const oneDayFromNow = new Date();
  oneDayFromNow.setDate(oneDayFromNow.getDate() + 1);
  return oneDayFromNow;
};
