/**
 * T1 — runtime config derived from `location` (no host/IP knob exists in the client, so the
 * browser can never be pointed at another tenant's origin — supports INV1 upstream).
 *
 * The tenant origin is `<subdomain>.term.<domain>`. `wsUrl` is ALWAYS same-origin and
 * scheme-following (`wss:` on HTTPS, else `ws:`) — the M6 guarantee that avoids mixed-content
 * blocking on TLS/Tailscale deploys.
 */
import { ConfigError } from './errors'

/** The label that marks the tenant zone: `<subdomain>.term.<domain>`. */
const TENANT_ZONE_LABEL = 'term'

export interface RelayWebConfig {
  /** left-most hostname label, e.g. 'alice' in alice.term.example.com */
  readonly subdomain: string
  /** scheme-following, SAME-ORIGIN ws URL builder (M6); a path cannot inject a foreign host */
  readonly wsUrl: (path: string) => string
  /** same-origin API base ('' — every control-plane call is relative) */
  readonly apiBase: string
}

/** Parse the tenant subdomain from a hostname, or throw (fail-fast, never default to a tenant). */
function parseSubdomain(hostname: string): string {
  const labels = hostname.split('.')
  const first = labels[0]
  // Require the `<sub>.term.<...>` shape: a non-empty left label with `term` as the 2nd label.
  if (labels.length < 3 || labels[1] !== TENANT_ZONE_LABEL || first === undefined || first === '') {
    throw new ConfigError(
      `hostname '${hostname}' has no tenant subdomain (expected '<subdomain>.${TENANT_ZONE_LABEL}.<domain>')`,
    )
  }
  return first
}

/**
 * Derive the client runtime config from `location`. Throws {@link ConfigError} on a host that is
 * not a valid tenant subdomain — it never silently falls back to another tenant's subdomain.
 */
export function readConfig(loc: Pick<Location, 'protocol' | 'host' | 'hostname'>): RelayWebConfig {
  const subdomain = parseSubdomain(loc.hostname)
  const wsScheme = loc.protocol === 'https:' ? 'wss' : 'ws'
  const host = loc.host

  const wsUrl = (path: string): string => {
    // Always anchor to our own host; normalize to a leading '/' so a caller-supplied
    // `//evil.com` becomes a PATH on our host, never a protocol-relative foreign origin.
    const normalized = path.startsWith('/') ? path : `/${path}`
    return `${wsScheme}://${host}${normalized}`
  }

  return Object.freeze({ subdomain, wsUrl, apiBase: '' })
}
