export type SpotifyResourceType = 'album' | 'artist' | 'episode' | 'playlist' | 'show' | 'track';
export type SoundcloudResourceType = 'playlist' | 'track';

export interface SpotifyResource {
  type: SpotifyResourceType;
  id: string;
}

export interface SoundcloudResource {
  canonicalUrl: string;
  type: SoundcloudResourceType;
}

const SPOTIFY_RESOURCE_TYPES = new Set<SpotifyResourceType>([
  'album',
  'artist',
  'episode',
  'playlist',
  'show',
  'track'
]);
const SPOTIFY_URI_PATTERN = /^spotify:(album|artist|episode|playlist|show|track):([a-zA-Z0-9]+)$/i;
const SOUNDCLOUD_HOST_PATTERN = /^(?:www\.|m\.)?soundcloud\.com$/i;
const YOUTUBE_HOST_PATTERN = /^(?:www\.|m\.|music\.)?youtube\.com$/i;
const YOUTU_BE_HOST_PATTERN = /^(?:www\.)?youtu\.be$/i;
const YOUTUBE_VIDEO_ID_PATTERN = /^[\w-]{11}$/;

function parseUrl(url: string): URL | null {
  try {
    return new URL(url);
  } catch {
    return null;
  }
}

export function extractYoutubeVideoId(url: string): string | null {
  const parsedUrl = parseUrl(url);

  if (!parsedUrl) {
    return null;
  }

  if (YOUTU_BE_HOST_PATTERN.test(parsedUrl.hostname)) {
    const shortId = parsedUrl.pathname.split('/').filter(Boolean)[0] ?? '';

    return YOUTUBE_VIDEO_ID_PATTERN.test(shortId) ? shortId : null;
  }

  if (!YOUTUBE_HOST_PATTERN.test(parsedUrl.hostname)) {
    return null;
  }

  const pathSegments = parsedUrl.pathname.split('/').filter(Boolean);

  if (parsedUrl.pathname === '/watch') {
    const queryId = parsedUrl.searchParams.get('v') ?? '';

    return YOUTUBE_VIDEO_ID_PATTERN.test(queryId) ? queryId : null;
  }

  if (pathSegments.length >= 2 && (pathSegments[0] === 'embed' || pathSegments[0] === 'shorts')) {
    const pathId = pathSegments[1];

    return YOUTUBE_VIDEO_ID_PATTERN.test(pathId) ? pathId : null;
  }

  return null;
}

export function isYoutubeUrl(url?: string): boolean {
  return !!url && extractYoutubeVideoId(url) !== null;
}

export function extractSpotifyResource(url: string): SpotifyResource | null {
  const spotifyUriMatch = url.match(SPOTIFY_URI_PATTERN);

  if (spotifyUriMatch?.[1] && spotifyUriMatch[2]) {
    return {
      type: spotifyUriMatch[1].toLowerCase() as SpotifyResourceType,
      id: spotifyUriMatch[2]
    };
  }

  const parsedUrl = parseUrl(url);

  if (!parsedUrl || !/^(?:open|play)\.spotify\.com$/i.test(parsedUrl.hostname)) {
    return null;
  }

  const segments = parsedUrl.pathname.split('/').filter(Boolean);

  if (segments.length >= 2 && SPOTIFY_RESOURCE_TYPES.has(segments[0] as SpotifyResourceType)) {
    return {
      type: segments[0] as SpotifyResourceType,
      id: segments[1]
    };
  }

  if (segments.length >= 4 && segments[0] === 'user' && segments[2] === 'playlist') {
    return {
      type: 'playlist',
      id: segments[3]
    };
  }

  return null;
}

export function isSpotifyUrl(url?: string): boolean {
  return !!url && extractSpotifyResource(url) !== null;
}

export function extractSoundcloudResource(url: string): SoundcloudResource | null {
  const parsedUrl = parseUrl(url);

  if (!parsedUrl || !SOUNDCLOUD_HOST_PATTERN.test(parsedUrl.hostname)) {
    return null;
  }

  const segments = parsedUrl.pathname.split('/').filter(Boolean);

  if (segments.length === 2) {
    const canonicalUrl = new URL(`https://soundcloud.com/${segments[0]}/${segments[1]}`);

    return {
      canonicalUrl: canonicalUrl.toString(),
      type: 'track'
    };
  }

  if (segments.length === 3 && segments[1] === 'sets') {
    const canonicalUrl = new URL(`https://soundcloud.com/${segments[0]}/sets/${segments[2]}`);

    return {
      canonicalUrl: canonicalUrl.toString(),
      type: 'playlist'
    };
  }

  return null;
}

export function isSoundcloudUrl(url?: string): boolean {
  return !!url && extractSoundcloudResource(url) !== null;
}

export function hasDedicatedChatEmbed(url?: string): boolean {
  return isYoutubeUrl(url) || isSpotifyUrl(url) || isSoundcloudUrl(url);
}
