/**
 * T3 — v0.8 shared-`clientToken` password gate → signed cookie.
 *
 * The auth the base app never had (EXPLORE §5). Posts `clientToken` once over TLS to the relay
 * edge (P5/relay), which sets an `HttpOnly; Secure; SameSite` signed cookie; on `'ok'` the app
 * routes to the terminal view. Replaced by Passkey (T7) in v0.10 behind the same route.
 *
 * Security: the token is NEVER stored in `localStorage` and NEVER logged; all error text is set via
 * `textContent` (never `innerHTML`); empty input disables submit (fail-fast at the boundary).
 */
import type { RelayWebConfig } from './config'

export interface PasswordLogin {
  submit(clientToken: string): Promise<'ok' | 'rejected'>
}

export interface PasswordLoginDeps {
  readonly fetchImpl?: typeof fetch
  /** Invoked once on a successful login so the shell wrapper can route to the terminal view. */
  readonly onSuccess?: () => void
}

const LOGIN_PATH = '/api/login'

export function mountPasswordLogin(
  root: HTMLElement,
  cfg: RelayWebConfig,
  deps: PasswordLoginDeps = {},
): PasswordLogin {
  const fetchImpl = deps.fetchImpl ?? fetch

  const form = document.createElement('form')
  form.className = 'login-form'

  const input = document.createElement('input')
  input.type = 'password'
  input.autocomplete = 'current-password'
  input.placeholder = 'Access token'
  input.className = 'login-input'

  const button = document.createElement('button')
  button.type = 'submit'
  button.textContent = 'Connect'
  button.disabled = true // empty input → disabled (fail-fast)

  const error = document.createElement('p')
  error.className = 'login-error'
  error.setAttribute('role', 'alert')

  input.addEventListener('input', () => {
    button.disabled = input.value.length === 0
    error.textContent = '' // clear stale error on edit
  })

  async function submit(clientToken: string): Promise<'ok' | 'rejected'> {
    if (clientToken.length === 0) return 'rejected'
    let res: Response
    try {
      res = await fetchImpl(`${cfg.apiBase}${LOGIN_PATH}`, {
        method: 'POST',
        credentials: 'include', // relay sets the signed cookie on the response
        headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
        body: JSON.stringify({ clientToken }), // shared password, NOT an account_id (INV3)
      })
    } catch {
      error.textContent = 'Network error — please retry.'
      return 'rejected'
    }
    if (!res.ok) {
      error.textContent = 'Invalid access token.'
      return 'rejected'
    }
    error.textContent = ''
    if (deps.onSuccess) deps.onSuccess()
    return 'ok'
  }

  form.addEventListener('submit', (ev) => {
    ev.preventDefault()
    void submit(input.value)
  })

  form.append(input, button, error)
  root.append(form)

  return { submit }
}
