/**
 * Contact form runtime: submits the form as JSON to zadex/v1/forms/basic and shows the result inline.
 * The recipient is resolved server side from the saved document (post id + element id).
 */
const bound = new WeakMap<HTMLElement, () => void>();

export interface FormBasicPayload {
  postId: number;
  elementId: string;
  name: string;
  email: string;
  message: string;
  website: string;
}

function setStatus(form: HTMLFormElement, state: 'idle' | 'sending' | 'success' | 'error', message = ''): void {
  form.classList.remove('zx-form-basic--idle', 'zx-form-basic--sending', 'zx-form-basic--success', 'zx-form-basic--error');
  form.classList.add(`zx-form-basic--${state}`);
  const status = form.querySelector<HTMLElement>('.zx-form-basic__status');
  if (status) status.textContent = message;
  const button = form.querySelector<HTMLButtonElement>('.zx-form-basic__button');
  if (button) button.disabled = state === 'sending';
}

export default function init(root: HTMLElement): () => void {
  bound.get(root)?.();
  if (!(root instanceof (root.ownerDocument.defaultView ?? window).HTMLFormElement) && root.tagName !== 'FORM') return () => {};
  const form = root as HTMLFormElement;

  const onSubmit = async (e: Event): Promise<void> => {
    e.preventDefault();
    const data = new FormData(form);
    const value = (k: string): string => String(data.get(k) ?? '').trim();
    const payload: FormBasicPayload = {
      postId: Number(form.dataset.zxPost ?? 0) || 0,
      elementId: form.dataset.zxId ?? '',
      name: value('name'),
      email: value('email'),
      message: value('message'),
      website: value('website'),
    };
    if (!payload.name || !payload.email || !payload.message || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(payload.email)) {
      setStatus(form, 'error', form.dataset.zxInvalid || 'Please fill in all fields with a valid email address.');
      return;
    }
    setStatus(form, 'sending', form.dataset.zxSending || '');
    const url = form.getAttribute('action') || form.action;
    try {
      const res = await fetch(url, {
        method: 'POST',
        credentials: 'same-origin',
        headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
        body: JSON.stringify(payload),
      });
      let json: { sent?: boolean; message?: string } | null = null;
      try {
        json = (await res.json()) as { sent?: boolean; message?: string };
      } catch {
        json = null;
      }
      if (res.ok && json?.sent) {
        setStatus(form, 'success', json.message || form.dataset.zxSuccess || 'Sent.');
        form.reset();
      } else {
        setStatus(form, 'error', json?.message || form.dataset.zxError || 'Something went wrong. Please try again.');
      }
    } catch {
      setStatus(form, 'error', form.dataset.zxError || 'Something went wrong. Please try again.');
    }
  };

  form.addEventListener('submit', onSubmit);
  const dispose = (): void => {
    form.removeEventListener('submit', onSubmit);
    bound.delete(root);
  };
  bound.set(root, dispose);
  return dispose;
}
