// === Request a Quote — configurator ===
// Standalone page app. Loads the public (price-only) config, lets the
// customer build a unit, shows a LIVE price preview (client-side mirror
// of the server maths), collects contact details, and POSTs to
// /api/quote which emails a branded PDF. The server recomputes the
// price authoritatively — this preview is UX only.

const round2 = (n) => Math.round((Number(n) + Number.EPSILON) * 100) / 100;
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

// Aggregate any per-unit spec over a quantity: leading number x qty, unit kept
// verbatim — works for "5kW"->"10kW", "16A", "5m", "440w". Non-numeric unit
// shows as-is; empty -> ''.
function specTotal(unitStr, qty) {
  const u = String(unitStr || '').trim();
  if (!u || !(qty > 0)) return '';
  const m = u.match(/^(\d+(?:\.\d+)?)\s*(.*)$/);
  if (!m) return u;
  const total = Math.round(parseFloat(m[1]) * qty * 100) / 100;
  return `${total}${m[2].trim()}`;
}

function useMoneyFmt(currency) {
  return React.useCallback((n) => {
    const prefix = (currency || 'NZD') === 'NZD' ? 'NZ$' : (currency || '') + ' ';
    return prefix + Number(n || 0).toLocaleString('en-NZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  }, [currency]);
}

// Small +/- stepper.
function Stepper({ label, sub, value, min, max, onChange }) {
  const disabled = max <= min;
  return (
    <div className={`q-stepper ${disabled ? 'is-disabled' : ''}`}>
      <div className="q-stepper-text">
        <div className="q-stepper-label">{label}</div>
        {sub && <div className="q-stepper-sub">{sub}</div>}
      </div>
      <div className="q-stepper-ctrl">
        <button type="button" aria-label={`Decrease ${label}`} disabled={disabled || value <= min}
                onClick={() => onChange(clamp(value - 1, min, max))}>−</button>
        <span className="q-stepper-val">{value}</span>
        <button type="button" aria-label={`Increase ${label}`} disabled={disabled || value >= max}
                onClick={() => onChange(clamp(value + 1, min, max))}>+</button>
      </div>
    </div>
  );
}

function QuoteApp() {
  const [pub, setPub] = React.useState(null);
  const [loadErr, setLoadErr] = React.useState('');

  const [sizeId, setSizeId] = React.useState(null);
  const [mount, setMount] = React.useState('trailer');
  const [addInv, setAddInv] = React.useState(0);
  const [addBat, setAddBat] = React.useState(0);
  const [floorPanels, setFloorPanels] = React.useState(0);
  const [cargoBay, setCargoBay] = React.useState(false);

  const [contact, setContact] = React.useState({ name: '', email: '', phone: '', address: '' });
  const [company, setCompany] = React.useState(''); // honeypot
  const [submitting, setSubmitting] = React.useState(false);
  const [result, setResult] = React.useState(null);
  const [error, setError] = React.useState('');

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch('/api/quote-config');
        if (!res.ok) throw new Error('load');
        const data = await res.json();
        if (cancelled) return;
        setPub(data);
        if (data.sizes && data.sizes[0]) setSizeId(data.sizes[0].id);
      } catch {
        if (!cancelled) setLoadErr('Could not load the configurator. Please refresh or email power@solartrailer.co.nz.');
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const fmt = useMoneyFmt(pub && pub.currency);
  const size = pub && pub.sizes ? pub.sizes.find((s) => s.id === sizeId) : null;

  // Re-clamp option counts whenever the selected size changes.
  React.useEffect(() => {
    if (!size) return;
    setAddInv((v) => clamp(v, 0, size.inverter.max - size.inverter.min));
    setAddBat((v) => clamp(v, 0, size.battery.max - size.battery.min));
    setFloorPanels((v) => clamp(v, size.panelStand.min, size.panelStand.max));
    if (!size.cargoBay.allowed) setCargoBay(false);
  }, [sizeId]); // eslint-disable-line

  // Live price preview — mirrors api/_lib/pricing.computeQuote.
  const preview = React.useMemo(() => {
    if (!pub || !size) return null;
    const lines = [];
    const push = (label, qty, unitPrice, unitSpec) => { if (qty > 0) lines.push({ label, qty, line: round2(unitPrice * qty), unitSpec: unitSpec || '' }); };

    if (mount === 'skids') push(size.skids.label, 1, size.skids.price, size.skids.unit);
    else push(size.trailer.label, 1, size.trailer.price, size.trailer.unit);
    push(size.switchboard.label, 1, size.switchboard.price, size.switchboard.unit);
    push(size.panelBase.label, size.panelBase.qty, size.panelBase.price, size.panelBase.unit);

    const invTotal = size.inverter.min + addInv;
    push(size.inverter.label, invTotal, size.inverter.price, size.inverter.unit);
    const batTotal = size.battery.min + addBat;
    push(size.battery.label, batTotal, size.battery.price, size.battery.unit);
    push(size.panelStand.label, floorPanels, size.panelStand.price, size.panelStand.unit);
    if (cargoBay && size.cargoBay.allowed) push(size.cargoBay.label, 1, size.cargoBay.price, size.cargoBay.unit);

    const subtotal = round2(lines.reduce((s, l) => s + l.line, 0));
    const operational = round2(subtotal * pub.operationalPct / 100);
    const total = round2(subtotal + operational);
    const deposit = round2(total * pub.depositPct / 100);
    const balance = round2(total - deposit);
    return { lines, subtotal, operational, total, deposit, balance, invTotal, batTotal };
  }, [pub, size, mount, addInv, addBat, floorPanels, cargoBay]);

  const setField = (k) => (e) => setContact((c) => ({ ...c, [k]: e.target.value }));

  const submit = async (e) => {
    e.preventDefault();
    if (submitting || !size) return;
    setError('');
    if (!contact.name || !contact.email || !contact.phone || !contact.address) {
      setError('Please fill in your name, email, phone and delivery address.');
      return;
    }
    setSubmitting(true);
    try {
      const res = await fetch('/api/quote', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          size: sizeId, mount, addInverters: addInv, addBatteries: addBat,
          floorPanels, cargoBay, ...contact, company_url: company,
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || `Server returned ${res.status}`);
      setResult(data);
    } catch (err) {
      setError(err.message || "Couldn't send right now. Please email power@solartrailer.co.nz.");
    } finally {
      setSubmitting(false);
    }
  };

  if (loadErr) return <div className="q-load q-load-err">{loadErr}</div>;
  if (!pub || !size) return <div className="q-load">Loading configurator…</div>;

  if (result) {
    return (
      <div className="q-done">
        <div className="q-done-check">✓</div>
        <h2 className="display q-done-title">Quote {result.quoteNumber} sent.</h2>
        <p className="q-done-sub">
          {result.emailedCustomer
            ? `We've emailed a branded PDF quote to ${contact.email} and to our team.`
            : `Your quote is on its way to our team — we'll be in touch shortly at ${contact.email}.`}
        </p>
        <div className="q-done-figures">
          <div><span>Total</span><strong>{fmt(result.total)}</strong></div>
          <div><span>{pub.depositPct}% deposit</span><strong>{fmt(result.deposit)}</strong></div>
        </div>
        <p className="q-done-fine">
          Pickup is free · shipping quoted separately · reply to the email to confirm your build.<br />
          This quote is valid 30 days and is subject to our <a href="/terms">Terms &amp; Conditions of Sale</a>.
        </p>
        <a href="/" className="btn btn-primary">Back to home <ArrowRight size={14} stroke={2} className="arrow" /></a>
      </div>
    );
  }

  const invMax = size.inverter.max - size.inverter.min;
  const batMax = size.battery.max - size.battery.min;
  // Spec now lives in its own field (e.g. "6kW", "5kW", "440w").
  const invSpec = size.inverter.unit || '';
  const batSpec = size.battery.unit || '';
  const fpSpec = size.panelStand.unit || '';

  return (
    <div className="q-grid">
      {/* LEFT — configuration */}
      <div className="q-config">
        <section className="q-block">
          <div className="q-step-eyebrow">Step 1 — Model size</div>
          <div className="q-sizes">
            {pub.sizes.map((s) => (
              <button key={s.id} type="button" className={`q-size ${s.id === sizeId ? 'active' : ''}`}
                      onClick={() => setSizeId(s.id)}>
                <div className="q-size-name">{s.label}</div>
                <div className="q-size-spec">{s.panelBase.qty} panels · {s.battery.min}–{s.battery.max} batteries</div>
              </button>
            ))}
          </div>
        </section>

        <section className="q-block">
          <div className="q-step-eyebrow">Step 2 — Mounting</div>
          <div className="q-mounts">
            <button type="button" className={`q-mount ${mount === 'skids' ? 'active' : ''}`} onClick={() => setMount('skids')}>
              <div className="q-mount-name">On skids</div>
              <div className="q-mount-sub">Fixed-site skid mount (no trailer)</div>
              <div className="q-mount-price">{fmt(size.skids.price)}</div>
            </button>
            <button type="button" className={`q-mount ${mount === 'trailer' ? 'active' : ''}`} onClick={() => setMount('trailer')}>
              <div className="q-mount-name">On a trailer</div>
              <div className="q-mount-sub">Road-legal trailer base</div>
              <div className="q-mount-price">{fmt(size.trailer.price)}</div>
            </button>
          </div>
        </section>

        <section className="q-block">
          <div className="q-step-eyebrow">Step 3 — Add capacity</div>
          <Stepper label={`Additional inverters${invSpec ? ' · ' + invSpec : ''}`} sub={`${size.inverter.min} included · up to ${invMax} more`}
                   value={addInv} min={0} max={invMax} onChange={setAddInv} />
          <Stepper label={`Additional batteries${batSpec ? ' · ' + batSpec : ''}`} sub={`${size.battery.min} included · up to ${batMax} more`}
                   value={addBat} min={0} max={batMax} onChange={setAddBat} />
          <Stepper label={`Floor-mounted panels${fpSpec ? ' · ' + fpSpec : ''}`} sub={`Add-on · up to ${size.panelStand.max}`}
                   value={floorPanels} min={size.panelStand.min} max={size.panelStand.max} onChange={setFloorPanels} />
        </section>

        <section className="q-block">
          <div className="q-step-eyebrow">Step 4 — Add-ons</div>
          {size.cargoBay.allowed ? (
            <button type="button" className={`q-toggle ${cargoBay ? 'active' : ''}`} onClick={() => setCargoBay((v) => !v)}
                    aria-pressed={cargoBay}>
              <span className="q-toggle-box">{cargoBay ? '✓' : ''}</span>
              <span className="q-toggle-text">
                <span className="q-toggle-name">Enclosed cargo bay</span>
                <span className="q-toggle-sub">Lockable storage on the back · {fmt(size.cargoBay.price)}</span>
              </span>
            </button>
          ) : (
            <div className="q-toggle is-disabled">
              <span className="q-toggle-box" />
              <span className="q-toggle-text">
                <span className="q-toggle-name">Enclosed cargo bay</span>
                <span className="q-toggle-sub">Not available on the {size.label} model</span>
              </span>
            </div>
          )}
        </section>
      </div>

      {/* RIGHT — summary + contact */}
      <form className="q-summary" onSubmit={submit}>
        <div className="q-summary-head">
          <span className="q-plate-title">Your quote</span>
          <span className="q-plate-no">{size.label} · {mount === 'skids' ? 'Skids' : 'Trailer'}</span>
        </div>

        <div className="q-lines">
          {preview.lines.map((l, i) => {
            const st = specTotal(l.unitSpec, l.qty);
            return (
              <div className="q-line" key={i}>
                <span className="q-line-label">{l.label}</span>
                <span className="q-line-qty">×{l.qty}</span>
                <span className="q-line-total">{st}</span>
              </div>
            );
          })}
        </div>

        <div className="q-totals">
          <div className="q-total-row"><span>Subtotal</span><span>{fmt(preview.subtotal)}</span></div>
          <div className="q-total-row muted"><span>GST ({pub.operationalPct}%)</span><span>{fmt(preview.operational)}</span></div>
          <div className="q-total-row grand"><span>Total</span><span>{fmt(preview.total)}</span></div>
        </div>

        <div className="q-deposit">
          <div className="q-deposit-l">
            <div className="q-deposit-label">{pub.depositPct}% deposit to confirm</div>
            <div className="q-deposit-sub">Balance {fmt(preview.balance)} before despatch</div>
          </div>
          <div className="q-deposit-amt">{fmt(preview.deposit)}</div>
        </div>

        <p className="q-fulfil">Free pickup · shipping quoted separately by address</p>

        <div className="q-contact">
          <div className="q-field">
            <label>Full name</label>
            <input value={contact.name} onChange={setField('name')} required placeholder="Your name" autoComplete="name" />
          </div>
          <div className="q-field">
            <label>Email</label>
            <input type="email" value={contact.email} onChange={setField('email')} required placeholder="you@company.co.nz" autoComplete="email" />
          </div>
          <div className="q-field">
            <label>Phone</label>
            <input type="tel" value={contact.phone} onChange={setField('phone')} required placeholder="021 234 5678" autoComplete="tel" />
          </div>
          <div className="q-field">
            <label>Delivery / site address</label>
            <textarea rows="2" value={contact.address} onChange={setField('address')} required placeholder="Street, town, region" autoComplete="street-address" />
          </div>
          {/* Honeypot */}
          <input type="text" name="company_url" value={company} onChange={(e) => setCompany(e.target.value)}
                 tabIndex="-1" autoComplete="off" aria-hidden="true"
                 style={{ position: 'absolute', left: '-9999px', width: 1, height: 1, opacity: 0 }} />
        </div>

        {error && <div className="q-error" role="alert">{error}</div>}

        <button type="submit" className="q-submit" disabled={submitting}>
          {submitting ? 'Sending your quote…' : 'Email me this quote'}
          {!submitting && <ArrowRight size={15} stroke={2.5} className="arrow" />}
        </button>
        <p className="q-legal">
          You'll get a branded PDF by email. A copy goes to our team so we can follow up.<br />
          Quotes are valid 30 days and are subject to our{' '}
          <a href="/terms" target="_blank" rel="noopener">Terms &amp; Conditions of Sale</a>.
        </p>
      </form>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<QuoteApp />);
