/* ===================== Hintalaskuri (price calculator) ===================== */

const eur = (n) => (Math.round(n * 100) / 100).toLocaleString("fi-FI", { minimumFractionDigits: 0, maximumFractionDigits: 2 }) + " €";

/* window-type glyph */
function WinGlyph({ id }) {
  const s = { width: 56, height: 56, viewBox: "0 0 56 56", fill: "none", stroke: "var(--brand)", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
  const glass = "color-mix(in oklab, var(--brand) 9%, #fff)";
  switch (id) {
    case "kaide": case "parv_kaide":
      return <svg {...s}><rect x="8" y="14" width="40" height="22" rx="2" fill={glass}/><path d="M8 36h40M16 14v22M28 14v22M40 14v22M6 42h44"/></svg>;
    case "ovi":
      return <svg {...s}><rect x="16" y="6" width="24" height="44" rx="2" fill={glass}/><path d="M28 6v44"/><circle cx="23" cy="30" r="1.4" fill="var(--brand)"/></svg>;
    case "peili":
      return <svg {...s}><rect x="14" y="8" width="28" height="40" rx="14" fill={glass}/><path d="M20 16c0 0 4-2 8 0"/></svg>;
    case "korkea": case "ter_katto":
      return <svg {...s}><path d="M6 20l44-8v10l-44 8z" fill={glass}/><path d="M12 30v18M44 24v18M8 48h40"/></svg>;
    case "suuri": case "ryhma": case "ter_molemmat": case "ter_sisa": case "parv_matala": case "parv_korkea":
      return <svg {...s}><rect x="8" y="10" width="40" height="36" rx="2" fill={glass}/><path d="M28 10v36M8 28h40"/></svg>;
    case "tuuletus":
      return <svg {...s}><rect x="20" y="8" width="16" height="40" rx="2" fill={glass}/><path d="M36 8l6 4v32l-6 4"/></svg>;
    case "kiintea": case "parv_sisa": case "parv_molemmat": case "normaali":
      return <svg {...s}><rect x="12" y="10" width="32" height="36" rx="2" fill={glass}/><path d="M18 16l8 8"/></svg>;
    case "kylpy":
      return <svg {...s}><rect x="8" y="12" width="18" height="32" rx="2" fill={glass}/><rect x="30" y="12" width="18" height="32" rx="2" fill={glass}/></svg>;
    case "av6": case "kuusipintainen":
      return <svg {...s}><rect x="14" y="8" width="22" height="40" rx="2" fill={glass}/><path d="M36 8l8 5v30l-8 5M25 8v40"/></svg>;
    case "salekaihdin":
      return <svg {...s}><rect x="10" y="8" width="36" height="40" rx="2" fill={glass}/><path d="M10 18h36M10 26h36M10 34h36M10 42h36"/><path d="M28 8v40" strokeDasharray="3 2" strokeWidth="1.5"/></svg>;
    default: /* av4, ruutu, ruudukko* */
      return <svg {...s}><rect x="14" y="8" width="22" height="40" rx="2" fill={glass}/><path d="M36 8l8 5v30l-8 5"/>{(id==="ruutu" || id.indexOf("ruudukko")===0) && <path d="M25 8v40M14 28h22"/>}</svg>;
  }
}

function Stepper({ value, onChange }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 14, justifyContent: "center" }}>
      <button className="step" data-off={value===0} onClick={() => onChange(Math.max(0, value - 1))} aria-label="Vähennä"><Ic.minus/></button>
      <span style={{ fontFamily: "var(--head)", fontWeight: 800, fontSize: 20, minWidth: 28, textAlign: "center", color: value>0 ? "var(--brand)" : "var(--navy)" }}>{value}</span>
      <button className="step step--on" onClick={() => onChange(value + 1)} aria-label="Lisää"><Ic.plus/></button>
    </div>
  );
}

function CalcGroup({ group, qty, setQty, open, toggle, ulko }) {
  return (
    <div className="cgroup">
      <button className="cgroup__head" onClick={toggle}>
        <span className="cgroup__chev" data-open={open}><Ic.chevron/></span>
        {group.label}
        <span className="cgroup__count">{group.items.length} kohdetta</span>
      </button>
      {open && (
        <div className="cgroup__grid">
          {group.items.map((it) => {
            const disabled = !!(ulko && it.noUlko);
            return (
              <div className="witem" key={it.id}
                data-active={!disabled && (qty[it.id]||0) > 0}
                style={disabled ? { opacity: .4, pointerEvents: "none" } : {}}>
                <div className="witem__top">
                  <div className="witem__name">{it.name}</div>
                  <div className="witem__price">
                    <s className="witem__was">{eur(it.price / 0.7)}</s>{" "}
                    {it.price} € <span>/ {it.unit}</span>
                  </div>
                </div>
                <div className="witem__glyph"><WinGlyph id={it.id}/></div>
                {disabled
                  ? <div className="witem__hint" style={{color:"var(--muted)"}}>Ei saatavilla ulkopesun yhteydessä</div>
                  : it.hint && <div className="witem__hint">{it.hint}</div>
                }
                {disabled
                  ? <div style={{fontSize:12,color:"var(--faint)",textAlign:"center",padding:"6px 0"}}>—</div>
                  : <Stepper value={qty[it.id] || 0} onChange={(v) => setQty(it.id, v)} />
                }
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

function Calculator({ go }) {
  const [qty, setQtyState] = useState(() => {
    try { return JSON.parse(localStorage.getItem("kl_qty") || "{}"); } catch { return {}; }
  });
  const [openGroups, setOpenGroups] = useState(() => Object.fromEntries(D.calcGroups.map(g => [g.id, !!g.open])));
  const [showBooking, setShowBooking] = useState(false);
  const [ulkoRaw, setUlkoRaw] = useState(false);

  // Postinumero + validointi (vain Seinäjoen palvelualueen postinumerot kelpaavat)
  const [zipInput, setZipInput] = useState("");
  const [geoState, setGeoState] = useState(null); // null | 'ok' | 'fail'

  const setQty = (id, v) => setQtyState((q) => {
    const n = { ...q, [id]: v };
    localStorage.setItem("kl_qty", JSON.stringify(n));
    return n;
  });

  // Switching to ulko-only resets noUlko items (e.g. blind cleaning)
  const setUlko = (v) => {
    if (v) {
      setQtyState((q) => {
        const ids = D.calcGroups.flatMap(g => g.items).filter(it => it.noUlko).map(it => it.id);
        const n = { ...q };
        ids.forEach(id => { n[id] = 0; });
        localStorage.setItem("kl_qty", JSON.stringify(n));
        return n;
      });
    }
    setUlkoRaw(v);
  };
  const ulko = ulkoRaw;

  const allItems = useMemo(() => Object.fromEntries(D.calcGroups.flatMap(g => g.items.map(i => [i.id, i]))), []);
  const subtotal = useMemo(() => Object.entries(qty).reduce((s, [id, n]) => s + (allItems[id]?.price || 0) * n, 0), [qty, allItems]);
  const discountedSubtotal = ulko ? Math.round(subtotal * 0.7 * 100) / 100 : subtotal;
  const lines = useMemo(() => Object.entries(qty)
    .filter(([, n]) => n > 0)
    .map(([id, n]) => {
      const it = allItems[id];
      if (!it || (ulko && it.noUlko)) return null;
      const basePrice = it.price || 0;
      const price = ulko ? Math.round(basePrice * 0.7 * 100) / 100 : basePrice;
      return { id, name: it.name, qty: n, unit: it.unit || "kpl", price, total: price * n };
    }).filter(Boolean), [qty, allItems, ulko]);
  const count = Object.values(qty).reduce((s, n) => s + n, 0);
  const grossBase = Math.max(discountedSubtotal, count > 0 ? D.minOrder : 0);
  const gross = grossBase;
  const belowMin = count > 0 && discountedSubtotal < D.minOrder;
  const ulkoDiscount = ulko ? subtotal - discountedSubtotal : 0;
  const deduction = grossBase * D.deductionRate;
  const afterDeduction = Math.max(0, grossBase - deduction);

  const checkZip = (raw) => {
    const zip = raw.trim();
    if (!/^\d{5}$/.test(zip)) { setGeoState("fail"); return; }
    setGeoState(D.serviceZips.includes(zip) ? "ok" : "fail");
  };

  const handleZipChange = (e) => {
    const v = e.target.value.replace(/\D/g, "").slice(0, 5);
    setZipInput(v);
    setGeoState(null);
  };

  const canBook = count > 0 && geoState === "ok";
  const reset = () => { setQtyState({}); localStorage.removeItem("kl_qty"); };

  return (
    <div className="calc">
      <div className="wrap calc__inner">

        {/* ── summary rail ─────────────────────────────────────── */}
        <aside className="calc__rail">
          <div className="srail">
            <div className="srail__badge"><Ic.euro style={{color:"var(--brand)"}}/> Hintalaskuri</div>

            <div className="srail__total">
              <div className="srail__totalLabel">Hinta yhteensä</div>
              <div className="srail__amount">{eur(gross)}</div>
            </div>

            {belowMin && (
              <div style={{background:"var(--brand-soft)",borderRadius:8,padding:"9px 13px",fontSize:13,color:"var(--navy)",display:"flex",gap:8,alignItems:"center"}}>
                <Ic.spark style={{color:"var(--brand)",width:16,height:16,flex:"none"}}/>
                Minimiveloitus {D.minOrder} € — hinta nostettu automaattisesti.
              </div>
            )}

            <div className="srail__rows">
              {ulko && ulkoDiscount > 0 && (
                <div className="srow srow--disc"><span>Ulkopinnat −30 %</span><b>−{eur(ulkoDiscount)}</b></div>
              )}
              <div className="srow"><span>Kotitalousvähennys 35 % (2026)</span><b>−{eur(deduction)}</b></div>
              <div className="srow srow--accent">
                <span>Hinta vähennyksen jälkeen <i>arvio</i></span>
                <b>{eur(afterDeduction)}</b>
              </div>
            </div>

            {/* Postinumero → validointi (vain Seinäjoen palvelualue kelpaa) */}
            <div className="srail__zip" style={{marginTop:14}}>
              <label>Kohteen postinumero</label>
              <div className="ziprow">
                <input
                  inputMode="numeric"
                  maxLength={5}
                  placeholder="Esim. 60100"
                  value={zipInput}
                  onChange={handleZipChange}
                  onKeyDown={(e) => { if (e.key === "Enter") checkZip(zipInput); }}
                  autoComplete="off"
                />
                <button className="btn btn--ghost"
                  onClick={() => checkZip(zipInput)}
                  disabled={zipInput.trim().length < 5}>
                  Tarkista
                </button>
              </div>
              {geoState === "ok" && (
                <div className="zipres zipres--ok">
                  <Ic.check style={{width:14,height:14,flex:"none"}}/>
                  Postinumero kuuluu palvelualueeseen · ei matkustuskuluja
                </div>
              )}
              {geoState === "fail" && (
                <div className="zipres zipres--no">
                  Postinumero ei ole Seinäjoen alueella — soita meille, niin katsotaan onnistuuko käynti.
                </div>
              )}
            </div>

            {/* Booking button */}
            {canBook
              ? <>
                  <button className="btn btn--primary btn--block btn--lg" onClick={() => { setShowBooking(true); window.klTrack && window.klTrack({ type: 'avaa_varaus' }); }}
                    style={{display:"flex",alignItems:"center",justifyContent:"center",gap:9}}>
                    <Ic.cal style={{width:19,height:19}}/> Varaa aika
                  </button>
                  <p style={{fontSize:13,color:"var(--muted)",textAlign:"center",marginTop:4}}>
                    Voit perua ajan milloin tahansa puhelimitse.
                  </p>
                </>
              : <div style={{display:"flex",flexDirection:"column",gap:8,marginTop:14}}>
                  <button className="btn btn--primary btn--block btn--lg" disabled
                    style={{opacity:.42,cursor:"not-allowed"}}>
                    <Ic.cal style={{width:19,height:19}}/>{" "}
                    {count === 0 ? "Valitse ensin ikkunasi" : "Anna postinumero ensin"}
                  </button>
                  <p style={{fontSize:12.5,color:"var(--muted)",textAlign:"center"}}>
                    {count === 0
                      ? "Lisää ikkunoita laskuriin — sitten tarkista postinumero."
                      : "Syötä kohteen postinumero yllä ja paina Tarkista."}
                  </p>
                </div>
            }

            {count > 0 && <button className="srail__reset" onClick={reset}>Tyhjennä valinnat</button>}

            <div className="srail__trust">
              <Ic.shield style={{color:"var(--brand)", flex:"none"}}/>
              <span>Kiinteä hinta · ei piilokuluja · tyytyväisyystakuu</span>
            </div>
            <div className="srail__trust" style={{marginTop:6}}>
              <Ic.wallet style={{color:"var(--muted)", flex:"none"}}/>
              <span>{D.payment.methods.join(" · ")} · {D.payment.business}</span>
            </div>
          </div>
        </aside>

        {/* ── item groups ──────────────────────────────────────── */}
        <div className="calc__main">
          <div className="calc__head">
            <h1>Mitä pestään?</h1>
            <p className="lead">Valitse ikkunat ja määrät — hinta päivittyy automaattisesti.</p>
            <div className="calc__saleNote">−30 % alennetut hinnat — yliviivattu hinta on aiempi hinta</div>
            <div className="pesutapa-toggle">
              <button
                className={`pesutapa-toggle__btn ${!ulko ? "is-active" : ""}`}
                onClick={() => setUlko(false)}>
                <Ic.window style={{width:16,height:16}}/> Kaikki pinnat
              </button>
              <button
                className={`pesutapa-toggle__btn ${ulko ? "is-active" : ""}`}
                onClick={() => setUlko(true)}>
                <Ic.spark style={{width:16,height:16}}/> Ulkopinnat <span className="pesutapa-toggle__disc">−30 %</span>
              </button>
            </div>
          </div>
          {D.calcGroups.map((g) => (
            <CalcGroup key={g.id} group={g} qty={qty} setQty={setQty} ulko={ulko}
              open={openGroups[g.id]}
              toggle={() => setOpenGroups(o => ({ ...o, [g.id]: !o[g.id] }))} />
          ))}
          <div className="calc__foot">
            <Ic.spark style={{color:"var(--brand)"}}/>
            <div>
              <b>Erikoiskohteita tai iso taloyhtiö?</b>
              <p className="muted" style={{fontSize:14.5}}>Valitse ikkunat laskurista ja soita — sovitaan räätälöity käynti.</p>
            </div>
          </div>
        </div>
      </div>

      <BookingModal
        open={showBooking}
        onClose={() => setShowBooking(false)}
        ctx={{
          qty, lines, count,
          gross, grossBase, travelFee: 0, geoKm: null,
          deduction, afterDeduction,
          zipInput,
          service: ulko ? "Ulkopinnat" : "Kaikki pinnat",
        }}
      />
    </div>
  );
}

Object.assign(window, { Calculator, eur });
