/* GarageWiz — shared UI components + app context */
(function () {
  const e = React.createElement;
  const { useState } = React;
  const Icon = window.Icon;

  /* ---------- App context ---------- */
  const AppCtx = React.createContext(null);
  window.AppCtx = AppCtx;
  window.useApp = () => React.useContext(AppCtx);

  /* ---------- Brand marks ---------- */
  function Wordmark({ height = 46, style }) {
    return e('img', {
      src: 'assets/wordmark-trans.png', alt: 'GarageWiz Overhead Doors',
      style: Object.assign({ height, width: 'auto', display: 'block' }, style),
      draggable: false,
    });
  }
  function Mascot({ size = 160, style, flip, className }) {
    return e('img', {
      src: 'assets/mascot.png', alt: '', className,
      style: Object.assign({ width: size, height: 'auto', display: 'block', transform: flip ? 'scaleX(-1)' : null }, style),
      draggable: false,
    });
  }
  window.Wordmark = Wordmark;
  window.Mascot = Mascot;

  /* ---------- Button ---------- */
  function Btn(props) {
    const { variant = 'primary', size, block, icon, iconRight, children, className = '', ...rest } = props;
    const cls = ['btn', 'btn-' + variant, size === 'sm' ? 'btn-sm' : '', size === 'lg' ? 'btn-lg' : '', block ? 'btn-block' : '', className].filter(Boolean).join(' ');
    return e('button', Object.assign({ className: cls }, rest),
      icon ? e(Icon, { name: icon, size: size === 'sm' ? 16 : 19 }) : null,
      children != null ? e('span', null, children) : null,
      iconRight ? e(Icon, { name: iconRight, size: size === 'sm' ? 16 : 19 }) : null,
    );
  }
  window.Btn = Btn;

  /* ---------- Badge ---------- */
  function Badge({ kind, children }) {
    const map = { pop: 'badge-pop', prem: 'badge-prem', start: 'badge-start', order: 'badge-order', good: 'badge-good' };
    return e('span', { className: 'badge ' + (map[kind] || 'badge-start') }, children);
  }
  window.Badge = Badge;

  /* ---------- Toggle switch ---------- */
  function Toggle({ on, onChange, label }) {
    return e('button', {
      type: 'button', role: 'switch', 'aria-checked': !!on,
      onClick: () => onChange(!on),
      'aria-label': label,
      style: {
        width: 52, height: 30, borderRadius: 999, border: 'none', padding: 3,
        background: on ? 'var(--good)' : '#C6D5D8', transition: 'background .18s',
        display: 'inline-flex', alignItems: 'center', flexShrink: 0,
      },
    }, e('span', {
      style: {
        width: 24, height: 24, borderRadius: 999, background: '#fff', display: 'block',
        transform: on ? 'translateX(22px)' : 'translateX(0)', transition: 'transform .18s cubic-bezier(.2,.8,.2,1)',
        boxShadow: '0 1px 3px rgba(0,0,0,.25)',
      },
    }));
  }
  window.Toggle = Toggle;

  /* ---------- Option tile (selectable card) ---------- */
  function OptionTile(props) {
    const { selected, onClick, title, sub, badge, badgeLabel, right, disabled, compact, style } = props;
    return e('button', {
      type: 'button', onClick, disabled,
      style: Object.assign({
        textAlign: 'left', position: 'relative', width: '100%',
        background: selected ? '#fff' : 'var(--field)',
        border: '2.5px solid ' + (selected ? 'var(--blue)' : 'transparent'),
        boxShadow: selected ? '0 6px 18px rgba(0,177,237,.18)' : 'inset 0 0 0 1px var(--line)',
        borderRadius: 'var(--r-lg)', padding: compact ? '14px 16px' : '18px 20px',
        cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? .5 : 1,
        transition: 'border-color .15s, box-shadow .15s, background .15s, transform .08s',
        display: 'flex', alignItems: 'center', gap: 14,
      }, style),
    },
      e('div', { className: 'grow', style: { minWidth: 0 } },
        e('div', { style: { display: 'flex', alignItems: 'center', gap: 9, flexWrap: 'wrap' } },
          e('span', { className: 'display', style: { fontSize: compact ? 17 : 19, fontWeight: 600, color: 'var(--ink)' } }, title),
          badge ? e(Badge, { kind: badge }, badgeLabel) : null,
        ),
        sub ? e('div', { className: 'muted', style: { fontSize: 13.5, marginTop: 3 } }, sub) : null,
      ),
      right != null ? e('div', { style: { flexShrink: 0 } }, right) : null,
      e('span', {
        style: {
          flexShrink: 0, width: 24, height: 24, borderRadius: 999,
          border: '2px solid ' + (selected ? 'var(--blue)' : 'var(--line-2)'),
          background: selected ? 'var(--blue)' : '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff',
        },
      }, selected ? e(Icon, { name: 'check', size: 15, strokeWidth: 3 }) : null),
    );
  }
  window.OptionTile = OptionTile;

  /* ---------- Segmented control ---------- */
  function Segmented({ value, onChange, options }) {
    return e('div', {
      style: { display: 'inline-flex', background: 'var(--field)', border: '1px solid var(--line)', borderRadius: 999, padding: 4, gap: 4 },
    }, options.map(o =>
      e('button', {
        key: o.value, type: 'button', onClick: () => onChange(o.value),
        className: 'display',
        style: {
          border: 'none', borderRadius: 999, padding: '8px 18px', fontSize: 15, fontWeight: 600,
          background: value === o.value ? 'var(--teal)' : 'transparent',
          color: value === o.value ? '#fff' : 'var(--ink-2)',
          boxShadow: value === o.value ? '0 2px 6px rgba(0,95,122,.3)' : 'none',
          transition: 'all .15s',
        },
      }, o.label),
    ));
  }
  window.Segmented = Segmented;

  /* ---------- Field ---------- */
  function Field({ label, hint, children, style }) {
    return e('label', { style: Object.assign({ display: 'block' }, style) },
      label ? e('div', { style: { fontWeight: 700, fontSize: 13.5, color: 'var(--ink-2)', marginBottom: 7, letterSpacing: '.01em' } }, label) : null,
      children,
      hint ? e('div', { className: 'muted', style: { fontSize: 12.5, marginTop: 6 } }, hint) : null,
    );
  }
  window.Field = Field;

  function Input(props) {
    const { style, ...rest } = props;
    return e('input', Object.assign({
      style: Object.assign({
        width: '100%', padding: '13px 15px', borderRadius: 'var(--r)', border: '1.5px solid var(--line-2)',
        background: '#fff', fontSize: 15.5, color: 'var(--ink)', outline: 'none',
        transition: 'border-color .15s, box-shadow .15s',
      }, style),
      onFocus: (ev) => { ev.target.style.borderColor = 'var(--blue)'; ev.target.style.boxShadow = 'var(--ring)'; },
      onBlur: (ev) => { ev.target.style.borderColor = 'var(--line-2)'; ev.target.style.boxShadow = 'none'; },
    }, rest));
  }
  window.Input = Input;

  /* ---------- Modal ---------- */
  function Modal({ open, onClose, children, width = 520, title }) {
    if (!open) return null;
    return e('div', {
      onClick: onClose,
      style: {
        position: 'fixed', inset: 0, zIndex: 200, background: 'rgba(1,30,40,.55)',
        display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20,
        animation: 'gw-fade .15s ease',
      },
    }, e('div', {
      onClick: (ev) => ev.stopPropagation(),
      className: 'card',
      style: { width: '100%', maxWidth: width, maxHeight: '88vh', overflow: 'auto', animation: 'gw-pop .2s ease', boxShadow: 'var(--sh-pop)' },
    },
      title ? e('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '20px 24px', borderBottom: '1px solid var(--line)' } },
        e('div', { className: 'display', style: { fontSize: 20, fontWeight: 600 } }, title),
        e('button', { onClick: onClose, style: { border: 'none', background: 'var(--field)', borderRadius: 999, width: 34, height: 34, display: 'grid', placeItems: 'center', color: 'var(--ink-2)' } }, e(Icon, { name: 'close', size: 18 })),
      ) : null,
      e('div', { style: { padding: title ? 24 : 0 } }, children),
    ));
  }
  window.Modal = Modal;

  /* ---------- Empty state with mascot ---------- */
  function EmptyState({ title, sub, action, size = 150 }) {
    return e('div', { style: { textAlign: 'center', padding: '48px 24px', maxWidth: 420, margin: '0 auto' } },
      e(Mascot, { size, style: { margin: '0 auto 14px' } }),
      e('div', { className: 'display', style: { fontSize: 23, fontWeight: 600, marginBottom: 6 } }, title),
      sub ? e('div', { className: 'muted', style: { fontSize: 15, marginBottom: 18 } }, sub) : null,
      action || null,
    );
  }
  window.EmptyState = EmptyState;

  /* ---------- Section header ---------- */
  function SectionTitle({ eyebrow, title, sub, right }) {
    return e('div', { style: { display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginBottom: 22, flexWrap: 'wrap' } },
      e('div', null,
        eyebrow ? e('div', { className: 'eyebrow', style: { marginBottom: 6 } }, eyebrow) : null,
        e('h1', { className: 'display', style: { fontSize: 30, fontWeight: 600, margin: 0, lineHeight: 1.05 } }, title),
        sub ? e('div', { className: 'muted', style: { fontSize: 15, marginTop: 7, maxWidth: 620 } }, sub) : null,
      ),
      right || null,
    );
  }
  window.SectionTitle = SectionTitle;

  /* ---------- Stepper rail ---------- */
  function StepRail({ steps, current, maxReached, onJump }) {
    return e('div', { style: { display: 'flex', flexDirection: 'column', gap: 2 } },
      steps.map((s, i) => {
        const done = i < current, active = i === current, reachable = i <= maxReached;
        return e('button', {
          key: i, onClick: () => reachable && onJump(i), disabled: !reachable,
          style: {
            display: 'flex', alignItems: 'center', gap: 13, textAlign: 'left', width: '100%',
            background: active ? 'rgba(0,177,237,.12)' : 'transparent', border: 'none',
            borderRadius: 12, padding: '11px 13px', cursor: reachable ? 'pointer' : 'default',
            opacity: reachable ? 1 : .4, transition: 'background .15s',
          },
        },
          e('span', {
            style: {
              flexShrink: 0, width: 30, height: 30, borderRadius: 999, display: 'grid', placeItems: 'center',
              fontFamily: 'var(--display)', fontWeight: 600, fontSize: 14,
              background: done ? 'var(--good)' : active ? 'var(--blue)' : 'rgba(255,255,255,.1)',
              color: (done || active) ? '#fff' : 'rgba(255,255,255,.65)',
              boxShadow: active ? '0 0 0 4px rgba(0,177,237,.25)' : 'none',
            },
          }, done ? e(Icon, { name: 'check', size: 16, strokeWidth: 3 }) : (i + 1)),
          e('span', {
            className: active ? 'display' : '',
            style: { fontSize: 14.5, fontWeight: active ? 600 : 500, color: active ? '#fff' : 'rgba(255,255,255,.75)' },
          }, s),
        );
      }),
    );
  }
  window.StepRail = StepRail;

  /* ---------- Pricing-rule override control ----------
     Lets admin set how one item prices vs the global target margin:
     Default (global %), a custom Margin %, or a × Cost multiplier.
     `value` is null | { mode:'margin'|'mult', value:number }. */
  function OverrideControl(props) {
    const { value, onChange, settings } = props;
    const mode = value ? value.mode : '';
    const targetPct = Math.round(((settings && settings.targetMargin) || 0.70) * 100);
    const setMode = (m) => {
      if (!m) return onChange(null);
      if (m === 'margin') onChange({ mode: 'margin', value: (value && value.mode === 'margin') ? value.value : 0.70 });
      else onChange({ mode: 'mult', value: (value && value.mode === 'mult') ? value.value : 2 });
    };
    const selSt = { padding: '8px 10px', borderRadius: 8, border: '1.5px solid var(--line-2)', fontSize: 13.5, fontWeight: 600, background: '#fff', outline: 'none', cursor: 'pointer', color: 'var(--ink)' };
    const numWrap = { position: 'relative', width: 90 };
    const numSt = (padR) => ({ width: '100%', padding: '8px ' + (padR ? '24px' : '10px') + ' 8px 10px', borderRadius: 8, border: '1.5px solid var(--line-2)', fontWeight: 600, textAlign: 'right', outline: 'none', fontVariantNumeric: 'tabular-nums' });
    const sfx = (t) => e('span', { style: { position: 'absolute', right: 9, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)', fontWeight: 700, pointerEvents: 'none' } }, t);
    return e('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
      e('select', { value: mode, onChange: ev => setMode(ev.target.value), style: selSt },
        e('option', { value: '' }, 'Default (' + targetPct + '%)'),
        e('option', { value: 'margin' }, 'Margin %'),
        e('option', { value: 'mult' }, '× Cost'),
      ),
      mode === 'margin' ? e('div', { style: numWrap },
        e('input', { type: 'number', value: Math.round((value.value || 0) * 100), onChange: ev => onChange({ mode: 'margin', value: Math.max(0, Math.min(95, Number(ev.target.value))) / 100 }), style: numSt(true) }), sfx('%'),
      ) : null,
      mode === 'mult' ? e('div', { style: numWrap },
        e('input', { type: 'number', step: 0.1, value: value.value, onChange: ev => onChange({ mode: 'mult', value: Math.max(0, Number(ev.target.value)) }), style: numSt(true) }), sfx('×'),
      ) : null,
    );
  }
  window.OverrideControl = OverrideControl;

  /* ---------- Signature pad (mouse + touch, tablet-friendly) ---------- */
  function SignaturePad({ onChange }) {
    const ref = React.useRef(null);
    const st = React.useRef({ drawing: false, last: null, dirty: false });
    React.useEffect(() => {
      const c = ref.current; if (!c) return;
      const fit = () => { const w = (c.parentNode && c.parentNode.clientWidth) || 320; c.width = w; c.height = 170; const ctx = c.getContext('2d'); ctx.lineWidth = 2.4; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.strokeStyle = '#0b2a36'; };
      fit();
      const pos = (ev) => { const r = c.getBoundingClientRect(); const t = ev.touches && ev.touches[0]; return { x: (t ? t.clientX : ev.clientX) - r.left, y: (t ? t.clientY : ev.clientY) - r.top }; };
      const start = (ev) => { ev.preventDefault(); st.current.drawing = true; st.current.last = pos(ev); };
      const move = (ev) => { if (!st.current.drawing) return; ev.preventDefault(); const ctx = c.getContext('2d'); const p = pos(ev); ctx.beginPath(); ctx.moveTo(st.current.last.x, st.current.last.y); ctx.lineTo(p.x, p.y); ctx.stroke(); st.current.last = p; st.current.dirty = true; };
      const end = () => { if (st.current.drawing) { st.current.drawing = false; if (st.current.dirty && onChange) onChange(c.toDataURL('image/png')); } };
      c.addEventListener('mousedown', start); c.addEventListener('mousemove', move); window.addEventListener('mouseup', end);
      c.addEventListener('touchstart', start, { passive: false }); c.addEventListener('touchmove', move, { passive: false }); c.addEventListener('touchend', end);
      window.addEventListener('resize', fit);
      c._gwClear = () => { c.getContext('2d').clearRect(0, 0, c.width, c.height); st.current.dirty = false; if (onChange) onChange(null); };
      return () => { c.removeEventListener('mousedown', start); c.removeEventListener('mousemove', move); window.removeEventListener('mouseup', end); c.removeEventListener('touchstart', start); c.removeEventListener('touchmove', move); c.removeEventListener('touchend', end); window.removeEventListener('resize', fit); };
    }, []);
    return e('div', null,
      e('canvas', { ref, style: { width: '100%', height: 170, border: '1.5px dashed var(--line-2)', borderRadius: 10, background: '#fff', touchAction: 'none', cursor: 'crosshair', display: 'block' } }),
      e('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 6 } },
        e('span', { className: 'muted', style: { fontSize: 12 } }, 'Sign above with finger or mouse'),
        e('button', { onClick: () => { const c = ref.current; if (c && c._gwClear) c._gwClear(); }, style: { border: 'none', background: 'transparent', color: 'var(--ink-3)', fontSize: 12.5, fontWeight: 600, cursor: 'pointer' } }, 'Clear'),
      ),
    );
  }
  window.SignaturePad = SignaturePad;

  /* ---------- Customer approval block (sign + accept) ---------- */
  function ApprovalBlock({ signature, onApprove, onClear }) {
    const [name, setName] = useState('');
    const [sig, setSig] = useState(null);
    const Btn = window.Btn, Field = window.Field, Input = window.Input;

    if (signature && signature.dataUrl) {
      const when = new Date(signature.signedAt || Date.now()).toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' });
      return e('div', { className: 'card', style: { padding: 20, border: '2px solid var(--good)', background: 'rgba(46,182,125,.05)' } },
        e('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 } },
          e('span', { style: { width: 26, height: 26, borderRadius: 999, background: 'var(--good)', color: '#fff', display: 'grid', placeItems: 'center' } }, e(Icon, { name: 'check', size: 15, strokeWidth: 3 })),
          e('div', { style: { fontWeight: 800, color: 'var(--good)', fontSize: 14 } }, 'Approved'),
        ),
        e('img', { src: signature.dataUrl, alt: 'Signature', style: { width: '100%', maxHeight: 120, objectFit: 'contain', borderBottom: '1px solid var(--line)', paddingBottom: 6 } }),
        e('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginTop: 8 } },
          e('div', null,
            e('div', { style: { fontWeight: 700, fontSize: 14.5 } }, signature.name || 'Customer'),
            e('div', { className: 'muted', style: { fontSize: 12 } }, 'Signed ' + when),
          ),
          onClear ? e('button', { className: 'no-print', onClick: onClear, style: { border: 'none', background: 'transparent', color: 'var(--ink-3)', fontSize: 12.5, fontWeight: 600, cursor: 'pointer' } }, 'Redo') : null,
        ),
      );
    }

    return e('div', { className: 'card no-print', style: { padding: 20 } },
      e('div', { className: 'eyebrow', style: { marginBottom: 10 } }, 'Customer approval'),
      e('div', { className: 'muted', style: { fontSize: 13, marginBottom: 12 } }, 'Once everything is agreed, have the customer sign to approve this estimate.'),
      e(Field, { label: 'Customer name', style: { marginBottom: 12 } }, e(Input, { value: name, onChange: ev => setName(ev.target.value), placeholder: 'Full name' })),
      e(window.SignaturePad, { onChange: setSig }),
      e(Btn, { variant: 'primary', block: true, icon: 'check', disabled: !(name && sig), style: { marginTop: 12 }, onClick: () => onApprove({ name: name, dataUrl: sig, signedAt: new Date().toISOString() }) }, 'Approve & accept estimate'),
    );
  }
  window.ApprovalBlock = ApprovalBlock;

  /* ---------- localStorage helper ---------- */
  window.gwStore = {
    get(k, def) { try { const v = localStorage.getItem('gw_' + k); return v == null ? def : JSON.parse(v); } catch (e) { return def; } },
    set(k, v) { try { localStorage.setItem('gw_' + k, JSON.stringify(v)); } catch (e) {} },
  };
})();
