// =================================================================
// ui-ext.jsx — Additional reusable components beyond ui.jsx primitives.
//   - StatCard:        label + big value + delta pill (Dashboard, Cost Analytics)
//   - BarChart:        compact bar chart for time-series spend
//   - DangerZone:      destructive-action panel with optional type-to-confirm
//   - Toolbar:         search + primary button row above tables
//   - SegmentedControl single-select pill-toggle (replaces ad-hoc segmented buttons)
//   - EmptyState:      icon + title + description + CTA for empty lists/tables
//   - Tabs:            controlled tab bar
//   - Drawer:          right-side slide-over panel
//   - Tooltip:         hover/focus tooltip wrapper
//   - ErrorBoundary:   React error boundary with reset button
// =================================================================

// ---------- StatCard ----------
const StatCard = ({ label, value, delta, deltaTone = "neutral", sub, icon, onClick }) => (
  <button className="hx-statc" onClick={onClick} disabled={!onClick} type="button">
    <div className="hx-statc-head">
      <span className="hx-statc-label">{label}</span>
      {icon && <span className="hx-statc-icon">{icon}</span>}
    </div>
    <div className="hx-statc-value">{value}</div>
    <div className="hx-statc-foot">
      {delta != null && <Pill tone={deltaTone}>{delta}</Pill>}
      {sub && <span className="hx-statc-sub">{sub}</span>}
    </div>
    <style>{`
      .hx-statc {
        text-align: left;
        background: var(--panel); border: 1px solid var(--line);
        border-radius: var(--r-md); padding: var(--pad);
        box-shadow: var(--shadow-1);
        font: inherit; color: var(--ink);
        cursor: ${onClick ? "pointer" : "default"};
        transition: border-color .12s, transform .04s;
        width: 100%;
      }
      .hx-statc:not(:disabled):hover { border-color: color-mix(in oklab, var(--ink) 30%, transparent); }
      .hx-statc:not(:disabled):active { transform: translateY(.5px); }
      .hx-statc-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
      .hx-statc-label { color: var(--muted); font-size: 13px; font-weight: 500; }
      .hx-statc-icon { color: var(--muted-2); display: inline-flex; }
      .hx-statc-value { font-size: 28px; font-weight: 600; letter-spacing: -.02em; margin-top: 8px; font-feature-settings: "tnum"; line-height: 1.1; }
      .hx-statc-foot { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
      .hx-statc-sub { color: var(--muted); font-size: 12px; }
    `}</style>
  </button>
);

// ---------- BarChart ----------
const BarChart = ({ data, height = 180, showAxis = true, axisLabels, formatValue }) => {
  const max = Math.max(...data, 1);
  const fmtVal = formatValue || ((v) => v.toFixed(2));
  return (
    <div className="hx-chart">
      <div className="hx-chart-bars" style={{ height }}>
        {data.map((v, i) => (
          <div key={i} className="hx-chart-bar" style={{ height: `${(v / max) * 100}%` }} title={fmtVal(v)}/>
        ))}
      </div>
      {showAxis && (
        <div className="hx-chart-axis">
          {(axisLabels || [`${data.length}d ago`, "Today"]).map((l, i) => <span key={i}>{l}</span>)}
        </div>
      )}
      <style>{`
        .hx-chart {}
        .hx-chart-bars { display: flex; align-items: flex-end; gap: 3px; }
        .hx-chart-bar {
          flex: 1; min-height: 4px;
          background: linear-gradient(to top, var(--accent), color-mix(in oklab, var(--accent) 55%, transparent));
          border-radius: 3px 3px 0 0;
          transition: opacity .12s;
        }
        .hx-chart-bar:hover { opacity: .8; }
        .hx-chart-axis { display: flex; justify-content: space-between; margin-top: 8px; color: var(--muted); font-size: 11.5px; }
      `}</style>
    </div>
  );
};

// ---------- DangerZone ----------
const DangerZone = ({ title = "Danger zone", description, actionLabel = "Delete", confirmPhrase, onConfirm }) => {
  const [expanded, setExpanded] = React.useState(false);
  const [phrase, setPhrase] = React.useState("");
  const needsTyping = !!confirmPhrase;
  const canDelete = needsTyping ? phrase === confirmPhrase : true;

  React.useEffect(() => { if (!expanded) setPhrase(""); }, [expanded]);

  return (
    <div className="hx-dz">
      <div className="hx-dz-head">
        <div>
          <div className="hx-dz-title">{title}</div>
          {description && <div className="hx-dz-desc">{description}</div>}
        </div>
        {!expanded && <Btn kind="danger" onClick={() => setExpanded(true)}>{actionLabel}</Btn>}
      </div>
      {expanded && (
        <div className="hx-dz-confirm">
          {needsTyping && (
            <>
              <p style={{ margin: "0 0 10px", fontSize: 13.5 }}>
                Type <code className="hx-inline-code">{confirmPhrase}</code> to confirm.
              </p>
              <Input value={phrase} onChange={(e) => setPhrase(e.target.value)} placeholder={confirmPhrase}/>
            </>
          )}
          <div className="hx-dz-actions">
            <Btn kind="secondary" onClick={() => setExpanded(false)}>Cancel</Btn>
            <Btn kind="danger" disabled={!canDelete} onClick={onConfirm}>
              {needsTyping ? `I understand, ${actionLabel.toLowerCase()}` : actionLabel}
            </Btn>
          </div>
        </div>
      )}
      <style>{`
        .hx-dz {
          border: 1px solid color-mix(in oklab, var(--bad) 28%, var(--line));
          border-radius: 12px; padding: 16px;
          background: color-mix(in oklab, var(--bad) 4%, var(--panel));
        }
        .hx-dz-head { display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap; }
        .hx-dz-title { font-weight: 600; color: var(--bad); }
        .hx-dz-desc { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
        .hx-dz-confirm { margin-top: 14px; padding-top: 14px; border-top: 1px dashed color-mix(in oklab, var(--bad) 25%, var(--line)); }
        .hx-dz-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
        .hx-inline-code { background: var(--panel-2); border: 1px solid var(--line); border-radius: 4px; padding: 1px 6px; font-family: var(--mono); font-size: 12.5px; }
      `}</style>
    </div>
  );
};

// ---------- Toolbar (search + actions) ----------
const Toolbar = ({ search, searchPlaceholder, onSearchChange, actions, children }) => (
  <div className="hx-toolbar-c">
    {actions && <div className="hx-toolbar-actions">{actions}</div>}
    {onSearchChange !== undefined && (
      <Input prefix={<IconSearch size={14}/>} placeholder={searchPlaceholder || "Search"}
        value={search || ""} onChange={(e) => onSearchChange(e.target.value)} style={{ minWidth: 240, maxWidth: 320, flex: 1 }}/>
    )}
    {children}
    <style>{`
      .hx-toolbar-c { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
      .hx-toolbar-actions { display: flex; gap: 8px; flex-wrap: wrap; }
      @media (max-width: 640px) {
        .hx-toolbar-c > .hx-input-wrap { flex-basis: 100%; max-width: 100%; }
      }
    `}</style>
  </div>
);

// ---------- SegmentedControl ----------
const SegmentedControl = ({ value, onChange, options, size = "md" }) => (
  <div className={`hx-segc hx-segc-${size}`}>
    {options.map((o) => {
      const v = typeof o === "object" ? o.value : o;
      const l = typeof o === "object" ? o.label : o;
      return (
        <button key={v} type="button" onClick={() => onChange(v)} className={value === v ? "on" : ""}>{l}</button>
      );
    })}
    <style>{`
      .hx-segc { display: inline-flex; background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px; padding: 3px; gap: 2px; }
      .hx-segc button {
        background: transparent; border: none; cursor: pointer; font: inherit;
        color: var(--ink-2); border-radius: 7px;
        transition: background .12s, color .12s;
      }
      .hx-segc-md button { padding: 7px 14px; font-size: 13px; }
      .hx-segc-sm button { padding: 5px 10px; font-size: 12.5px; }
      .hx-segc button:hover { color: var(--ink); }
      .hx-segc button.on { background: var(--panel); color: var(--ink); font-weight: 500; box-shadow: 0 1px 2px rgba(0,0,0,.06); }
    `}</style>
  </div>
);

// ---------- EmptyState ----------
const EmptyState = ({ icon, title, description, action }) => (
  <div className="hx-empty">
    {icon && <div className="hx-empty-icon">{icon}</div>}
    <div className="hx-empty-title">{title}</div>
    {description && <div className="hx-empty-desc">{description}</div>}
    {action && <div className="hx-empty-action">{action}</div>}
    <style>{`
      .hx-empty {
        display: flex; flex-direction: column; align-items: center; gap: 8px;
        padding: 56px 20px; text-align: center;
      }
      .hx-empty-icon { color: var(--muted-2); margin-bottom: 4px; }
      .hx-empty-title { font-weight: 600; font-size: 15px; }
      .hx-empty-desc { color: var(--muted); font-size: 13px; max-width: 380px; line-height: 1.55; }
      .hx-empty-action { margin-top: 8px; }
    `}</style>
  </div>
);

// ---------- Tabs ----------
const Tabs = ({ value, onChange, items }) => (
  <div className="hx-tabs">
    <div className="hx-tabs-list" role="tablist">
      {items.map((it) => (
        <button key={it.value} role="tab" aria-selected={value === it.value}
          className={`hx-tab ${value === it.value ? "on" : ""}`}
          onClick={() => onChange(it.value)}>
          {it.label}
          {it.count != null && <span className="hx-tab-count">{it.count}</span>}
        </button>
      ))}
    </div>
    <style>{`
      .hx-tabs { border-bottom: 1px solid var(--line); }
      .hx-tabs-list { display: flex; gap: 0; overflow-x: auto; }
      .hx-tab {
        background: transparent; border: none; cursor: pointer; font: inherit;
        padding: 12px 16px; color: var(--muted);
        font-size: 13.5px; font-weight: 500;
        border-bottom: 2px solid transparent; margin-bottom: -1px;
        display: inline-flex; align-items: center; gap: 8px;
        white-space: nowrap;
        transition: color .12s, border-color .12s;
      }
      .hx-tab:hover { color: var(--ink-2); }
      .hx-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
      .hx-tab-count { background: var(--line-2); color: var(--ink-2); padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 500; }
      .hx-tab.on .hx-tab-count { background: var(--accent-soft); color: var(--accent-strong); }
    `}</style>
  </div>
);

// ---------- Drawer (right-side slide-over) ----------
const Drawer = ({ open, onClose, title, children, footer, width = 480 }) => {
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && onClose();
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="hx-drawer-overlay" onClick={onClose}>
      <div className="hx-drawer" style={{ width }} onClick={(e) => e.stopPropagation()}>
        <div className="hx-drawer-head">
          <div className="hx-drawer-title">{title}</div>
          <button className="hx-modal-x" onClick={onClose} aria-label="Close"><IconClose size={18}/></button>
        </div>
        <div className="hx-drawer-body">{children}</div>
        {footer && <div className="hx-drawer-foot">{footer}</div>}
      </div>
      <style>{`
        .hx-drawer-overlay { position: fixed; inset: 0; background: rgba(13,17,28,.45); z-index: 80; animation: hxfade .15s ease both; }
        .hx-drawer { position: absolute; top: 0; right: 0; bottom: 0; max-width: 100%; background: var(--panel); box-shadow: var(--shadow-modal); display: flex; flex-direction: column; animation: hxslide .22s cubic-bezier(.2,.9,.3,1.05) both; }
        @keyframes hxslide { from { transform: translateX(20px); opacity: 0; } to { transform: none; opacity: 1; } }
        .hx-drawer-head { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--line-2); }
        .hx-drawer-title { font-size: 16px; font-weight: 600; }
        .hx-drawer-body { padding: 20px; overflow-y: auto; flex: 1; }
        .hx-drawer-foot { padding: 14px 20px; border-top: 1px solid var(--line-2); display: flex; justify-content: flex-end; gap: 8px; background: var(--panel-2); }
        @media (max-width: 640px) {
          .hx-drawer { width: 100% !important; }
        }
      `}</style>
    </div>
  );
};

// ---------- Tooltip ----------
const Tooltip = ({ children, content, side = "top" }) => {
  const [show, setShow] = React.useState(false);
  const ref = React.useRef();
  return (
    <span className="hx-tt-wrap" ref={ref}
      onMouseEnter={() => setShow(true)} onMouseLeave={() => setShow(false)}
      onFocus={() => setShow(true)} onBlur={() => setShow(false)}>
      {children}
      {show && <span className={`hx-tt hx-tt-${side}`}>{content}</span>}
      <style>{`
        .hx-tt-wrap { position: relative; display: inline-flex; }
        .hx-tt {
          position: absolute; z-index: 70; pointer-events: none;
          background: #0b0d12; color: white;
          padding: 5px 9px; border-radius: 6px;
          font-size: 12px; font-weight: 500; white-space: nowrap;
          box-shadow: 0 4px 16px rgba(0,0,0,.18);
          animation: hxttin .12s ease both;
        }
        @keyframes hxttin { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: none; } }
        .hx-tt-top    { bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); }
        .hx-tt-bottom { top: calc(100% + 6px);    left: 50%; transform: translateX(-50%); }
        .hx-tt-left   { right: calc(100% + 6px);  top: 50%; transform: translateY(-50%); }
        .hx-tt-right  { left: calc(100% + 6px);   top: 50%; transform: translateY(-50%); }
      `}</style>
    </span>
  );
};

// ---------- ErrorBoundary ----------
class ErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = { hasError: false, error: null }; }
  static getDerivedStateFromError(error) { return { hasError: true, error }; }
  componentDidCatch(error, info) { console.error("App crashed:", error, info); }
  reset = () => this.setState({ hasError: false, error: null });
  render() {
    if (this.state.hasError) {
      return (
        <div style={{ padding: 40, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 14, minHeight: "60vh", justifyContent: "center" }}>
          <div style={{ width: 56, height: 56, borderRadius: 14, background: "var(--warn-soft)", color: "var(--warn)", display: "inline-flex", alignItems: "center", justifyContent: "center", fontSize: 24 }}>!</div>
          <div style={{ fontSize: 18, fontWeight: 600 }}>Something went wrong</div>
          <div style={{ color: "var(--muted)", fontSize: 13.5, maxWidth: 460, lineHeight: 1.55 }}>
            The page hit an unexpected error. Try going back to the dashboard, or reload to start fresh.
          </div>
          {this.state.error && (
            <pre style={{ background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "10px 12px", fontSize: 12, fontFamily: "var(--mono)", maxWidth: 600, overflow: "auto", textAlign: "left", color: "var(--muted)" }}>
              {String(this.state.error?.message || this.state.error)}
            </pre>
          )}
          <div style={{ display: "flex", gap: 8 }}>
            <Btn kind="secondary" onClick={() => { window.location.hash = "#/dashboard"; this.reset(); }}>Back to Dashboard</Btn>
            <Btn kind="primary" onClick={() => window.location.reload()}>Reload page</Btn>
          </div>
        </div>
      );
    }
    return this.props.children;
  }
}

Object.assign(window, {
  StatCard, BarChart, DangerZone, Toolbar, SegmentedControl,
  EmptyState, Tabs, Drawer, Tooltip, ErrorBoundary,
});
