/**
 * Разбор пользовательского ввода на экране подключения к конференции
 * (JoinPage, поле «Ссылка или номер») в значение, которое можно передать
 * backend'у как `q` в `GET /conferences/resolve?q=` — это либо slug конференции,
 * либо её номер (цифры, возможно с пробелами).
 *
 * Поддерживаемые форматы входной строки:
 * - голый slug: `oEjfD0s-XJg`;
 * - голый номер, в т.ч. с пробелами: `8842 104`;
 * - полная ссылка с любым origin и путём приглашения `/j/{slug}`:
 *   `https://vidconf.ru/j/oEjfD0s-XJg`, `vidconf.ru/j/oEjfD0s-XJg`;
 * - полная ссылка на саму комнату `/room/{slug}` (её видно в адресной строке
 *   уже во время звонка и её тоже логично уметь вставить обратно):
 *   `http://localhost:5173/room/aCFxP2REfhw`;
 * - с «хвостом» query/fragment после slug: `.../j/oEjfD0s-XJg?ref=email#x`.
 *
 * Тест-раннер (vitest/jest) в проекте не настроен (см. package.json) — вместо
 * юнит-тестов ниже приведены примеры поведения в комментариях; при появлении
 * тест-раннера их можно почти дословно перенести в `*.test.ts`.
 *
 * @example
 * parseJoinQuery('8842 104') // '8842 104' (номер с пробелом — как есть)
 * parseJoinQuery('oEjfD0s-XJg') // 'oEjfD0s-XJg' (голый slug — как есть)
 * parseJoinQuery('vidconf.ru/j/oEjfD0s-XJg') // 'oEjfD0s-XJg'
 * parseJoinQuery('https://vidconf.ru/j/oEjfD0s-XJg?ref=email') // 'oEjfD0s-XJg'
 * parseJoinQuery('http://localhost:5173/room/aCFxP2REfhw') // 'aCFxP2REfhw'
 * parseJoinQuery('  https://vidconf.ru/j/x-y#section ') // 'x-y'
 */

/** Путь приглашения (`/j/`) или прямая ссылка на комнату (`/room/`) — оба ведут к одному и тому же slug. */
const JOIN_PATH_SEGMENT = /\/(?:j|room)\/([^/?#]+)/i

/** Похоже на домен (`vidconf.ru/...`) без явной схемы `http(s)://`. */
const BARE_DOMAIN_LIKE = /^[\w-]+(?:\.[a-z]{2,})+(?::\d+)?(\/|$)/i

/** Явная схема URL (`http://`, `https://`, в теории и другие). */
const URL_SCHEME = /^[a-z][a-z0-9+.-]*:\/\//i

function safeDecode(value: string): string {
  try {
    return decodeURIComponent(value)
  } catch {
    return value
  }
}

/** Отрезает query (`?...`) и fragment (`#...`) от конца строки, если они есть. */
function stripQueryAndFragment(value: string): string {
  const idx = value.search(/[?#]/)
  return idx === -1 ? value : value.slice(0, idx)
}

/**
 * Извлекает slug или номер конференции из произвольного пользовательского
 * ввода (ссылка любого вида или номер). Если распознать путь `/j/`/`/room/`
 * не удалось — возвращает исходную строку без схемы/домена (если они были)
 * либо как есть, чтобы `resolveConference` сам решил, валидна она или нет
 * (публичный эндпоинт и так отвечает единообразным 404, не палит различие
 * между «неверный формат» и «не найдено»).
 */
export function parseJoinQuery(raw: string): string {
  const trimmed = raw.trim()
  if (!trimmed) return ''

  const segmentMatch = trimmed.match(JOIN_PATH_SEGMENT)
  if (segmentMatch) {
    return safeDecode(segmentMatch[1])
  }

  const looksLikeUrl = URL_SCHEME.test(trimmed) || BARE_DOMAIN_LIKE.test(trimmed)
  if (looksLikeUrl) {
    const withoutScheme = trimmed.replace(URL_SCHEME, '')
    const slashIndex = withoutScheme.indexOf('/')
    if (slashIndex !== -1) {
      const rest = stripQueryAndFragment(withoutScheme.slice(slashIndex + 1))
      if (rest) return safeDecode(rest)
    }
  }

  return stripQueryAndFragment(trimmed).trim() || trimmed
}
