// Handle parsing for cross-protocol account lookup.
//
// Halflight is multi-protocol. A "handle" can appear as `@user`, `@user@host`,
// or a bare `user` / `user@host` (e.g. a search input). The two adapters need
// the same normalised representation so the resolution chain in
// `ProtocolAdapter.lookupAccount` doesn't repeat string slicing at every entry.
//
// `isLocalToActiveAccount` is the discriminant the adapter uses to choose
// between the cheap local-handle path and the more expensive search/webfinger
// fallback. Hosts compared case-insensitively; the `@` prefix and any
// whitespace get stripped before comparison.

export type AccountQueryHandle = {
  // Original input, kept for diagnostics and toast copy.
  raw: string
  // Username portion with no `@` prefix.
  localPart: string
  // Host portion, lowercased — null when the handle is bare (`@user`) or no
  // `@` separator is present.
  host: string | null
  // True when `host` is null OR matches the active account's instance host
  // (case-insensitive). Adapters use this to pick the cheap local-lookup
  // endpoint over the more expensive search path.
  isLocalToActiveAccount: boolean
  // Convenience: the canonical `user@host` form when host is known, else
  // just `user`. This is what gets fed into Mastodon's `acct=` query and
  // into search `q=`.
  acct: string
}

/**
 * Parse a user-typed or post-mention handle into a normalised representation.
 *
 * Accepts: `@user`, `@user@host`, `user`, `user@host`, optional leading/
 * trailing whitespace. Multiple leading `@` chars are stripped; the first
 * `@` after the localpart separates host. Anything past a second `@` (which
 * Mastodon would already have rejected as invalid) is treated as part of the
 * host string and the caller's lookup will simply 404.
 */
export function parseHandle(raw: string, activeInstance: string): AccountQueryHandle {
  const trimmed = (raw ?? '').trim().replace(/^@+/, '')
  const at = trimmed.indexOf('@')
  const localPart = at === -1 ? trimmed : trimmed.slice(0, at)
  const hostRaw = at === -1 ? null : trimmed.slice(at + 1).trim()
  const host = hostRaw && hostRaw.length > 0 ? hostRaw.toLowerCase() : null
  const isLocalToActiveAccount =
    host === null || host === (activeInstance ?? '').toLowerCase()
  const acct = host ? `${localPart}@${host}` : localPart
  return { raw, localPart, host, isLocalToActiveAccount, acct }
}

/**
 * Strip the leading `#` from a hashtag name and trim whitespace. The Mastodon
 * tag name validator is `/\A[[:word:]]+\z/` — a bare `#` in the path produces
 * 422. Pixelfed accepts the same shape. Centralising the normalisation here
 * means call sites can pass raw user input straight through and the adapter
 * guarantees the wire-level invariant.
 */
export function normaliseTagName(raw: string): string {
  return (raw ?? '').replace(/^#+/, '').trim()
}
