/**
 * Extract a YouTube `videoId` from a URL.
 *
 * Supports:
 *   - youtube.com/watch?v=ID
 *   - youtu.be/ID
 *   - youtube.com/shorts/ID
 *   - youtube.com/embed/ID
 *   - youtube.com/v/ID
 *   - m.youtube.com/* mirrors
 *
 * Returns `null` if the URL does not match.
 */
export function extractYouTubeId(input: string): string | null {
  let url: URL;
  try {
    url = new URL(input);
  } catch {
    return null;
  }

  const host = url.hostname.replace(/^www\.|^m\./, '');

  if (host === 'youtu.be') {
    const id = url.pathname.replace(/^\//, '').split('/')[0];
    return isValidId(id) ? id : null;
  }

  if (host === 'youtube.com' || host === 'youtube-nocookie.com') {
    if (url.pathname === '/watch') {
      const v = url.searchParams.get('v');
      return v && isValidId(v) ? v : null;
    }
    const m = url.pathname.match(/^\/(?:shorts|embed|v|live)\/([^/?#]+)/);
    if (m) {
      return isValidId(m[1]) ? m[1] : null;
    }
  }

  return null;
}

/** Parse the YouTube `?t=` / `&t=` start-time param (`90`, `90s`, `1m30s`). */
export function parseYouTubeStartTime(input: string | null): number | undefined {
  if (!input) return undefined;
  // Pure seconds.
  if (/^\d+s?$/.test(input)) {
    const n = parseInt(input, 10);
    return Number.isFinite(n) && n > 0 ? n : undefined;
  }
  // `1h2m3s` / `2m30s` / `45s`.
  const match = input.match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s?)?$/);
  if (!match) return undefined;
  const [, h, m, s] = match;
  const total =
    (h ? parseInt(h, 10) * 3600 : 0) +
    (m ? parseInt(m, 10) * 60 : 0) +
    (s ? parseInt(s, 10) : 0);
  return total > 0 ? total : undefined;
}

function isValidId(id: string | undefined): id is string {
  return !!id && /^[\w-]{6,}$/.test(id);
}
