/* Quote list + quote form + short contact form */

const DIAL = [
  { c: "TR", d: "+90" }, { c: "BG", d: "+359" }, { c: "GR", d: "+30" }, { c: "other", d: "+" }
];
const emailOk = v => /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v.trim());
const phoneOk = v => v.replace(/[^\d]/g, "").length >= 7;

function DemoSim({ value, onChange }) {
  const { t } = useApp();
  return (
    <div className="demo-sim">
      <span>{t("demo.sim")}:</span>
      <div className="seg" role="radiogroup" aria-label={t("demo.sim")}>
        {["ok", "fail"].map(v => (
          <label key={v}><input type="radio" name="sim" checked={value === v} onChange={() => onChange(v)} />{t("demo." + v)}</label>
        ))}
      </div>
    </div>
  );
}

function Field({ id, label, optional, error, hint, children, full }) {
  const { t } = useApp();
  return (
    <div className={"field" + (error ? " invalid" : "") + (full ? " full" : "")}>
      <label htmlFor={id}>{label} {optional && <span className="opt">({t("fm.optional")})</span>}</label>
      {children}
      {hint && !error && <span className="hint" id={id + "-hint"}>{hint}</span>}
      {error && <span className="ferr" id={id + "-err"} role="alert">{Ico.info(16)} {error}</span>}
    </div>
  );
}

function PrivacyLine() {
  const { t, route } = useApp();
  const parts = t("fm.privacy").split("{link}");
  return <p className="hint">{parts[0]}<a href={hrefFor(route.lang, "privacy")}>{t("fm.privacy.link")}</a>{parts[1]}</p>;
}

function QuoteForm() {
  const { t, route, quote } = useApp();
  const defCountry = { tr: "TR", bg: "BG", el: "GR", en: "TR" }[route.lang];
  const [f, setF] = useState({
    name: "", dial: DIAL.find(d => d.c === defCountry).d, phone: "", email: "", country: defCountry, city: "",
    clang: route.lang, type: "ind", amount: "", desc: "", marketing: false
  });
  const [files, setFiles] = useState([]);
  const [more, setMore] = useState(false);
  const [errs, setErrs] = useState({});
  const [state, setState] = useState("idle"); // idle | sending | ok | fail
  const [sim, setSim] = useState("ok");
  const [summary, setSummary] = useState("");
  const topRef = useRef(null);
  const set = (k, v) => { setF(s => ({ ...s, [k]: v })); if (errs[k] || (k === "phone" || k === "email") && errs.contact) setErrs(e => ({ ...e, [k]: null, contact: null })); };

  const onCountry = v => { const d = DIAL.find(x => x.c === v); setF(s => ({ ...s, country: v, dial: d && v !== "other" ? d.d : s.dial })); };

  const validate = () => {
    const e = {};
    if (!f.name.trim() || f.name.trim().length < 2) e.name = t("err.name");
    if (!f.phone.trim() && !f.email.trim()) e.contact = t("err.contact");
    if (f.email.trim() && !emailOk(f.email)) e.email = t("err.email");
    if (f.phone.trim() && !phoneOk(f.phone)) e.phone = t("err.phone");
    return e;
  };

  const submit = ev => {
    ev.preventDefault();
    const e = validate();
    setErrs(e);
    if (Object.keys(e).length) {
      setTimeout(() => { const el = document.querySelector(".field.invalid input, .field.invalid textarea"); el && el.focus(); }, 0);
      return;
    }
    setState("sending");
    const items = quote.items.map(i => {
      const p = window.PRODUCTS.find(x => x.id === i.id);
      return `• ${p ? p.name + " (" + p.code + ")" : i.id}${i.qty ? " — " + i.qty + " " + t("q." + i.unit) : ""}${i.note ? " — " + i.note : ""}`;
    }).join("\n");
    setSummary([
      `${t("fm.name")}: ${f.name}`,
      f.phone && `${t("fm.phone")}: ${f.dial} ${f.phone}`,
      f.email && `${t("fm.email")}: ${f.email}`,
      `${t("fm.country")}: ${t("fm.c." + f.country)}${f.city ? " / " + f.city : ""}`,
      `${t("fm.lang")}: ${translate(f.clang, "meta.name")}`,
      `${t("fm.type")}: ${t("fm.t." + f.type)}`,
      f.amount && `${t("fm.amount")}: ${f.amount}`,
      f.desc && `${t("fm.desc")}: ${f.desc}`,
      files.length && `${t("fm.file")}: ${files.map(x => x.name).join(", ")}`,
      "",
      `${t("q.items")}:`,
      items || "— " + t("q.general")
    ].filter(x => x !== false && x !== undefined && x !== null && x !== 0).join("\n"));
    setTimeout(() => {
      setState(sim);
      topRef.current && topRef.current.focus();
    }, 1400);
  };

  if (state === "ok") {
    return (
      <div className="form-card result" ref={topRef} tabIndex={-1}>
        <div className="alert alert-ok">{Ico.check()}<div><b>{t("ok.title")}</b><br />{t("ok.text")}</div></div>
        <div><p className="tiny muted" style={{ marginBottom: 6, textTransform: "uppercase", letterSpacing: ".08em" }}>{t("ok.summary")}</p><pre>{summary}</pre></div>
        <div className="btn-row">
          <button className="btn btn-dark" onClick={() => { setState("idle"); }}>{t("ok.new")}</button>
          <a className="btn btn-line" href={hrefFor(route.lang, "products")}>{t("q.browse")}</a>
        </div>
      </div>
    );
  }

  const sending = state === "sending";
  const errCount = Object.values(errs).filter(Boolean).length;
  return (
    <form className="form-card" onSubmit={submit} noValidate aria-labelledby="fm-h" ref={topRef} tabIndex={-1}>
      <div className="alert alert-demo" style={{ marginBottom: 22 }}>{Ico.info()}<span>{t("demo.notice")}</span></div>
      {state === "fail" && (
        <div className="alert alert-err" role="alert" style={{ marginBottom: 18 }}>{Ico.info()}<div><b>{t("fail.title")}</b><br />{t("fail.text")}</div></div>
      )}
      {errCount > 0 && <div className="alert alert-err" role="alert" style={{ marginBottom: 18 }}>{Ico.info()}<span>{t("err.summary")}</span></div>}
      <h2 id="fm-h" className="h-3" style={{ marginBottom: 18 }}>{t("fm.title")}</h2>
      <div className="form-grid">
        <Field id="fm-name" label={t("fm.name")} error={errs.name} full>
          <input id="fm-name" className="input" autoComplete="name" value={f.name} onChange={e => set("name", e.target.value)} aria-invalid={!!errs.name} aria-describedby={errs.name ? "fm-name-err" : undefined} />
        </Field>
        <Field id="fm-phone" label={t("fm.phone")} error={errs.phone || (errs.contact && !f.phone ? errs.contact : null)}>
          <div className="tel">
            <select className="input" aria-label="Country code" value={f.dial} onChange={e => set("dial", e.target.value)}>
              {["+90", "+359", "+30", "+49", "+44", "+"].map(d => <option key={d} value={d}>{d === "+" ? "+ …" : d}</option>)}
            </select>
            <input id="fm-phone" className="input" type="tel" inputMode="tel" autoComplete="tel-national" value={f.phone} onChange={e => set("phone", e.target.value)} aria-invalid={!!(errs.phone || errs.contact)} aria-describedby="fm-either" />
          </div>
        </Field>
        <Field id="fm-email" label={t("fm.email")} error={errs.email || (errs.contact && !f.email ? errs.contact : null)}>
          <input id="fm-email" className="input" type="email" autoComplete="email" value={f.email} onChange={e => set("email", e.target.value)} aria-invalid={!!(errs.email || errs.contact)} aria-describedby="fm-either" />
        </Field>
        <p className="hint full" id="fm-either" style={{ marginTop: -8 }}>{t("fm.either")}</p>
        <Field id="fm-country" label={t("fm.country")}>
          <select id="fm-country" className="input" value={f.country} onChange={e => onCountry(e.target.value)}>
            {["TR", "BG", "GR", "other"].map(c => <option key={c} value={c}>{t("fm.c." + c)}</option>)}
          </select>
        </Field>
        <Field id="fm-city" label={t("fm.city")} optional>
          <input id="fm-city" className="input" autoComplete="address-level2" value={f.city} onChange={e => set("city", e.target.value)} />
        </Field>
        <Field id="fm-lang" label={t("fm.lang")} full>
          <div className="seg" role="radiogroup" aria-labelledby="fm-lang-l" id="fm-lang">
            {window.LANGS.map(l => (
              <label key={l} lang={l}><input type="radio" name="clang" checked={f.clang === l} onChange={() => set("clang", l)} />{translate(l, "meta.name")}</label>
            ))}
          </div>
        </Field>
        <Field id="fm-type" label={t("fm.type")} full>
          <div className="seg" role="radiogroup" id="fm-type">
            {["ind", "arch", "firm"].map(v => (
              <label key={v}><input type="radio" name="ctype" checked={f.type === v} onChange={() => set("type", v)} />{t("fm.t." + v)}</label>
            ))}
          </div>
        </Field>
        <Field id="fm-desc" label={t("fm.desc")} optional full>
          <textarea id="fm-desc" className="input" placeholder={t("fm.desc.ph")} value={f.desc} onChange={e => set("desc", e.target.value)} />
        </Field>

        <div className="full">
          <button type="button" className="more-toggle" aria-expanded={more} aria-controls="fm-more" onClick={() => setMore(m => !m)}>
            <span>{more ? t("fm.less") : t("fm.more")}</span>
            <span style={{ transform: more ? "rotate(45deg)" : "none", transition: "transform .2s", display: "grid" }}>{Ico.plus(16)}</span>
          </button>
        </div>
        {more && <>
          <Field id="fm-amount" label={t("fm.amount")} optional full>
            <input id="fm-amount" className="input" placeholder={t("fm.amount.ph")} value={f.amount} onChange={e => set("amount", e.target.value)} />
          </Field>
          <div className="field full" id="fm-more">
            <span className="lbl">{t("fm.file")} <span className="opt">({t("fm.optional")})</span></span>
            <div className="file-drop">
              <label className="btn btn-line btn-sm" style={{ cursor: "pointer" }}>
                {t("fm.file.btn")}
                <input type="file" multiple accept=".pdf,.jpg,.jpeg,.png" className="sr-only"
                  onChange={e => setFiles(Array.from(e.target.files).slice(0, 3))} />
              </label>
              <span className="hint">{t("fm.file.hint")}</span>
              {files.length > 0 && <div className="file-list">{files.map(x => <span key={x.name}>— {x.name}</span>)}</div>}
            </div>
          </div>
        </>}

        <div className="full" style={{ display: "grid", gap: 14, marginTop: 4 }}>
          <PrivacyLine />
          <label className="check">
            <input type="checkbox" checked={f.marketing} onChange={e => set("marketing", e.target.checked)} />
            <span>{t("fm.marketing")} <span className="muted">({t("fm.optional")})</span></span>
          </label>
          <button type="submit" className="btn btn-primary btn-block" disabled={sending} aria-busy={sending}>
            {sending ? <><span className="spinner" aria-hidden="true"></span>{t("fm.sending")}</> : (state === "fail" ? t("fail.retry") : t("fm.submit"))}
          </button>
          <DemoSim value={sim} onChange={setSim} />
        </div>
      </div>
    </form>
  );
}

function QuotePage() {
  const { t, route, quote, toast } = useApp();
  const rows = quote.items.map(i => ({ i, p: window.PRODUCTS.find(x => x.id === i.id) })).filter(r => r.p);
  return (
    <>
      <PageHead title={t("q.title")} lead={t("q.intro")} />
      <div className="wrap quote">
        <section aria-labelledby="qi-h">
          <h2 id="qi-h" className="h-3" style={{ marginBottom: 14, display: "flex", gap: 10, alignItems: "center" }}>
            {t("q.items")} <span className={"count" + (rows.length ? "" : " zero")}>{rows.length}</span>
          </h2>
          <div className="q-items">
            {rows.length === 0 && (
              <div className="q-empty">
                <p>{t("q.empty")}</p>
                <a className="btn btn-line btn-sm" href={hrefFor(route.lang, "products")}>{t("q.browse")} {Ico.arrow()}</a>
              </div>
            )}
            {rows.map(({ i, p }) => (
              <article key={p.id} className="q-item">
                <img src={p.img[0]} alt="" />
                <div>
                  <div className="q-head">
                    <div>
                      <span className="card-code">{p.code}</span>
                      <h3><a href={hrefFor(route.lang, "product", p.id)}>{p.name}</a></h3>
                      <p className="small muted">{p.size} cm · {t("v." + p.surface)}</p>
                    </div>
                    <button className="q-rm" onClick={() => { quote.remove(p.id); toast(t("toast.removed", { name: p.name })); }} aria-label={`${t("q.remove")}: ${p.name}`}>{t("q.remove")}</button>
                  </div>
                  <div className="q-row">
                    <div className="field">
                      <label className="tiny muted" htmlFor={"qty-" + p.id}>{t("q.qty")}</label>
                      <input id={"qty-" + p.id} className="input small" inputMode="decimal" value={i.qty} onChange={e => quote.update(p.id, { qty: e.target.value })} placeholder="0" />
                    </div>
                    <div className="field">
                      <label className="tiny muted" htmlFor={"unit-" + p.id}>{t("q.unit")}</label>
                      <select id={"unit-" + p.id} className="input small" value={i.unit} onChange={e => quote.update(p.id, { unit: e.target.value })}>
                        <option value="m2">{t("q.m2")}</option><option value="pcs">{t("q.pcs")}</option>
                      </select>
                    </div>
                    <div className="field note-f">
                      <label className="tiny muted" htmlFor={"note-" + p.id}>{t("q.note")}</label>
                      <input id={"note-" + p.id} className="input small" value={i.note} onChange={e => quote.update(p.id, { note: e.target.value })} placeholder={t("q.note.ph")} />
                    </div>
                  </div>
                </div>
              </article>
            ))}
          </div>
          <p className="small muted" style={{ marginTop: 18 }}>{t("price.note")}. {t("intl.terms")}</p>
        </section>
        <div className="q-side"><QuoteForm /></div>
      </div>
    </>
  );
}

function ContactForm() {
  const { t } = useApp();
  const [f, setF] = useState({ name: "", contact: "", msg: "" });
  const [errs, setErrs] = useState({});
  const [state, setState] = useState("idle");
  const [sim, setSim] = useState("ok");
  const submit = e => {
    e.preventDefault();
    const er = {};
    if (f.name.trim().length < 2) er.name = t("err.name");
    if (!f.contact.trim()) er.contact = t("err.contact");
    else if (f.contact.includes("@") ? !emailOk(f.contact) : !phoneOk(f.contact)) er.contact = f.contact.includes("@") ? t("err.email") : t("err.phone");
    if (!f.msg.trim()) er.msg = t("err.message");
    setErrs(er);
    if (Object.keys(er).length) return;
    setState("sending");
    setTimeout(() => setState(sim), 1200);
  };
  if (state === "ok") return (
    <div className="form-card result">
      <div className="alert alert-ok">{Ico.check()}<div><b>{t("ok.title")}</b><br />{t("ok.text")}</div></div>
      <button className="btn btn-dark" onClick={() => { setState("idle"); setF({ name: "", contact: "", msg: "" }); }}>{t("ok.new")}</button>
    </div>
  );
  return (
    <form className="form-card" onSubmit={submit} noValidate>
      <h2 className="h-3" style={{ marginBottom: 16 }}>{t("ct.form")}</h2>
      <div className="alert alert-demo" style={{ marginBottom: 18 }}>{Ico.info()}<span>{t("demo.notice")}</span></div>
      {state === "fail" && <div className="alert alert-err" role="alert" style={{ marginBottom: 16 }}>{Ico.info()}<div><b>{t("fail.title")}</b><br />{t("fail.text")}</div></div>}
      <div className="form-grid">
        <Field id="cf-name" label={t("fm.name")} error={errs.name} full>
          <input id="cf-name" className="input" autoComplete="name" value={f.name} onChange={e => setF({ ...f, name: e.target.value })} aria-invalid={!!errs.name} />
        </Field>
        <Field id="cf-contact" label={`${t("fm.phone")} / ${t("fm.email")}`} error={errs.contact} full hint={t("fm.either")}>
          <input id="cf-contact" className="input" value={f.contact} onChange={e => setF({ ...f, contact: e.target.value })} aria-invalid={!!errs.contact} />
        </Field>
        <Field id="cf-msg" label={t("fm.message")} error={errs.msg} full>
          <textarea id="cf-msg" className="input" value={f.msg} onChange={e => setF({ ...f, msg: e.target.value })} aria-invalid={!!errs.msg} />
        </Field>
        <div className="full" style={{ display: "grid", gap: 14 }}>
          <PrivacyLine />
          <button className="btn btn-primary btn-block" disabled={state === "sending"} aria-busy={state === "sending"}>
            {state === "sending" ? <><span className="spinner" aria-hidden="true"></span>{t("fm.sending")}</> : (state === "fail" ? t("fail.retry") : t("fm.send"))}
          </button>
          <DemoSim value={sim} onChange={setSim} />
        </div>
      </div>
    </form>
  );
}

Object.assign(window, { QuotePage, ContactForm, Field });
