/* global React, Icon, Button, Textarea, TurnstileWidget, formErrorMessage */
// ReviewPage — /avis?t=<token>
// Formulaire d'avis produits envoyé par email après une commande (voir
// functions/api/commande.js). Le token est l'identifiant de la commande :
// seuls les produits réellement commandés peuvent être notés.

const REVIEW_TURNSTILE_SITE_KEY = "0x4AAAAAAEbyFraFe3-4y-QN";

function StarRating({ value, onChange }) {
  const [hover, setHover] = React.useState(0);
  return (
    <div className="flex items-center gap-1" role="radiogroup" aria-label="Note">
      {[1, 2, 3, 4, 5].map((n) => (
        <button
          key={n}
          type="button"
          role="radio"
          aria-checked={value === n}
          aria-label={n + " étoile" + (n > 1 ? "s" : "")}
          onClick={() => onChange(n)}
          onMouseEnter={() => setHover(n)}
          onMouseLeave={() => setHover(0)}
          className="p-0.5">
          <Icon
            name="star"
            size={28}
            className={(hover || value) >= n ? "text-primary" : "text-line"}
          />
        </button>
      ))}
    </div>
  );
}

function ReviewPage({ onNav, params }) {
  const token = (params && params.t) || "";
  const [state, setState] = React.useState("loading"); // loading | invalid | already | form | sent
  const [clientPrenom, setClientPrenom] = React.useState("");
  const [lignes, setLignes] = React.useState([]);
  const [notes, setNotes] = React.useState({});
  const [turnstileToken, setTurnstileToken] = React.useState("");
  const [turnstileKey, setTurnstileKey] = React.useState(0);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    if (!token) {
      setState("invalid");
      return;
    }
    fetch("/api/avis?t=" + encodeURIComponent(token), { headers: { Accept: "application/json" } }).
    then((r) => (r.ok ? r.json() : Promise.reject())).
    then((data) => {
      if (data.configured === false || !data.lignes || data.lignes.length === 0) {
        setState("invalid");
        return;
      }
      setClientPrenom(data.clientPrenom || "");
      setLignes(data.lignes);
      setNotes(Object.fromEntries(data.lignes.map((l) => [l.id, { rating: 0, comment: "" }])));
      setState(data.alreadySubmitted ? "already" : "form");
    }).
    catch(() => setState("invalid"));
  }, [token]);

  const setRating = (id, rating) => setNotes((n) => ({ ...n, [id]: { ...n[id], rating } }));
  const setComment = (id, comment) => setNotes((n) => ({ ...n, [id]: { ...n[id], comment } }));

  const allRated = lignes.length > 0 && lignes.every((l) => notes[l.id] && notes[l.id].rating > 0);

  const submit = (e) => {
    e.preventDefault();
    if (!allRated || !turnstileToken || submitting) return;
    setSubmitting(true);
    setError("");
    fetch("/api/avis", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        token,
        avis: lignes.map((l) => ({ id: l.id, rating: notes[l.id].rating, comment: notes[l.id].comment })),
        turnstileToken,
      }),
    }).
    then(async (r) => {
      if (!r.ok) {
        const body = await r.json().catch(() => ({}));
        throw new Error(formErrorMessage(body.error));
      }
    }).
    then(() => setState("sent")).
    catch((err) => {
      setTurnstileToken("");
      setTurnstileKey((k) => k + 1);
      setError((err && err.message) || "Une erreur est survenue, réessayez dans un instant.");
    }).
    finally(() => setSubmitting(false));
  };

  if (state === "loading") {
    return (
      <section className="py-24 md:py-32 bg-foam min-h-[60vh]">
        <div className="container-x max-w-[560px] text-center text-mute">Chargement…</div>
      </section>);
  }

  if (state === "invalid") {
    return (
      <section className="py-24 md:py-32 bg-foam min-h-[60vh] flex items-center">
        <div className="container-x max-w-[520px] mx-auto text-center">
          <h1 className="h-display">Lien invalide</h1>
          <p className="lead mt-4 text-mute">Ce lien d'avis n'est pas valide ou a expiré. Si vous pensez qu'il s'agit d'une erreur, contactez-nous.</p>
          <Button variant="primary" className="mt-6" onClick={() => onNav("contact")}>Nous contacter</Button>
        </div>
      </section>);
  }

  if (state === "already") {
    return (
      <section className="py-24 md:py-32 bg-foam min-h-[60vh] flex items-center">
        <div className="container-x max-w-[520px] mx-auto text-center">
          <div className="w-16 h-16 rounded-full bg-success text-white grid place-items-center mx-auto mb-6"><Icon name="check" size={28} /></div>
          <h1 className="h-display">Merci !</h1>
          <p className="lead mt-4 text-mute">Vous avez déjà donné votre avis pour cette commande.</p>
          <Button variant="primary" className="mt-6" onClick={() => onNav("home")}>Retour à l'accueil</Button>
        </div>
      </section>);
  }

  if (state === "sent") {
    return (
      <section className="py-24 md:py-32 bg-foam min-h-[60vh] flex items-center">
        <div className="container-x max-w-[520px] mx-auto text-center">
          <div className="w-16 h-16 rounded-full bg-success text-white grid place-items-center mx-auto mb-6"><Icon name="check" size={28} /></div>
          <h1 className="h-display">Merci pour votre avis !</h1>
          <p className="lead mt-4 text-mute">Il sera visible sur le site après relecture par notre équipe.</p>
          <Button variant="primary" className="mt-6" onClick={() => onNav("home")}>Retour à l'accueil</Button>
        </div>
      </section>);
  }

  return (
    <section className="py-16 md:py-24 bg-foam min-h-[60vh]">
      <div className="container-x max-w-[640px] mx-auto">
        <h1 className="h-display">{clientPrenom ? `Merci ${clientPrenom} !` : "Votre avis"}</h1>
        <p className="lead mt-4 text-mute">Notez les produits que vous avez commandés, votre avis aide les futurs clients et nous aide à nous améliorer.</p>

        <form onSubmit={submit} className="mt-8 space-y-5">
          {lignes.map((l) => (
            <div key={l.id} className="panel p-6">
              <h3 className="font-serif text-primary text-[19px] leading-tight">{l.produit}</h3>
              <div className="mt-3">
                <StarRating value={(notes[l.id] && notes[l.id].rating) || 0} onChange={(v) => setRating(l.id, v)} />
              </div>
              <Textarea
                className="mt-4"
                rows={3}
                placeholder="Un commentaire (facultatif)"
                value={(notes[l.id] && notes[l.id].comment) || ""}
                onChange={(e) => setComment(l.id, e.target.value)} />
            </div>
          ))}

          <div className="panel p-6">
            <p className="text-[13px] text-mute leading-snug">Si vous laissez un avis, votre note, votre commentaire éventuel et votre prénom pourront être affichés publiquement sur la fiche du produit concerné, après relecture par notre équipe. Votre nom, votre email et le reste de votre commande ne sont jamais publiés.</p>
            <div className="mt-4">
              <TurnstileWidget key={turnstileKey} siteKey={REVIEW_TURNSTILE_SITE_KEY} onToken={setTurnstileToken} />
            </div>
            {error &&
            <div className="mt-3 text-[13px] text-red-700 flex items-center gap-2">
                <Icon name="alert-triangle" size={14} />
                {error}
              </div>
            }
            <Button type="submit" variant="primary" size="lg" className="w-full mt-4" disabled={!allRated || !turnstileToken || submitting}>
              {submitting ? "Envoi en cours…" : "Envoyer mon avis"}
            </Button>
            {!allRated && <p className="text-[13px] text-mute mt-3 text-center">Donnez une note à chaque produit pour envoyer votre avis.</p>}
          </div>
        </form>
      </div>
    </section>);
}

window.ReviewPage = ReviewPage;
