// =====================================================================
//  Art&Suites — Liste d'attente  ·  logique du formulaire (React)
// =====================================================================
//
//  WEBHOOK MAKE — module « Custom webhook » du scénario.
//  Le formulaire POSTe le payload JSON ci-dessous à cette adresse.
//
const WEBHOOK_URL = "https://hook.eu2.make.com/3ordu80g2n0dth071bhpkttkez6qqlkt";

// ---------------------------------------------------------------------
//  Suites
// ---------------------------------------------------------------------
const SUITES = [
  {
    id: "sarah",
    caption: { fr: "Belle Époque Narbonne", en: "Belle Époque Narbonne", es: "Belle Époque Narbonne" },
    name: "Sarah Bernhardt",
    meta: { fr: "80 m² · 1 à 6 pers.", en: "80 m² · 1–6 guests", es: "80 m² · 1 a 6 huésp." },
    price: 80,
    swatch: "linear-gradient(150deg, #E2B791 0%, #C99873 55%, #8C6240 100%)",
    image: "assets/suite-sarah.webp",
  },
  {
    id: "frida",
    caption: { fr: "Casa Azul Narbonne", en: "Casa Azul Narbonne", es: "Casa Azul Narbonne" },
    name: "Frida Kahlo",
    meta: { fr: "42 m² · 1 à 4 pers.", en: "42 m² · 1–4 guests", es: "42 m² · 1 a 4 huésp." },
    price: 75,
    swatch: "linear-gradient(150deg, #F5BFB4 0%, #F51549 60%, #8E0A29 100%)",
    image: "assets/suite-frida.webp",
  },
  {
    id: "boheme",
    caption: { fr: "Portanelle Millénaire Gaillac", en: "Portanelle Millénaire Gaillac", es: "Portanelle Millénaire Gaillac" },
    name: "La Bohème Saint Michel",
    meta: { fr: "75 m² · 1 à 5 pers.", en: "75 m² · 1–5 guests", es: "75 m² · 1 a 5 huésp." },
    price: 70,
    swatch: "linear-gradient(150deg, #FCF2E6 0%, #E2B791 65%, #886040 100%)",
    image: "assets/suite-boheme.webp",
  },
];

// ---------------------------------------------------------------------
//  i18n
// ---------------------------------------------------------------------
const T = {
  fr: {
    nav: "Les suites",
    eyebrow: "Liste d'attente",
    title: "Si une suite se libère, vous le saurez avant tout le monde !",
    lead: "Vos dates sont déjà complètes ?\nDès qu'une suite correspondant à vos attentes se libère, nous vous écrivons, souvent avant qu'elle ne reparaisse en ligne.",
    suiteQ: "La suite qui vous fait rêver",
    suiteHelp: "",
    perNight: "/ nuit",
    name: "Nom complet",
    namePh: "Camille Laurent",
    email: "Adresse e-mail",
    emailPh: "camille@exemple.fr",
    mobile: "Téléphone mobile",
    mobilePh: "06 12 34 56 78",
    mobileHelp: "Pour vous joindre vite si la suite se libère.",
    periodQ: "Période souhaitée",
    checkin: "Arrivée",
    checkout: "Départ",
    guests: "Nombre de personnes",
    guestUnit: ["personne", "personnes"],
    guestPlus: "6 personnes ou plus",
    rgpd: "J'accepte qu'Art\u0026Suites conserve mes coordonnées afin de me prévenir d'une disponibilité. Elles ne seront ni revendues, ni utilisées à d'autres fins.",
    submit: "Rejoindre la liste",
    sending: "Envoi…",
    reassure: "Sans engagement · Vous pouvez nous demander de vous retirer de la liste à tout moment.",
    errReq: "Ce champ est requis.",
    errEmail: "Cette adresse e-mail semble incomplète.",
    errSuite: "Choisissez une suite.",
    errConsent: "Merci de cocher cette case pour continuer.",
    errDates: "Le départ doit être après l'arrivée.",
  },
  en: {
    nav: "The suites",
    eyebrow: "Waitlist",
    title: "When a suite opens up, you'll be the first to know.",
    lead: "Are your dates already booked? Leave us a few words. The moment a suite matching your stay frees up, we write to you — often before it reappears online.",
    suiteQ: "The suite you're dreaming of",
    suiteHelp: "",
    perNight: "/ night",
    name: "Full name",
    namePh: "Camille Laurent",
    email: "Email address",
    emailPh: "camille@example.com",
    mobile: "Mobile phone",
    mobilePh: "+33 6 12 34 56 78",
    mobileHelp: "So we can reach you quickly if it opens up.",
    periodQ: "Preferred dates",
    checkin: "Check-in",
    checkout: "Check-out",
    guests: "Number of guests",
    guestUnit: ["guest", "guests"],
    guestPlus: "6 guests or more",
    rgpd: "I agree that Art\u0026Suites may keep my details to notify me of availability. They will never be sold or used for any other purpose.",
    submit: "Join the list",
    sending: "Sending…",
    reassure: "No commitment · You can ask to be removed from the list at any time.",
    errReq: "This field is required.",
    errEmail: "This email address looks incomplete.",
    errSuite: "Please choose a suite.",
    errConsent: "Please tick this box to continue.",
    errDates: "Check-out must be after check-in.",
  },
  es: {
    nav: "Las suites",
    eyebrow: "Lista de espera",
    title: "Cuando una suite se libere, será el primero en saberlo.",
    lead: "¿Sus fechas ya están completas? Déjenos unas palabras. En cuanto se libere una suite para su estancia, le escribimos — a menudo antes de que vuelva a aparecer en línea.",
    suiteQ: "La suite que le seduce",
    suiteHelp: "",
    perNight: "/ noche",
    name: "Nombre completo",
    namePh: "Camille Laurent",
    email: "Correo electrónico",
    emailPh: "camille@ejemplo.com",
    mobile: "Teléfono móvil",
    mobilePh: "+34 612 34 56 78",
    mobileHelp: "Para localizarle rápido si se libera.",
    periodQ: "Fechas deseadas",
    checkin: "Llegada",
    checkout: "Salida",
    guests: "Número de personas",
    guestUnit: ["persona", "personas"],
    guestPlus: "6 personas o más",
    rgpd: "Acepto que Art\u0026Suites conserve mis datos para avisarme de la disponibilidad. No serán vendidos ni usados para otros fines.",
    submit: "Unirse a la lista",
    sending: "Enviando…",
    reassure: "Sin compromiso · Puede pedir que le retiremos de la lista en cualquier momento.",
    errReq: "Este campo es obligatorio.",
    errEmail: "Este correo parece incompleto.",
    errSuite: "Elija una suite.",
    errConsent: "Marque esta casilla para continuar.",
    errDates: "La salida debe ser posterior a la llegada.",
  },
};

const LANGS = [["fr", "FR"], ["en", "EN"], ["es", "ES"]];

// ---------------------------------------------------------------------
//  Small pieces
// ---------------------------------------------------------------------
function CheckIcon({ stroke }) {
  return (
    <svg viewBox="0 0 24 24" width="15" height="15" fill="none"
         stroke={stroke || "currentColor"} strokeWidth="2.4"
         strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M4 12.5l5 5L20 6" />
    </svg>
  );
}

function Field({ label, help, error, children, htmlFor }) {
  return (
    <div className="wl-field">
      <label className="label" htmlFor={htmlFor}>{label}</label>
      {children}
      {help && !error && <span className="wl-help">{help}</span>}
      {error && <span className="wl-error">{error}</span>}
    </div>
  );
}

function SuiteTile({ suite, lang, selected, highlight, layout, onSelect }) {
  return (
    <button
      type="button"
      role="radio"
      aria-checked={selected}
      className={"wl-suite" + (selected ? " is-selected" : "") + (layout === "list" ? " is-list" : "")}
      style={selected ? { borderColor: highlight, boxShadow: `0 0 0 1.5px ${highlight}` } : undefined}
      onClick={() => onSelect(suite.id)}
    >
      <span className="wl-suite__media"
            style={suite.image
              ? { backgroundImage: `url("${suite.image}")`, backgroundSize: "cover", backgroundPosition: "center" }
              : { background: suite.swatch }}
            aria-hidden="true"></span>
      <span className="wl-suite__body">
        <span className="caption">{suite.caption[lang]}</span>
        <span className="wl-suite__name">{suite.name}</span>
        <span className="wl-suite__meta">{suite.meta[lang]}</span>
        <span className="wl-suite__foot">
          <span className="wl-radio" style={selected ? { borderColor: highlight } : undefined}>
            {selected && <span className="wl-radio__dot" style={{ background: highlight }}></span>}
          </span>
        </span>
      </span>
    </button>
  );
}

// ---------------------------------------------------------------------
//  App
// ---------------------------------------------------------------------
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "lang": "fr",
  "presentation": "card",
  "suiteLayout": "list",
  "highlight": "#449BAA"
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const lang = T[t.lang] ? t.lang : "fr";
  const tr = T[lang];

  const [form, setForm] = React.useState({
    suite: "", name: "", email: "", mobile: "",
    checkin: "", checkout: "", guests: "2", consent: false,
  });
  const [errors, setErrors] = React.useState({});
  const [sending, setSending] = React.useState(false);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  function validate() {
    const e = {};
    if (!form.suite) e.suite = tr.errSuite;
    if (!form.name.trim()) e.name = tr.errReq;
    if (!form.email.trim()) e.email = tr.errReq;
    else if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(form.email)) e.email = tr.errEmail;
    if (!form.mobile.trim()) e.mobile = tr.errReq;
    if (!form.checkin) e.checkin = tr.errReq;
    if (!form.checkout) e.checkout = tr.errReq;
    if (form.checkin && form.checkout && form.checkout <= form.checkin) e.checkout = tr.errDates;
    if (!form.consent) e.consent = tr.errConsent;
    setErrors(e);
    return Object.keys(e).length === 0;
  }

  async function submit(ev) {
    ev.preventDefault();
    if (!validate()) return;
    const suiteObj = SUITES.find(s => s.id === form.suite);
    const payload = {
      source: "waitlist-art-and-suites",
      submitted_at: new Date().toISOString(),
      language: lang,
      suite_id: form.suite,
      suite_name: suiteObj ? suiteObj.name : "",
      full_name: form.name.trim(),
      email: form.email.trim(),
      mobile: form.mobile.trim(),
      check_in: form.checkin,
      check_out: form.checkout,
      guests: Number(form.guests),
      consent: form.consent,
    };

    setSending(true);
    // Envoi vers Make. On tente d'abord un POST JSON classique ; si le
    // navigateur bloque (CORS / preflight), on bascule en requête « simple »
    // (no-cors, text/plain) que Make accepte et parse comme du JSON. Dans
    // tous les cas on route ensuite le client vers la page de remerciement.
    const sendOnce = (opts) => fetch(WEBHOOK_URL, {
      method: "POST",
      body: JSON.stringify(payload),
      keepalive: true,
      ...opts,
    });
    try {
      await sendOnce({ headers: { "Content-Type": "application/json" }, mode: "cors" });
    } catch (err) {
      console.warn("[waitlist] POST cors bloqué, repli no-cors :", err);
      try {
        await sendOnce({ headers: { "Content-Type": "text/plain;charset=UTF-8" }, mode: "no-cors" });
      } catch (err2) {
        console.warn("[waitlist] webhook non joignable :", err2);
      }
    }
    console.log("[waitlist] payload envoyé à Make :", payload);

    const q = new URLSearchParams({
      lang,
      name: form.name.trim().split(" ")[0] || form.name.trim(),
      suite: suiteObj ? suiteObj.name : "",
    });
    window.location.href = "Merci.html?" + q.toString();
  }

  const guestOpts = [];
  for (let i = 1; i <= 5; i++) {
    guestOpts.push(<option key={i} value={String(i)}>{i} {tr.guestUnit[i === 1 ? 0 : 1]}</option>);
  }
  guestOpts.push(<option key="6" value="6">{tr.guestPlus}</option>);

  return (
    <div className={"wl-root pres-" + t.presentation}>
      {/* header */}
      <header className="wl-header">
        <div className="wl-header__inner">
          <a className="wordmark wl-logo" href="#" aria-label="Art&Suites">
            ART<em style={{ color: "rgb(51, 22, 73)", fontFamily: "-apple-system" }}>&nbsp;&amp;&nbsp;</em>SUITES
          </a>
          <div className="wl-lang" role="group" aria-label="Langue">
            {LANGS.map(([code, lbl]) => (
              <button key={code}
                className={"wl-lang__btn" + (code === lang ? " is-active" : "")}
                onClick={() => setTweak("lang", code)}>{lbl}</button>
            ))}
          </div>
        </div>
      </header>

      {/* intro */}
      <section className="wl-intro">
        <span className="caption">{tr.eyebrow}</span>
        <h1>{tr.title}</h1>
      </section>

      {/* form */}
      <form className="wl-card" onSubmit={submit} noValidate>
        {/* suites */}
        <div className="wl-suitegroup" role="radiogroup" aria-label={tr.suiteQ}>
          <div className="wl-grouphead">
            <span className="label">{tr.suiteQ}</span>
            {tr.suiteHelp && <span className="wl-help">{tr.suiteHelp}</span>}
          </div>
          <div className={"wl-suites" + (t.suiteLayout === "list" ? " is-list" : "")}>
            {SUITES.map(s => (
              <SuiteTile key={s.id} suite={s} lang={lang}
                selected={form.suite === s.id}
                highlight={t.highlight} layout={t.suiteLayout}
                onSelect={(id) => { set("suite", id); setErrors(e => ({ ...e, suite: undefined })); }} />
            ))}
          </div>
          {errors.suite && <span className="wl-error">{errors.suite}</span>}
        </div>

        <hr className="wl-rule" />

        {/* identity */}
        <Field label={tr.name} error={errors.name} htmlFor="wl-name">
          <input id="wl-name" className="input" value={form.name} placeholder={tr.namePh}
                 onChange={e => set("name", e.target.value)} autoComplete="name" />
        </Field>

        <div className="wl-row2">
          <Field label={tr.email} error={errors.email} htmlFor="wl-email">
            <input id="wl-email" className="input" type="email" value={form.email} placeholder={tr.emailPh}
                   onChange={e => set("email", e.target.value)} autoComplete="email" />
          </Field>
          <Field label={tr.mobile} help={tr.mobileHelp} error={errors.mobile} htmlFor="wl-mobile">
            <input id="wl-mobile" className="input" type="tel" value={form.mobile} placeholder={tr.mobilePh}
                   onChange={e => set("mobile", e.target.value)} autoComplete="tel" />
          </Field>
        </div>

        {/* period */}
        <div className="wl-grouphead"><span className="label">{tr.periodQ}</span></div>
        <div className="wl-row2">
          <Field label={tr.checkin} error={errors.checkin} htmlFor="wl-in">
            <input id="wl-in" className="input" type="date" value={form.checkin}
                   onChange={e => set("checkin", e.target.value)} />
          </Field>
          <Field label={tr.checkout} error={errors.checkout} htmlFor="wl-out">
            <input id="wl-out" className="input" type="date" value={form.checkout}
                   onChange={e => set("checkout", e.target.value)} />
          </Field>
        </div>

        <div className="wl-row-guests">
          <Field label={tr.guests} htmlFor="wl-guests">
            <select id="wl-guests" className="select" value={form.guests}
                    onChange={e => set("guests", e.target.value)}>
              {guestOpts}
            </select>
          </Field>
        </div>

        <hr className="wl-rule" />

        {/* consent */}
        <label className={"wl-consent" + (errors.consent ? " has-error" : "")}>
          <span className={"wl-check" + (form.consent ? " is-on" : "")}>
            {form.consent && <CheckIcon stroke="#FCF2E6" />}
          </span>
          <input type="checkbox" checked={form.consent} className="wl-sr"
                 onChange={e => { set("consent", e.target.checked); setErrors(er => ({ ...er, consent: undefined })); }} />
          <span className="wl-consent__txt">{tr.rgpd}</span>
        </label>
        {errors.consent && <span className="wl-error" style={{ marginTop: 4 }}>{errors.consent}</span>}

        <button type="submit" className="btn btn--primary btn--block wl-submit" disabled={sending}>
          {sending ? tr.sending : tr.submit}
        </button>
        <p className="wl-reassure">{tr.reassure}</p>
      </form>

      <footer className="wl-foot">
        <span className="wordmark">ART<em>&amp;</em>SUITES</span>
        <span>© 2026 BMG — Une maison, pas un hôtel.</span>
      </footer>

      <TweaksPanel>
        <TweakSection label="Langue" />
        <TweakRadio label="Par défaut" value={t.lang} options={["fr", "en", "es"]}
                    onChange={v => setTweak("lang", v)} />
        <TweakSection label="Présentation" />
        <TweakRadio label="Formulaire" value={t.presentation} options={["card", "paper"]}
                    onChange={v => setTweak("presentation", v)} />
        <TweakRadio label="Suites" value={t.suiteLayout} options={["grid", "list"]}
                    onChange={v => setTweak("suiteLayout", v)} />
        <TweakColor label="Surbrillance" value={t.highlight}
                    options={["#449BAA", "#331649", "#C99873"]}
                    onChange={v => setTweak("highlight", v)} />
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
