import {
  Film,
  FolderTree,
  Image as ImageIcon,
  Layers,
  ListVideo,
  Music,
  Radio,
  Repeat,
  Sparkles,
  Tv,
  Video
} from 'lucide-react';
import type { LibraryBrowseItem, LibraryBrowseMediaType } from '../api';

export const TYPE_ICON: Record<LibraryBrowseMediaType, typeof Film> = {
  Movie: Film,
  TelevisionShow: Tv,
  TelevisionSeason: Tv,
  Artist: Music,
  Collection: FolderTree,
  SmartCollection: Sparkles,
  MultiCollection: Layers,
  RerunCollection: Repeat,
  Playlist: ListVideo,
  Episode: Tv,
  MusicVideo: Video,
  Song: Music,
  OtherVideo: Film,
  Image: ImageIcon,
  RemoteStream: Radio
};

export const TYPE_LABEL: Record<LibraryBrowseMediaType, string> = {
  Movie: 'Movie',
  TelevisionShow: 'Show',
  TelevisionSeason: 'Season',
  Artist: 'Artist',
  Collection: 'Collection',
  SmartCollection: 'Smart',
  MultiCollection: 'Multi',
  RerunCollection: 'Rerun',
  Playlist: 'Playlist',
  Episode: 'Episode',
  MusicVideo: 'Music Video',
  Song: 'Song',
  OtherVideo: 'Other Video',
  Image: 'Image',
  RemoteStream: 'Remote Stream'
};

// The SPA detail-page path for a browse item, or null if the kind has no detail page.
// item.id is the domain id the detail endpoints expect (movie/show/season/artist id).
export function mediaDetailPath(item: LibraryBrowseItem): string | null {
  switch (item.mediaType) {
    case 'Movie':
      return `/app/media/movies/${item.id}`;
    case 'TelevisionShow':
      return `/app/media/shows/${item.id}`;
    case 'TelevisionSeason':
      return `/app/media/seasons/${item.id}`;
    case 'Artist':
      return `/app/media/artists/${item.id}`;
    case 'Episode':
      return item.seasonId != null ? `/app/media/seasons/${item.seasonId}#episode-${item.id}` : null;
    default:
      return null;
  }
}

// Deterministic hue so the same title always gets the same placeholder gradient.
export function hueOf(value: string): number {
  let hue = 0;
  for (let index = 0; index < value.length; index += 1) {
    hue = (hue * 31 + value.charCodeAt(index)) % 360;
  }
  return hue;
}

export function parseDurationSeconds(value: string | null | undefined): number | null {
  if (!value) {
    return null;
  }

  const timeSpan = /^(?:(\d+)\.)?(\d{1,2}):(\d{2}):(\d{2})(?:\.\d+)?$/.exec(value);
  if (timeSpan) {
    const [, days, hours, minutes, seconds] = timeSpan;
    return (days ? Number(days) * 86400 : 0) + Number(hours) * 3600 + Number(minutes) * 60 + Number(seconds);
  }

  const iso = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/.exec(value);
  if (iso) {
    const [, days, hours, minutes, seconds] = iso;
    return (
      (days ? Number(days) * 86400 : 0) +
      (hours ? Number(hours) * 3600 : 0) +
      (minutes ? Number(minutes) * 60 : 0) +
      (seconds ? Number(seconds) : 0)
    );
  }

  return null;
}

export function formatDuration(totalSeconds: number): string {
  const totalMinutes = Math.round(totalSeconds / 60);
  const hours = Math.floor(totalMinutes / 60);
  const minutes = totalMinutes % 60;
  if (hours && minutes) {
    return `${hours}h ${String(minutes).padStart(2, '0')}m`;
  }
  if (hours) {
    return `${hours}h`;
  }
  return `${minutes}m`;
}

// The subtitle the API supplies (episode "Show - S1E2", song "Artist - Album", …) with a duration
// fallback so cards always have a useful second line.
export function itemSubtitle(item: LibraryBrowseItem): string {
  if (item.subtitle) {
    return item.subtitle;
  }
  const durationSeconds = parseDurationSeconds(item.duration);
  if (durationSeconds) {
    return formatDuration(durationSeconds);
  }
  if (item.itemCount) {
    return `${item.itemCount} item${item.itemCount === 1 ? '' : 's'}`;
  }
  return '';
}
