// ui.jsx — shared presentational primitives. Exports to window.
const { useState, useEffect, useRef } = React;

const cloneValue = (value) => JSON.parse(JSON.stringify(value));

function readStored(key, fallback) {
  try {
    const raw = localStorage.getItem(key);
    return raw ? JSON.parse(raw) : cloneValue(fallback);
  } catch (e) {
    return cloneValue(fallback);
  }
}

function writeStored(key, value) {
  try {
    localStorage.setItem(key, JSON.stringify(value));
    window.dispatchEvent(new CustomEvent('ac-store', { detail: { key } }));
  } catch (e) {}
}

function readImageFile(file, onLoad) {
  const reader = new FileReader();
  reader.onload = () => {
    if (typeof reader.result === 'string') onLoad(reader.result);
  };
  reader.readAsDataURL(file);
}

function patchStored(key, fallback, fn) {
  const next = fn(readStored(key, fallback));
  writeStored(key, next);
  return next;
}

function useStoredState(key, fallback) {
  const fallbackValue = () => (typeof fallback === 'function' ? fallback() : fallback);
  const [value, setRawValue] = useState(() => readStored(key, fallbackValue()));
  const setValue = (nextValue) => {
    setRawValue((current) => {
      const next = typeof nextValue === 'function' ? nextValue(current) : nextValue;
      writeStored(key, next);
      return next;
    });
  };
  useEffect(() => {
    const sync = (event) => {
      if (!event.detail || event.detail.key === key) {
        setRawValue(readStored(key, fallbackValue()));
      }
    };
    window.addEventListener('storage', sync);
    window.addEventListener('ac-store', sync);
    return () => {
      window.removeEventListener('storage', sync);
      window.removeEventListener('ac-store', sync);
    };
  }, [key]);
  return [value, setValue];
}

function Badge({ kind = 'neutral', pip, children }) {
  return (
    <span className={`badge ${kind}`}>
      {pip && <span className="pip" />}
      {children}
    </span>
  );
}

function StatusBadge({ status }) {
  const m = WO_STATUS[status] || { label: status, badge: 'neutral' };
  return <Badge kind={m.badge} pip>{tx(m.label)}</Badge>;
}

function PayBadge({ method, size }) {
  const cash = method === 'cash';
  return (
    <span className={`badge ${cash ? 'cash' : 'neutral'}`}>
      {React.createElement(Icon[cash ? 'cash' : 'card'], { size: 13, stroke: 2.2 })}
      {cash ? tx('Cash') : tx('Card')}
    </span>
  );
}

function Avatar({ name, initials, size = 30, accent, photo }) {
  const ini = initials || (name || '?').split(' ').map((w) => w[0]).slice(0, 2).join('');
  return (
    <span className="avatar" style={{ width: size, height: size, fontSize: size * 0.4,
      background: accent ? 'var(--accent)' : undefined, color: accent ? 'var(--accent-fg)' : undefined }}>
      {photo ? <img src={photo} alt="" /> : ini}
    </span>
  );
}

function VehicleCell({ v, sub }) {
  return (
    <div className="veh">
      <div className="veh-ic">{React.createElement(Icon.car, { size: 19 })}</div>
      <div style={{ minWidth: 0, flex: 1 }}>
        <b>{v.make} {v.model}</b>
        <div className="row" style={{ gap: 7, marginTop: 2 }}>
          <span className="plate">{v.plate}</span>
          <span className="veh" style={{ fontSize: 12, color: 'var(--text-3)' }}>{sub || `${v.year}`}</span>
        </div>
      </div>
    </div>
  );
}

function Pipeline({ status, compact }) {
  const idx = PIPELINE.indexOf(status);
  const steps = compact ? PIPELINE : PIPELINE;
  return (
    <div className="pipe">
      {steps.map((s, i) => {
        const done = i < idx, current = i === idx;
        const cls = done ? 'done' : current ? 'current' : '';
        return (
          <React.Fragment key={s}>
            <div className={`pipe-step ${cls}`}>
              <div className="pipe-node">
                <span className="tick">
                  {done ? React.createElement(Icon.check, { size: 11, stroke: 3 })
                        : <span style={{ fontSize: 10, fontWeight: 700 }}>{i + 1}</span>}
                </span>
                {WO_STATUS[s].label && tx(WO_STATUS[s].label)}
              </div>
            </div>
            {i < steps.length - 1 && <span className="pipe-line" style={done ? { background: 'var(--success)' } : null} />}
          </React.Fragment>
        );
      })}
    </div>
  );
}

function Stat({ label, icon, value, unit, delta, deltaDir = 'up', accent }) {
  return (
    <div className="stat">
      <div className="lbl">
        {icon && React.createElement(Icon[icon], { size: 14 })}
        {label}
      </div>
      <div className="val" style={accent ? { color: 'var(--accent)' } : null}>
        {value}{unit && <small> {unit}</small>}
      </div>
      {delta && (
        <div className={`delta ${deltaDir}`}>
          {deltaDir === 'up' && React.createElement(Icon.arrowUp, { size: 13 })}
          {delta}
        </div>
      )}
    </div>
  );
}

function Modal({ title, sub, onClose, children, footer, wide }) {
  useEffect(() => {
    const h = (e) => e.key === 'Escape' && onClose();
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, []);
  return (
    <div className="scrim" onMouseDown={onClose}>
      <div className={`modal ${wide ? 'wide' : ''}`} onMouseDown={(e) => e.stopPropagation()}>
        <div className="modal-hd">
          <div style={{ flex: 1 }}>
            <h3>{title}</h3>
            {sub && <div className="muted tiny" style={{ marginTop: 3 }}>{sub}</div>}
          </div>
          <button className="icon-btn" onClick={onClose}>{React.createElement(Icon.x, { size: 17 })}</button>
        </div>
        <div className="modal-bd">{children}</div>
        {footer && <div className="modal-ft">{footer}</div>}
      </div>
    </div>
  );
}

function Switch({ on, onClick }) {
  return <div className={`switch ${on ? 'on' : ''}`} onClick={onClick}><i /></div>;
}

function Seg({ value, options, onChange }) {
  return (
    <div className="seg">
      {options.map((o) => (
        <button key={o.value} className={value === o.value ? 'on' : ''} onClick={() => onChange(o.value)}>
          {o.icon && React.createElement(Icon[o.icon], { size: 14 })}
          {o.label}
        </button>
      ))}
    </div>
  );
}

// Toast system via a tiny event bus
const toastBus = { fns: [] };
function toast(msg, icon = 'check') { toastBus.fns.forEach((f) => f(msg, icon)); }
function ToastHost() {
  const [items, setItems] = useState([]);
  useEffect(() => {
    const fn = (msg, icon) => {
      const id = Math.random();
      setItems((x) => [...x, { id, msg, icon }]);
      setTimeout(() => setItems((x) => x.filter((i) => i.id !== id)), 2600);
    };
    toastBus.fns.push(fn);
    return () => { toastBus.fns = toastBus.fns.filter((f) => f !== fn); };
  }, []);
  return (
    <div className="toast-wrap">
      {items.map((i) => (
        <div className="toast" key={i.id}>
          <span className="ti">{React.createElement(Icon[i.icon] || Icon.check, { size: 16, stroke: 2.4 })}</span>
          {i.msg}
        </div>
      ))}
    </div>
  );
}

// thumbnail placeholder (striped) with optional required/missing state
function Thumb({ label, req, missing }) {
  if (req) {
    return (
      <div className={`thumb req ${missing ? 'missing' : ''}`} title={label}>
        {React.createElement(Icon[missing ? 'alert' : 'camera'], { size: 14 })}
        <span style={{ marginTop: 2 }}>{label}</span>
      </div>
    );
  }
  return (
    <div className="thumb" title={label}>
      {React.createElement(Icon.camera, { size: 15 })}
    </div>
  );
}

Object.assign(window, {
  Badge, StatusBadge, PayBadge, Avatar, VehicleCell, Pipeline, Stat,
  Modal, Switch, Seg, toast, ToastHost, Thumb,
  readStored, writeStored, patchStored, readImageFile, useStoredState,
});
