/**
 * Pull the video id out of any YouTube watch / shorts / embed / live / youtu.be
 * URL. Returns null for non-YouTube URLs or anything unparseable, so callers can
 * cheaply ask "is there a YouTube id derivable from this link?". The single home
 * for this parse — thumbnails, duplicate detection, and the placeholder title all
 * use it (H2).
 */
export function youtubeId(url: string | undefined): string | null {
  if (!url) return null
  let u: URL
  try {
    u = new URL(url)
  } catch {
    return null
  }
  const host = u.hostname.replace(/^www\./i, '').toLowerCase()
  if (host === 'youtu.be') return u.pathname.slice(1).split('/')[0] || null
  if (host === 'youtube.com' || host.endsWith('.youtube.com')) {
    const v = u.searchParams.get('v')
    if (v) return v
    const m = u.pathname.match(/^\/(?:embed|shorts|v|live)\/([^/?#]+)/i)
    if (m?.[1]) return m[1]
  }
  return null
}

/** A quick heuristic for "this clipboard text is a link worth offering". */
export function looksLikeUrl(text: string): boolean {
  const t = text.trim()
  if (!/^https?:\/\//i.test(t)) return false
  try {
    new URL(t)
    return true
  } catch {
    return false
  }
}

/**
 * True for URLs that point at a single video rather than a channel/playlist. The
 * library's add-source field wants collections to sync, not one-off videos, so it
 * filters these out of its suggestions. Conservative on purpose: it only flags the
 * common YouTube single-video shapes (a `/watch?v=` or `youtu.be/<id>` with no
 * `list=` context), so a channel/playlist link — on YouTube or any other site — is
 * never wrongly rejected. A `list=` param means "add the playlist", so it's kept.
 */
export function looksLikeSingleVideo(text: string): boolean {
  let u: URL
  try {
    u = new URL(text.trim())
  } catch {
    return false
  }
  if (u.searchParams.has('list')) return false
  const host = u.hostname.replace(/^www\./, '').toLowerCase()
  if (host === 'youtube.com' || host === 'm.youtube.com' || host === 'music.youtube.com') {
    return u.pathname === '/watch' && u.searchParams.has('v')
  }
  if (host === 'youtu.be') {
    return /^\/[\w-]{6,}$/.test(u.pathname)
  }
  return false
}

/**
 * True for URLs that point at a whole channel or playlist rather than a single
 * video — the shapes that belong in the Library (index once, download in bulk),
 * not the one-off Downloads bar (UX3). Conservative on purpose: it only flags the
 * clear YouTube channel and dedicated-playlist shapes, so a plain `/watch?v=…`
 * video (even one carrying a `list=` context) is never flagged and keeps working
 * in the Downloads bar; a non-YouTube link is never flagged.
 */
export function looksLikeChannelOrPlaylist(text: string): boolean {
  let u: URL
  try {
    u = new URL(text.trim())
  } catch {
    return false
  }
  const host = u.hostname.replace(/^www\./, '').toLowerCase()
  const isYouTube =
    host === 'youtube.com' || host === 'm.youtube.com' || host === 'music.youtube.com'
  if (!isYouTube) return false
  // A dedicated playlist page (not a /watch video that merely carries a list).
  if (u.pathname === '/playlist' && u.searchParams.has('list')) return true
  // Channel shapes: /channel/UC…, /c/Name, /user/Name, /@handle — with an optional
  // /videos, /streams, /shorts, /playlists tab suffix.
  if (/^\/(channel|c|user)\/[^/]+/i.test(u.pathname)) return true
  if (/^\/@[^/]+/.test(u.pathname)) return true
  return false
}

/**
 * Return the first http(s) URL from a multi-line blob of text.
 * Lines are trimmed; '#' comment lines are skipped.
 * Used for clipboard paste and drag-drop text.
 */
export function firstUrlInText(text: string): string | null {
  for (const raw of text.split(/\r?\n/)) {
    const line = raw.trim()
    if (!line || line.startsWith('#')) continue
    if (looksLikeUrl(line)) return line
  }
  return null
}
