/* Kings Roofing — Roof Generator app */
(function () {
  const { useState, useRef, useEffect } = React;
  const { I, Stars, TopBar, Steps, TrustBar, AddressInput, UploadInput } = window.KUI;
  const { ColourPicker, StickyBar } = window.KPICK;

  /* Locked-in design tokens (the design-tool "Tweaks" panel is stripped for production). */
  const T = {
    heroLayout: "split",
    headingStyle: "underline",
    swatchStyle: "cards",
    accent: "#7C3AED",
    showTrust: true,
    roundedCorners: 20,
  };

  const PHONE = "022 024 6072";
  // Kings Roofing contact page — the "Get a free quote" CTA links here.
  const CONTACT_URL = "https://kingsroofing.co.nz/contact";

  /* ===== Backend client ===== */
  const api = {
    async generate({ mode, address, view, photo, colour, finish }) {
      const fd = new FormData();
      fd.append("mode", mode);
      fd.append("address", address || "");
      fd.append("view", view || "top");
      fd.append("colorName", colour.name);
      fd.append("colorHex", colour.hex);
      fd.append("finish", finish);
      if (photo && photo.custom && photo.file) fd.append("photo", photo.file, photo.name);
      const res = await fetch("/api/generate", { method: "POST", body: fd });
      if (!res.ok) throw new Error("generate failed: " + res.status);
      return res.json(); // { image?, source?, mock?, engine }
    },
    async lead(payload) {
      try {
        await fetch("/api/lead", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload),
        });
      } catch (e) { /* non-blocking */ }
    },
  };

  /* ===== Marquee credential strip (Kings brand chrome) ===== */
  function Marquee() {
    const items = [
      "Free instant roof render", "No obligation, ever", "#1 rated roofer · Wellington 2025",
      "5.0★ from 100+ Google reviews", "RANZ member", "Colorsteel® approved installer",
      "30-year warranties", "Local Wellington crew",
    ];
    const run = (
      <div className="mq-run" aria-hidden="false">
        {items.map((x, i) => (
          <span className="mq-item" key={i}><span className="mq-dot"></span>{x}</span>
        ))}
      </div>
    );
    return (
      <div className="marquee">
        <div className="mq-track">{run}{run}</div>
      </div>
    );
  }

  /* ===== Generator card (shared across layouts) ===== */
  function Generator(props) {
    const { mode, setMode, address, setAddress, photo, setPhoto,
            colour, setColour, finish, setFinish, swatchStyle, onGenerate,
            view, setView } = props;
    const canGo = !!colour && (mode === "address" ? address.trim().length > 3 : !!photo);
    return (
      <div className="gen-card fade-in">
        <div className="gen-section">
          <div className="gen-head"><span className="n">1</span><h3>Find your place</h3></div>
          <div className="seg">
            <button className={mode === "address" ? "on" : ""} onClick={() => setMode("address")}>
              <span className="ic"><I.pin width="17" height="17" /></span>Use my address
              {mode === "address" && <span className="tag">Recommended</span>}
            </button>
            <button className={mode === "upload" ? "on" : ""} onClick={() => setMode("upload")}>
              <span className="ic"><I.image width="17" height="17" /></span>Upload a photo
            </button>
          </div>
          {mode === "address"
            ? (<>
                <AddressInput value={address} onChange={setAddress} onPick={setAddress} />
                <div className="view-toggle">
                  <span className="vt-label">Capture</span>
                  <label className={view === "top" ? "on" : ""}>
                    <input type="radio" name="viewmode" checked={view === "top"} onChange={() => setView("top")} />
                    Top view
                  </label>
                  <label className={view === "street" ? "on" : ""}>
                    <input type="radio" name="viewmode" checked={view === "street"} onChange={() => setView("street")} />
                    Street view
                  </label>
                </div>
              </>)
            : <UploadInput photo={photo} onUseDemo={setPhoto} onClear={() => setPhoto(null)} />}
        </div>

        <div className="gen-section">
          <div className="gen-head"><span className="n">2</span><h3>Choose a colour</h3></div>
          <p className="gen-note">Tap a Colorsteel® swatch and we’ll paint it straight onto your roof. Not sure yet? You can swap colours the moment your render lands.</p>
          <ColourPicker colour={colour} onPick={setColour} finish={finish} onFinish={setFinish} swatchStyle={swatchStyle} />
        </div>

        <div className="gen-foot">
          <StickyBar colour={colour} canGo={canGo} onGo={onGenerate} />
        </div>
      </div>
    );
  }

  /* ===== Hero copy block ===== */
  function HeroCopy({ centered, headingStyle }) {
    const hs = headingStyle || "underline";
    const accentCls = hs === "underline" ? "accent-underline" : "accent-text";
    return (
      <div className="hero-copy">
        <span className="pill-badge">
          <I.check className="tick" width="13" height="13" /> Free render · See it on your own home · No sales pitch
        </span>
        <h1 className={"display h1 hstyle-" + hs}>
          Try on a <span className={accentCls}>new roof</span> <span className="h1-rest">before you spend a cent.</span>
        </h1>
        <p className="hero-sub">
          Drop in your Wellington address, choose a Colorsteel® colour, and we’ll paint it onto a render of your actual home — in about a minute.
        </p>
      </div>
    );
  }

  /* ===== Selection sidebar ===== */
  function SelectionCard({ colour, finish }) {
    const [open, setOpen] = useState(false);
    return (
      <div className="sel-card">
        <div className="sel-h"><span className="k">Your selection</span></div>
        <div className="sel-body">
          <span className="big" style={{ background: colour.hex }}></span>
          <div>
            <div className="nm">{colour.name}</div>
            <div className="sub">Colorsteel® · {finish} · Corrugate</div>
          </div>
        </div>
        <button className="sel-h" style={{ width: "100%", textAlign: "left", borderTop: "1px solid var(--line)", borderBottom: open ? "1px solid var(--line)" : "none", display: "flex", justifyContent: "space-between", alignItems: "center" }} onClick={() => setOpen(!open)}>
          <span className="k">Selection details</span>
          <span style={{ color: "var(--ink-3)", transform: open ? "rotate(180deg)" : "none", transition: ".2s" }}><I.chevron width="16" height="16" /></span>
        </button>
        {open && (
          <div style={{ padding: "14px 20px", fontSize: "13px", color: "var(--ink-2)", lineHeight: 1.7 }}>
            <div>Profile · Corrugate (0.55 BMT)</div>
            <div>Finish · {finish} Colorsteel®</div>
            <div>Warranty · Up to 30 years</div>
          </div>
        )}
        <div className="sel-foot"><span className="dot" style={{ width: 7, height: 7, borderRadius: 99, background: "var(--good)" }}></span>Free site visit within 5 working days · no obligation</div>
      </div>
    );
  }

  /* ===== Lead form ===== */
  function LeadForm({ onSubmit }) {
    const [f, setF] = useState({ name: "", phone: "", email: "", consent: true });
    const emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(f.email.trim());
    const phoneOk = f.phone.replace(/\D/g, "").length >= 8;
    const ok = f.name.trim() && phoneOk && emailOk && f.consent;
    const set = (k) => (e) => setF({ ...f, [k]: e.target.value });
    return (
      <div className="code-card fade-in">
        <div className="lock-ic" style={{ color: "var(--accent-2)" }}><I.shield width="22" height="22" /></div>
        <h3>Get your free, no-obligation quote</h3>
        <p>Like what you see? Pop in your details and the Kings Roofing team will be in touch about your new roof.</p>
        <div className="lead-form">
          <div className="lead-field">
            <label>Full name</label>
            <input value={f.name} onChange={set("name")} placeholder="Jordan Te Whare" />
          </div>
          <div className="fl-row">
            <div className="lead-field">
              <label>Mobile</label>
              <input value={f.phone} onChange={set("phone")} placeholder="021 234 5678" inputMode="tel" />
            </div>
            <div className="lead-field">
              <label>Email</label>
              <input value={f.email} onChange={set("email")} placeholder="you@email.co.nz" inputMode="email" />
            </div>
          </div>
          <label className="consent">
            <input type="checkbox" checked={f.consent} onChange={(e) => setF({ ...f, consent: e.target.checked })} />
            I’d like Kings Roofing to contact me about my quote. No spam.
          </label>
          <button className="btn btn-primary btn-lg" disabled={!ok} onClick={() => onSubmit(f)}
            style={{ justifyContent: "center", ...( !ok ? { opacity: .45, cursor: "not-allowed", boxShadow: "none" } : {}) }}>
            Get my free quote<span className="arrow"><I.arrow width="14" height="14" /></span>
          </button>
        </div>
      </div>
    );
  }

  /* ===== Thank-you card (shown after the quote form is submitted) ===== */
  function ThanksCard() {
    return (
      <div className="code-card fade-in" style={{ textAlign: "center" }}>
        <div className="lock-ic" style={{ color: "var(--accent-2)" }}><I.check width="22" height="22" /></div>
        <h3>Thanks — we’ll be in touch</h3>
        <p>Your details are with the Kings Roofing team. We’ll reach out shortly about your free quote.</p>
      </div>
    );
  }

  /* ===== OTP =====
     Simulated 6-digit verification (matches the design intent — no live SMS gateway). */
  function OtpCard({ lead, onDone, onEdit }) {
    const [d, setD] = useState(["", "", "", "", "", ""]);
    const refs = useRef([]);
    useEffect(() => { refs.current[0] && refs.current[0].focus(); }, []);
    useEffect(() => { if (d.every((x) => x !== "")) { const t = setTimeout(onDone, 350); return () => clearTimeout(t); } }, [d]);
    const tail = (lead && lead.phone || "•••• 1111").replace(/\s/g, "").slice(-4);
    const set = (i, v) => {
      v = v.replace(/\D/g, "").slice(-1);
      const nd = [...d]; nd[i] = v; setD(nd);
      if (v && i < 5) refs.current[i + 1].focus();
    };
    const key = (i, e) => { if (e.key === "Backspace" && !d[i] && i > 0) refs.current[i - 1].focus(); };
    return (
      <div className="code-card fade-in">
        <div className="lock-ic"><I.lock width="22" height="22" /></div>
        <h3>Enter your 6-digit code</h3>
        <p>We texted a code to <b>+64 ••• {tail}</b>. Pop it in below and we’ll render your roof.</p>
        <div className="otp">
          {d.map((v, i) => (
            <input key={i} ref={(el) => (refs.current[i] = el)} value={v} className={v ? "filled" : ""}
              inputMode="numeric" maxLength="1"
              onChange={(e) => set(i, e.target.value)} onKeyDown={(e) => key(i, e)} />
          ))}
        </div>
        <div className="code-links">
          <button onClick={onEdit}>Edit my details</button>
          <button onClick={() => { setD(["","","","","",""]); refs.current[0].focus(); }}>Didn’t get it? Resend</button>
        </div>
      </div>
    );
  }

  /* ===== Quote CTA ===== */
  function QuoteCTA({ colour }) {
    return (
      <div className="quote-cta fade-in">
        <div className="inner">
          <div>
            <span className="eyebrow accent">Ready when you are</span>
            <h2 className="display" style={{ fontSize: "clamp(26px,3vw,40px)", marginTop: 12 }}>
              We’ll prepare a fixed-price quote for your {colour.name} roof.
            </h2>
            <p>One of our Wellington roofers will visit, measure up and confirm your fixed price — usually within 5 working days. No obligation.</p>
          </div>
          <div className="quote-actions">
            <a className="btn btn-primary btn-lg" href={CONTACT_URL} target="_top" rel="noopener">Get a free quote<span className="arrow"><I.arrow width="14" height="14" /></span></a>
            <a className="btn btn-ghost btn-lg" href={"tel:" + PHONE.replace(/\s/g, "")} target="_top"><I.phone width="17" height="17" /> Call {PHONE}</a>
          </div>
        </div>
      </div>
    );
  }

  /* ===== Result ===== */
  function Result({ engine, photoSrc, aiSrc, colour, onPickColour, finish, rendering, lead, onSubmitLead }) {
    const D = window.KINGS_DATA;
    return (
      <>
      <div className="result-grid">
        <div>
          <window.RoofReveal engine={engine} photoSrc={photoSrc} aiSrc={aiSrc} colour={colour} finish={finish} loading={rendering} />
          <div className="try-rail">
            <div className="lab">Try another colour — we’ll re-render your roof</div>
            <div className="rail-sw">
              {D.COLOURS.map((c) => (
                <button key={c.name} className={colour.name === c.name ? "on" : ""} onClick={() => onPickColour(c)}>
                  <div className="d" style={{ background: c.hex }}></div>
                  <div className="n">{c.name}</div>
                </button>
              ))}
            </div>
          </div>
        </div>
        {/* Right column: selection summary, then the quote form directly below it. */}
        <div style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
          <SelectionCard colour={colour} finish={finish} />
          {!rendering && (lead ? <ThanksCard /> : <LeadForm onSubmit={onSubmitLead} />)}
        </div>
      </div>
      <QuoteCTA colour={colour} />
      </>
    );
  }

  /* ===== Root App ===== */
  function App() {
    const [stage, setStage] = useState("input"); // input | lead | verify | result
    const [mode, setMode] = useState("address");
    const [address, setAddress] = useState("");
    const [view, setView] = useState("top"); // top (satellite) | street

    const [photo, setPhoto] = useState(null);
    const [colour, setColour] = useState(null);
    const [finish, setFinish] = useState("Standard");
    const [lead, setLead] = useState(null);
    const [engine, setEngine] = useState(null);
    const [aiSrc, setAiSrc] = useState(null);
    const [beforeSrc, setBeforeSrc] = useState(null);
    const [rendering, setRendering] = useState(false);
    const [roofNote, setRoofNote] = useState(null);
    const aiMode = useRef(false); // true once the backend returns a real AI render

    // brand tokens -> CSS vars
    useEffect(() => {
      const r = document.documentElement.style;
      r.setProperty("--accent", T.accent);
      r.setProperty("--radius", T.roundedCorners + "px");
    }, []);

    // What the canvas-mock engine paints when no AI key is configured.
    const mockSrc = (photo && photo.custom) ? photo.src : "assets/house.jpg";
    const mockMask = (photo && photo.custom) ? null : "assets/roof-mask.png";

    const locationLabel = mode === "upload"
      ? "Your uploaded home"
      : (address || "Your Wellington home");

    // Ben: render first, capture info afterwards. Go straight to the render.
    const startGenerate = () => { beginRender(); };
    const jumpToFlow = () => setTimeout(() => {
      const el = document.getElementById("flow");
      if (el) window.scrollTo({ top: el.offsetTop - 80, behavior: "smooth" });
    }, 40);

    // ensure the canvas mock engine is built for the current source
    const ensureEngine = async (src, mask) => {
      let eng = engine;
      if (!eng || eng._src !== src) {
        eng = new window.RoofEngine();
        await eng.init(src, mask);
        eng._src = src;
        setEngine(eng);
      }
      return eng;
    };

    // Call the backend to produce the render for `col`.
    const runRender = async (col) => {
      setRendering(true);
      // Show the user's real home immediately (their photo, or the same source the
      // AI will recolour) so they see something in <1s instead of a bare spinner.
      if (photo && photo.custom && photo.src) {
        setBeforeSrc(photo.src);
      } else if (address) {
        setBeforeSrc("/api/source?address=" + encodeURIComponent(address) + "&view=" + encodeURIComponent(view || "top"));
      }
      try {
        const out = await api.generate({ mode, address, view, photo, colour: col, finish });
        if (out && out.image) {
          aiMode.current = true;
          setBeforeSrc(out.source || mockSrc);
          setAiSrc(out.image);
          setRoofNote(out.roofDetected === false
            ? "We couldn’t clearly find a roof at this location, so nothing was recoloured. Try the “Upload a photo” option for an accurate render."
            : null);
          // wait for the AI image to decode before lifting the loader
          await new Promise((res) => { const im = new Image(); im.onload = im.onerror = res; im.src = out.image; });
          setRendering(false);
        } else {
          // mock / no-key path: paint locally with the canvas engine
          aiMode.current = false;
          setAiSrc(null);
          setBeforeSrc(mockSrc); setRoofNote(null);
          await ensureEngine(mockSrc, mockMask);
          setTimeout(() => setRendering(false), 700);
        }
      } catch (e) {
        // network/server error -> fall back to the canvas mock so the flow never dead-ends
        aiMode.current = false;
        setAiSrc(null);
        setBeforeSrc(mockSrc);
        try { await ensureEngine(mockSrc, mockMask); } catch (_) {}
        setTimeout(() => setRendering(false), 700);
      }
    };

    const beginRender = async () => {
      setStage("result");
      jumpToFlow();
      await runRender(colour);
    };

    // "Try another colour" rail
    const pickColourLive = (c) => {
      setColour(c);
      if (aiMode.current) {
        runRender(c); // re-render with AI for the new colour
      }
      // mock mode: the RoofReveal canvas recolours instantly via its own effect
    };

    const startOver = () => {
      setStage("input");
      setAiSrc(null);
      setBeforeSrc(null);
      setRoofNote(null);
      setLead(null);
      aiMode.current = false;
      window.scrollTo({ top: 0, behavior: "smooth" });
    };

    const heroLayout = T.heroLayout;

    return (
      <>

        {stage === "input" && (
          <section className="hero">
            <div className="hero-bg"></div>
            {heroLayout === "showcase" ? (
              <div className="app" style={{ paddingTop: 0 }}>
                <div className="showcase-band">
                  <img className="showcase-bg" src="assets/house.jpg" alt="" />
                  <div className="showcase-inner"><HeroCopy centered headingStyle={T.headingStyle} /></div>
                </div>
                <div style={{ maxWidth: 760, margin: "26px auto 0" }}>
                  {T.showTrust && <div style={{ display: "flex", justifyContent: "center", marginBottom: 26 }}><TrustBar /></div>}
                  <Generator mode={mode} setMode={setMode} address={address} setAddress={setAddress}
                    photo={photo} setPhoto={setPhoto} colour={colour} setColour={setColour}
                    finish={finish} setFinish={setFinish} swatchStyle={T.swatchStyle} onGenerate={startGenerate}
                    view={view} setView={setView} />
                </div>
              </div>
            ) : (
              <div className={"app hero-grid " + (heroLayout === "stacked" ? "stacked" : "split")}>
                {heroLayout === "stacked" ? (
                  <div>
                    <HeroCopy centered headingStyle={T.headingStyle} />
                    {T.showTrust && <TrustBar />}
                    <div style={{ maxWidth: 720, margin: "38px auto 0" }}>
                      <Generator mode={mode} setMode={setMode} address={address} setAddress={setAddress}
                        photo={photo} setPhoto={setPhoto} colour={colour} setColour={setColour}
                        finish={finish} setFinish={setFinish} swatchStyle={T.swatchStyle} onGenerate={startGenerate}
                    view={view} setView={setView} />
                    </div>
                  </div>
                ) : (
                  <>
                    <div>
                      <HeroCopy headingStyle={T.headingStyle} />
                      {T.showTrust && <TrustBar />}
                    </div>
                    <Generator mode={mode} setMode={setMode} address={address} setAddress={setAddress}
                      photo={photo} setPhoto={setPhoto} colour={colour} setColour={setColour}
                      finish={finish} setFinish={setFinish} swatchStyle={T.swatchStyle} onGenerate={startGenerate}
                    view={view} setView={setView} />
                  </>
                )}
              </div>
            )}
          </section>
        )}

        {stage !== "input" && (
          <section id="flow" className="app flow-wrap">
            <button className="back-link" onClick={startOver}><I.back width="14" height="14" /> Start over</button>
            <div className="flow-eyebrow eyebrow accent">Your Kings Roofing render</div>
            <h2 className="flow-addr">{locationLabel}</h2>

            {stage === "result" && (
              <div style={{ marginTop: 30 }}>
                {roofNote && (
                  <div style={{ background: "var(--accent-soft)", border: "1px solid rgba(124,58,237,.32)",
                    color: "var(--accent-2)", padding: "12px 16px", borderRadius: "12px", marginBottom: "18px",
                    fontSize: "13.5px", fontWeight: 600, display: "flex", gap: "9px", alignItems: "center" }}>
                    <I.image width="17" height="17" /> {roofNote}
                  </div>
                )}
                <Result engine={engine} photoSrc={beforeSrc || mockSrc} aiSrc={aiSrc} colour={colour}
                  onPickColour={pickColourLive} finish={finish} rendering={rendering}
                  lead={lead}
                  onSubmitLead={(f) => {
                    setLead(f);
                    api.lead({ ...f, address, mode, colour: colour.name, hex: colour.hex, finish });
                  }} />
              </div>
            )}
          </section>
        )}
      </>
    );
  }

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