import { DiscoverSectionItemEntity } from '@/state/discoverStore';

export type ContestEntity = DiscoverSectionItemEntity<'contest_list'>;

export enum ContestSection {
  Hero = 'hero',
  RemixCTA = 'remix-cta',
  Submissions = 'submissions',
  VideoHighlight = 'video-highlight',
  FAQ = 'faq',
}

export enum ContestSectionVisibility {
  Everyone = 'everyone',
  Staff = 'staff',
  None = 'none',
}

export type TimeLeft = {
  days: number;
  hours: number;
  minutes: number;
  seconds: number;
};

export function getTimeLeft(untilMs: number): TimeLeft {
  const totalSeconds = Math.max(0, Math.floor(untilMs / 1000));
  const days = Math.floor(totalSeconds / 86400);
  const hours = Math.floor((totalSeconds % 86400) / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;
  return { days, hours, minutes, seconds };
}

export function formatTimeLeftCompact(timeLeft: TimeLeft): string {
  const { days, hours, minutes, seconds } = timeLeft;
  return `${days}d : ${hours}h : ${minutes}m : ${seconds}s`;
}

export function rangeLabel(startMs: number, endMs: number): string {
  try {
    const s = new Date(startMs);
    const e = new Date(endMs);
    const fmt: Intl.DateTimeFormatOptions = { month: 'long', day: 'numeric' };
    const sLabel = s.toLocaleDateString('en-US', fmt);
    const eLabel = e.toLocaleDateString('en-US', fmt);
    return `${sLabel} - ${eLabel}`;
  } catch {
    return '';
  }
}

export function dateLabel(dateMs: number): string {
  try {
    const d = new Date(dateMs);
    const fmt: Intl.DateTimeFormatOptions = { month: 'long', day: 'numeric' };
    return d.toLocaleDateString('en-US', fmt);
  } catch {
    return '';
  }
}

// Build a remix link for a given clip id, defaulting to create if missing
export function buildRemixHrefFromClipId(
  clipId?: string,
  type: 'cover' | 'extend' = 'cover'
): string {
  return clipId ? `/remix?type=${type}&song_id=${clipId}` : '/create';
}

// Imperatively redirect to the remix URL (avoids Link for iOS deep-linking issues)
export function redirectToRemixFromClipId(
  clipId?: string,
  type: 'cover' | 'extend' = 'cover'
): void {
  const href = buildRemixHrefFromClipId(clipId, type);
  if (typeof window !== 'undefined') {
    window.location.href = href;
  }
}

// Shared: compute whether a ContestSection should be visible given page config and staff flag
export function getSectionVisibility(
  sections: Record<ContestSection, { visibility: ContestSectionVisibility }>,
  section: ContestSection,
  isStaff: boolean
): boolean {
  const sectionVisibility = sections[section];
  if (!sectionVisibility) return false;
  if (sectionVisibility.visibility === ContestSectionVisibility.Everyone) {
    return true;
  }
  if (sectionVisibility.visibility === ContestSectionVisibility.Staff) {
    return isStaff;
  }
  if (sectionVisibility.visibility === ContestSectionVisibility.None) {
    return false;
  }
  return false;
}

// Return contest submissions visibility as an enum for consistent downstream use
export function getContestSubmissionsVisibility(
  contest:
    | { submissions_visibility_level?: 'everyone' | 'staff' | 'none' }
    | undefined
): ContestSectionVisibility | undefined {
  const level = contest?.submissions_visibility_level;
  switch (level) {
    case 'everyone':
      return ContestSectionVisibility.Everyone;
    case 'staff':
      return ContestSectionVisibility.Staff;
    case 'none':
      return ContestSectionVisibility.None;
    default:
      return undefined;
  }
}

// Convert string visibility level to enum for consistent downstream use
export function getContestVisibilityLevel(
  contestVisibilityLevel: string | undefined
): ContestSectionVisibility | undefined {
  switch (contestVisibilityLevel) {
    case 'everyone':
      return ContestSectionVisibility.Everyone;
    case 'staff':
      return ContestSectionVisibility.Staff;
    case 'none':
      return ContestSectionVisibility.None;
    default:
      return undefined;
  }
}

// Shared: compute if submissions should be shown for a given contest and user staff flag
export function shouldShowContestSubmissions(
  contest:
    | { submissions_visibility_level?: 'everyone' | 'staff' | 'none' }
    | undefined,
  isStaff: boolean
): boolean {
  if (!contest) return false;
  const enumLevel = getContestSubmissionsVisibility(contest);
  if (!enumLevel) return false; // default to hidden when not specified
  if (enumLevel === ContestSectionVisibility.Everyone) return true;
  if (enumLevel === ContestSectionVisibility.Staff) return isStaff;
  if (enumLevel === ContestSectionVisibility.None) return false;
  return false;
}

// Utility to detect and convert Twitch URLs to embed format
export function getTwitchEmbedUrl(
  url: string,
  autoPlay = true,
  muted = true
): string | null {
  // Check if it's a Twitch video URL
  const twitchVideoMatch = url.match(/twitch\.tv\/videos\/(\d+)/);
  if (twitchVideoMatch) {
    const videoId = twitchVideoMatch[1];
    return `https://player.twitch.tv/?video=${videoId}&parent=localhost&parent=suno.com&parent=www.suno.com&autoplay=${autoPlay}&muted=${muted}`;
  }

  // Check if it's already a Twitch embed URL
  if (url.includes('player.twitch.tv')) {
    return url;
  }

  return null;
}

// Extract original Twitch video URL from various formats
export function getTwitchVideoUrl(url: string): string | null {
  // If it's already a regular Twitch video URL, return it
  const twitchVideoMatch = url.match(/twitch\.tv\/videos\/(\d+)/);
  if (twitchVideoMatch) {
    return url;
  }

  // If it's a Twitch embed URL, extract the video ID and return the regular URL
  const embedMatch = url.match(/player\.twitch\.tv\/\?video=(\d+)/);
  if (embedMatch) {
    const videoId = embedMatch[1];
    return `https://www.twitch.tv/videos/${videoId}`;
  }

  return null;
}

// Check if a URL is a Twitch video URL (any format)
export function isTwitchVideoUrl(url: string): boolean {
  return getTwitchVideoUrl(url) !== null || getTwitchEmbedUrl(url) !== null;
}

export function dateToHtmlInput(date: Date | null): string {
  if (!date || isNaN(date.getTime())) return '';
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  return `${year}-${month}-${day}T${hours}:${minutes}`;
}

export function htmlInputToDate(input: string): Date | null {
  if (!input) return null;
  const date = new Date(input);
  return isNaN(date.getTime()) ? null : date;
}

export function isoStringToDate(
  isoString: string | null | undefined
): Date | null {
  if (!isoString) return null;
  const date = new Date(isoString);
  return isNaN(date.getTime()) ? null : date;
}

export function dateToIsoString(date: Date | null): string | null {
  if (!date || isNaN(date.getTime())) return null;
  return date.toISOString();
}
