"use client";

import { ApiError } from "@/lib/api/browser";

import { Field, inputClass } from "./ui";

/**
 * Who is hosting an event — shared by the create form and the event editor (design D9, D10).
 *
 * One component rather than the same three inputs written twice, because the two forms have
 * to agree on more than markup: what counts as complete, what a blank second name means, and
 * which refusal belongs to which field. Two copies would drift the first time one of those
 * changed, and the drift would show up as a form that submits something the API rejects.
 *
 * The host is a *parent* of the couple, one or two of them — never the bride and groom. That
 * is why the labels say host rather than couple, and why there is no default drawn from the
 * wedding: nothing stored knows a parent's name.
 */
export interface HostValues {
  name1: string;
  name2: string;
  phone: string;
}

export const EMPTY_HOST: HostValues = { name1: "", name2: "", phone: "" };

/** Seed the form from an event the API returned. `name2` becomes "" because an input's value
 *  cannot be null; `hostPatch` turns it back into null on the way out. */
export function seedHost(event: {
  host_name_1: string;
  host_name_2: string | null;
  host_phone: string;
}): HostValues {
  return {
    name1: event.host_name_1,
    name2: event.host_name_2 ?? "",
    phone: event.host_phone,
  };
}

/** True while the required half is missing. Both forms disable their submit on this, so the
 *  admin is told before the round trip rather than by a 422 after it. */
export function isHostIncomplete(values: HostValues): boolean {
  return !values.name1.trim() || !values.phone.trim();
}

export function hostChanged(values: HostValues, seed: HostValues): boolean {
  return (
    values.name1 !== seed.name1 || values.name2 !== seed.name2 || values.phone !== seed.phone
  );
}

/** The wire shape. A blank second name is sent as null, matching the column: "" and null
 *  both meaning "no second host" is two spellings of one state (design D3). */
export function hostPatch(values: HostValues) {
  return {
    host_name_1: values.name1.trim(),
    host_name_2: values.name2.trim() || null,
    host_phone: values.phone.trim(),
  };
}

/**
 * Pull a field-level refusal out of whatever the save threw.
 *
 * The API answers a bad host phone with a coded refusal naming the field, so the message can
 * land under the input that caused it instead of in the form-wide error note where an admin
 * has to work out which of six fields it means.
 */
export function hostFieldError(error: unknown, field: "host_name_1" | "host_phone"): string | null {
  if (!(error instanceof ApiError)) return null;
  return error.context.field === field ? error.message : null;
}

export default function EventHostFields({
  values,
  canEdit,
  error,
  onChange,
}: {
  values: HostValues;
  canEdit: boolean;
  /** Whatever the last save threw, so a coded refusal can be routed to its field. */
  error?: unknown;
  onChange: (values: HostValues) => void;
}) {
  return (
    <div className="space-y-4">
      <div className="grid gap-4 sm:grid-cols-2">
        <Field label="Host name" error={hostFieldError(error, "host_name_1")}>
          <input
            value={values.name1}
            onChange={(e) => onChange({ ...values, name1: e.target.value })}
            disabled={!canEdit}
            required
            className={inputClass}
          />
        </Field>
        <Field label="Second host name" hint="Optional — leave empty for a single host">
          <input
            value={values.name2}
            onChange={(e) => onChange({ ...values, name2: e.target.value })}
            disabled={!canEdit}
            className={inputClass}
          />
        </Field>
      </div>

      <div className="grid gap-4 sm:grid-cols-2">
        <Field
          label="Host phone"
          hint="Shown on the invitation for guests to call"
          error={hostFieldError(error, "host_phone")}
        >
          <input
            type="tel"
            value={values.phone}
            onChange={(e) => onChange({ ...values, phone: e.target.value })}
            disabled={!canEdit}
            required
            className={inputClass}
          />
        </Field>
      </div>
    </div>
  );
}
