// The contact form — an ISLAND inside an otherwise-static page. The page is
// `interactive: 'islands'`, so only THIS component hydrates; the surrounding
// marketing copy stays inert HTML.
//
// `hydrate: 'visible'` defers hydration until the form scrolls into view —
// it's below the fold, so there's no reason to spend JS on it at first paint.
//
// i18n note: islands hydrate INDEPENDENTLY of the layout's URL <I18nProvider>,
// so this component must NOT import @voltro/i18n (`<T>`/useT would crash / show
// raw keys at hydration). Instead the PAGE resolves every UI string per-locale
// (inside the provider) and passes them in as `labels` — the framework
// serialises those props into the island's HTML, so it hydrates already
// translated. Dynamic runtime data (the server's error detail) stays as-is.
//
// On submit it POSTs JSON to the serverless function (CONTACT_ENDPOINT). The
// function lives on a different origin, but the framework's node runner +
// the edge hosts both send CORS headers, so the cross-origin call works.

import type { FormEvent, ReactNode } from 'react'
import { useState } from 'react'
import { island } from '@voltro/web'
import { CONTACT_ENDPOINT } from '../config'

// Every user-facing string the island shows, resolved per-locale by the page.
export interface ContactFormLabels {
  readonly name: string
  readonly email: string
  readonly message: string
  readonly send: string
  readonly sending: string
  readonly sentNotice: string
  readonly errorPrefix: string
  readonly networkError: string
}

// Object-literal type (not an interface) so it satisfies the island()
// generic's `Record<string, unknown>` constraint.
type ContactFormProps = { readonly labels: ContactFormLabels }

type Status =
  | { readonly kind: 'idle' }
  | { readonly kind: 'sending' }
  | { readonly kind: 'sent' }
  | { readonly kind: 'error'; readonly message: string }

function ContactForm({ labels }: ContactFormProps): ReactNode {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  const [message, setMessage] = useState('')
  const [status, setStatus] = useState<Status>({ kind: 'idle' })

  const onSubmit = async (e: FormEvent): Promise<void> => {
    e.preventDefault()
    setStatus({ kind: 'sending' })
    try {
      const res = await fetch(CONTACT_ENDPOINT, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ name, email, message }),
      })
      const body = (await res.json().catch(() => ({}))) as { error?: string; detail?: string }
      if (!res.ok) {
        setStatus({ kind: 'error', message: body.detail ?? body.error ?? `HTTP ${res.status}` })
        return
      }
      setStatus({ kind: 'sent' })
      setName('')
      setEmail('')
      setMessage('')
    } catch (err) {
      setStatus({ kind: 'error', message: err instanceof Error ? err.message : labels.networkError })
    }
  }

  if (status.kind === 'sent') {
    return <p className="notice ok">{labels.sentNotice}</p>
  }

  const sending = status.kind === 'sending'
  return (
    <form onSubmit={onSubmit} className="contact-form">
      <label htmlFor="name">{labels.name}</label>
      <input id="name" required value={name} onChange={(e) => setName(e.target.value)} />

      <label htmlFor="email">{labels.email}</label>
      <input id="email" type="email" required value={email} onChange={(e) => setEmail(e.target.value)} />

      <label htmlFor="message">{labels.message}</label>
      <textarea id="message" required rows={5} value={message} onChange={(e) => setMessage(e.target.value)} />

      {status.kind === 'error' && (
        <p className="notice err">
          {labels.errorPrefix} {status.message}
        </p>
      )}

      <button type="submit" disabled={sending}>
        {sending ? labels.sending : labels.send}
      </button>
    </form>
  )
}

export default island(ContactForm, { name: 'ContactForm', hydrate: 'visible' })
