// Himma shared primitives — wordmark, card, donut, sparkline, pill

// Official UAE Dirham currency symbol — drop-in replacement for the "AED" prefix.
// Inherits text color via currentColor; size scales relative to its em-height so it
// sits cleanly next to numbers at any text size.
function Dh({ size = '0.95em', color = 'currentColor', style = {} }) {
  // SVG has aspect ratio 344.84 : 299.91 ≈ 1.15 : 1 (wider than tall).
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 344.84 299.91"
      style={{
        display: 'inline-block',
        verticalAlign: '-0.12em',
        flexShrink: 0,
        ...style,
      }}
      aria-label="AED"
    >
      <path
        fill={color}
        d="M342.14,140.96l2.7,2.54v-7.72c0-17-11.92-30.84-26.56-30.84h-23.41C278.49,36.7,222.69,0,139.68,0c-52.86,0-59.65,0-109.71,0,0,0,15.03,12.63,15.03,52.4v52.58h-27.68c-5.38,0-10.43-2.08-14.61-6.01l-2.7-2.54v7.72c0,17.01,11.92,30.84,26.56,30.84h18.44s0,29.99,0,29.99h-27.68c-5.38,0-10.43-2.07-14.61-6.01l-2.7-2.54v7.71c0,17,11.92,30.82,26.56,30.82h18.44s0,54.89,0,54.89c0,38.65-15.03,50.06-15.03,50.06h109.71c85.62,0,139.64-36.96,155.38-104.98h32.46c5.38,0,10.43,2.07,14.61,6l2.7,2.54v-7.71c0-17-11.92-30.83-26.56-30.83h-18.9c.32-4.88.49-9.87.49-15s-.18-10.11-.51-14.99h28.17c5.37,0,10.43,2.07,14.61,6.01ZM89.96,15.01h45.86c61.7,0,97.44,27.33,108.1,89.94l-153.96.02V15.01ZM136.21,284.93h-46.26v-89.98l153.87-.02c-9.97,56.66-42.07,88.38-107.61,90ZM247.34,149.96c0,5.13-.11,10.13-.34,14.99l-157.04.02v-29.99l157.05-.02c.22,4.84.33,9.83.33,15Z"
      />
    </svg>
  );
}

// Renders a string and replaces every "AED " (with trailing space) with the Dirham
// symbol. Use for prose where currency values are embedded (notifications, articles,
// etc.). Pass-through for non-strings so callers can wrap freely.
function dhText(text) {
  if (typeof text !== 'string') return text;
  if (!text.includes('AED ')) return text;
  const parts = text.split('AED ');
  const out = [parts[0]];
  for (let i = 1; i < parts.length; i++) {
    out.push(
      <React.Fragment key={i}><Dh /> {parts[i]}</React.Fragment>
    );
  }
  return out;
}

// Wordmark: "himma" in serif + small Arabic "هِمّة" after it
function Wordmark({ color = '#F5F1EA', accent = '#D4B27A', showArabic = true, size = 22 }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'baseline', gap: 6, color, fontFamily: FONTS.display, fontSize: size, fontWeight: 400, letterSpacing: -0.5 }}>
      <span>himma<span style={{ color: accent }}>.</span></span>
      {showArabic && (
        <span style={{ fontFamily: FONTS.arabic, fontSize: size * 0.72, color: accent, opacity: 0.9 }} lang="ar" dir="rtl">هِمّة</span>
      )}
    </span>
  );
}

// Card primitive
function Card({ children, style = {}, theme, padded = true, bg }) {
  const t = theme;
  return (
    <div style={{
      background: bg || t.surface,
      border: `0.5px solid ${t.line}`,
      borderRadius: 20,
      padding: padded ? 18 : 0,
      ...style,
    }}>{children}</div>
  );
}

// Section label (small, uppercase, spaced)
function SectionLabel({ children, theme, style = {} }) {
  return (
    <div style={{
      fontFamily: FONTS.mono, fontSize: 10.5, letterSpacing: 1.5,
      textTransform: 'uppercase', color: theme.textMute, fontWeight: 500,
      ...style,
    }}>{children}</div>
  );
}

// Monospace number — large + small part
function BigNumber({ value, prefix, theme, accent, size = 44, decimals = 0 }) {
  const [whole, dec] = Number(value).toFixed(decimals).split('.');
  const whRendered = Number(whole).toLocaleString('en-AE');
  // The currency mark sits in front of the number; defaults to the Dirham symbol.
  const Mark = prefix
    ? <span style={{ fontSize: size * 0.45, color: accent, fontFamily: FONTS.mono, fontWeight: 500, letterSpacing: 0.5, transform: 'translateY(-4px)' }}>{prefix}</span>
    : <Dh size={size * 0.62} color={accent} style={{ transform: 'translateY(-2px)' }}/>;
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, fontFamily: FONTS.display, color: theme.text, letterSpacing: -1 }}>
      {Mark}
      <span style={{ fontSize: size, fontWeight: 400, fontVariantNumeric: 'tabular-nums' }}>{whRendered}</span>
      {decimals > 0 && <span style={{ fontSize: size * 0.5, color: theme.textDim }}>.{dec}</span>}
    </div>
  );
}

// Donut chart — SVG, segments with gaps
function Donut({ segments, size = 130, stroke = 14, theme, centerLabel, centerValue }) {
  const total = segments.reduce((s, x) => s + x.value, 0);
  const r = (size - stroke) / 2;
  const cx = size / 2, cy = size / 2;
  const circ = 2 * Math.PI * r;
  let offset = 0;
  const gap = 2; // px of circumference

  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={theme.line2} strokeWidth={0.5} />
        {segments.map((seg, i) => {
          const frac = seg.value / total;
          const len = Math.max(0, frac * circ - gap);
          const dashArray = `${len} ${circ - len}`;
          const dashOffset = -offset;
          offset += len + gap;
          return (
            <circle key={seg.key || i}
              cx={cx} cy={cy} r={r} fill="none"
              stroke={seg.color} strokeWidth={stroke}
              strokeDasharray={dashArray}
              strokeDashoffset={dashOffset}
              strokeLinecap="butt"
            />
          );
        })}
      </svg>
      {(centerLabel || centerValue) && (
        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', gap: 2 }}>
          {centerLabel && <div style={{ fontFamily: FONTS.mono, fontSize: 9, letterSpacing: 1.2, textTransform: 'uppercase', color: theme.textMute }}>{centerLabel}</div>}
          {centerValue && <div style={{ fontFamily: FONTS.display, fontSize: 18, color: theme.text, fontVariantNumeric: 'tabular-nums' }}>{centerValue}</div>}
        </div>
      )}
    </div>
  );
}

// Sparkline. Pass `responsive` to stretch to the parent's width via viewBox.
function Spark({ data, width = 100, height = 28, color = '#D4B27A', fill = true, dot = true, responsive = false }) {
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * width;
    const y = height - ((v - min) / range) * (height - 4) - 2;
    return [x, y];
  });
  const path = 'M ' + pts.map(p => p.join(' ')).join(' L ');
  const area = path + ` L ${width} ${height} L 0 ${height} Z`;
  const svgWidth = responsive ? '100%' : width;
  return (
    <svg width={svgWidth} height={height} viewBox={`0 0 ${width} ${height}`}
      preserveAspectRatio={responsive ? 'none' : 'xMidYMid meet'}
      style={{ display: 'block', overflow: 'visible' }}>
      {fill && <path d={area} fill={color} opacity={0.12} vectorEffect={responsive ? 'non-scaling-stroke' : undefined}/>}
      <path d={path} fill="none" stroke={color} strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" vectorEffect={responsive ? 'non-scaling-stroke' : undefined}/>
      {dot && <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r={2.5} fill={color} />}
    </svg>
  );
}

// Single-segment progress ring (for compact goal % glyphs)
function ProgressRing({ pct, size = 48, stroke = 4, color, track, label, sublabel }) {
  const r = (size - stroke) / 2;
  const cx = size / 2, cy = size / 2;
  const circ = 2 * Math.PI * r;
  const dash = circ * Math.max(0, Math.min(1, pct));
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={track} strokeWidth={stroke}/>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={color} strokeWidth={stroke}
          strokeDasharray={`${dash} ${circ - dash}`} strokeLinecap="round"/>
      </svg>
      {(label || sublabel) && (
        <div style={{
          position: 'absolute', inset: 0,
          display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
          fontFamily: FONTS.mono, lineHeight: 1, gap: 2,
        }}>
          {label && <div style={{ fontSize: size * 0.24, fontWeight: 600, fontVariantNumeric: 'tabular-nums', color }}>{label}</div>}
          {sublabel && <div style={{ fontSize: size * 0.16, color: 'inherit', opacity: 0.6 }}>{sublabel}</div>}
        </div>
      )}
    </div>
  );
}

// Horizontal bar (stacked)
function StackedBar({ segments, height = 6, theme }) {
  const total = segments.reduce((s, x) => s + x.value, 0);
  return (
    <div style={{ display: 'flex', gap: 2, height, width: '100%', borderRadius: height/2, overflow: 'hidden' }}>
      {segments.map((s, i) => (
        <div key={i} style={{ flex: s.value / total, background: s.color, borderRadius: 1 }} />
      ))}
    </div>
  );
}

// Chip / pill
function Chip({ children, active = false, onClick, theme, accent }) {
  return (
    <button onClick={onClick} style={{
      background: active ? theme.text : 'transparent',
      color: active ? theme.bg : theme.text,
      border: `0.5px solid ${active ? theme.text : theme.line2}`,
      borderRadius: 999,
      padding: '7px 13px',
      fontSize: 12.5,
      fontFamily: FONTS.ui,
      fontWeight: 500,
      cursor: 'pointer',
      whiteSpace: 'nowrap',
      transition: 'all 120ms',
    }}>{children}</button>
  );
}

// Delta indicator (+ or - with % )
function Delta({ value, pct, theme, size = 13, sign = true }) {
  const positive = value >= 0;
  const color = positive ? theme.positive : theme.negative;
  const arrow = positive ? '↑' : '↓';
  const display = pct !== undefined
    ? `${arrow} ${Math.abs(pct).toFixed(1)}%`
    : `${arrow} ${fmtAED(Math.abs(value))}`;
  return (
    <span style={{ color, fontFamily: FONTS.mono, fontSize: size, fontWeight: 500, fontVariantNumeric: 'tabular-nums' }}>{display}</span>
  );
}

// Tag (small, bordered)
function Tag({ children, color, theme, style = {} }) {
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      fontFamily: FONTS.mono, fontSize: 9.5, letterSpacing: 1.2, textTransform: 'uppercase',
      color: color || theme.textDim,
      padding: '3px 7px', borderRadius: 4,
      border: `0.5px solid ${theme.line2}`,
      ...style,
    }}>{children}</span>
  );
}

// Category icon bubble
function CategoryIcon({ category, theme, accent, size = 34 }) {
  const map = {
    'Food':        { icon: 'food',   tone: '#9BB08A' },
    'Transport':   { icon: 'car',    tone: '#7389A8' },
    'Shopping':    { icon: 'cart',   tone: '#C9B088' },
    'Bills':       { icon: 'bolt',   tone: '#D4A25A' },
    'Transfers':   { icon: 'arrowUR',tone: '#E8D4A8' },
    'Income':      { icon: 'download', tone: '#9BB08A' },
    'Investments': { icon: 'chart',  tone: '#D4B27A' },
    'tx-up':       { icon: 'download', tone: '#9BB08A' },
    'tx-down':     { icon: 'cart',   tone: '#C9B088' },
    'brok':        { icon: 'chart',  tone: '#D4B27A' },
  };
  const m = map[category] || { icon: 'wallet', tone: accent };
  const IconC = Ico[m.icon];
  return (
    <div style={{
      width: size, height: size, borderRadius: 10,
      background: theme.surface2,
      border: `0.5px solid ${theme.line}`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      flexShrink: 0,
      color: m.tone,
    }}>
      <IconC size={size * 0.5} sw={1.5} />
    </div>
  );
}

// Sankey — 2-stage flow (income sources → category buckets).
// Hand-rolled SVG; ribbons are cubic Bézier shapes. Assumes totalIn ≈ totalOut.
function Sankey({ data, width = 320, height = 200, theme }) {
  const inSeg  = data.in;
  const outSeg = data.out;
  const totalIn  = inSeg.reduce((s, x) => s + x.value, 0);
  const totalOut = outSeg.reduce((s, x) => s + x.value, 0);
  const total    = Math.max(totalIn, totalOut);

  const padY        = 6;
  const barW        = 6;
  const leftLabelW  = 76;
  const rightLabelW = 96;
  const leftBarX    = leftLabelW;
  const rightBarX   = width - rightLabelW - barW;
  const usableH     = height - padY * 2;
  const gapPx       = 3;

  const layout = (segs, totalVal) => {
    const totalGaps = (segs.length - 1) * gapPx;
    const valueH = usableH - totalGaps;
    let y = padY;
    return segs.map(s => {
      const h = (s.value / totalVal) * valueH;
      const r = { ...s, y, h };
      y += h + gapPx;
      return r;
    });
  };
  const left  = layout(inSeg,  total);
  const right = layout(outSeg, total);

  const flows = [];
  const lCursor = left.map(b => b.y);
  const rCursor = right.map(b => b.y);
  for (let i = 0; i < left.length; i++) {
    for (let j = 0; j < right.length; j++) {
      const hL = left[i].h  * (right[j].value / totalOut);
      const hR = right[j].h * (left[i].value  / totalIn);
      flows.push({ sy: lCursor[i], sh: hL, ty: rCursor[j], th: hR, color: left[i].color });
      lCursor[i] += hL;
      rCursor[j] += hR;
    }
  }

  const x1 = leftBarX + barW;
  const x2 = rightBarX;
  const cx = (x1 + x2) / 2;

  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: 'block' }}>
      {flows.map((f, idx) => {
        const top    = `M ${x1} ${f.sy} C ${cx} ${f.sy}, ${cx} ${f.ty}, ${x2} ${f.ty}`;
        const bottom = ` L ${x2} ${f.ty + f.th} C ${cx} ${f.ty + f.th}, ${cx} ${f.sy + f.sh}, ${x1} ${f.sy + f.sh} Z`;
        return <path key={idx} d={top + bottom} fill={f.color} opacity={0.28} />;
      })}
      {left.map((b, i) => (
        <rect key={'L'+i} x={leftBarX} y={b.y} width={barW} height={b.h} fill={b.color} rx={1.5}/>
      ))}
      {right.map((b, i) => (
        <rect key={'R'+i} x={rightBarX} y={b.y} width={barW} height={b.h} fill={b.color} rx={1.5}/>
      ))}
      {left.map((b, i) => (
        <foreignObject key={'LL'+i} x={0} y={b.y - 1} width={leftLabelW - 6} height={Math.max(b.h, 22)}>
          <div xmlns="http://www.w3.org/1999/xhtml" style={{
            fontFamily: FONTS.ui, fontSize: 10.5, color: theme.text, lineHeight: 1.1,
            display: 'flex', flexDirection: 'column', justifyContent: 'center', height: '100%',
            textAlign: 'right',
          }}>
            <div style={{ fontWeight: 500 }}>{b.label}</div>
            <div style={{ fontFamily: FONTS.mono, fontSize: 9, color: theme.textMute, marginTop: 1 }}>
              {fmtAED(b.value, { compact: true })}
            </div>
          </div>
        </foreignObject>
      ))}
      {right.map((b, i) => (
        <foreignObject key={'RL'+i} x={rightBarX + barW + 6} y={b.y - 1} width={rightLabelW - 6} height={Math.max(b.h, 22)}>
          <div xmlns="http://www.w3.org/1999/xhtml" style={{
            fontFamily: FONTS.ui, fontSize: 10.5, color: theme.text, lineHeight: 1.1,
            display: 'flex', flexDirection: 'column', justifyContent: 'center', height: '100%',
            textAlign: 'left',
          }}>
            <div style={{ fontWeight: 500 }}>{b.label}</div>
            <div style={{ fontFamily: FONTS.mono, fontSize: 9, color: theme.textMute, marginTop: 1 }}>
              {fmtAED(b.value, { compact: true })}
            </div>
          </div>
        </foreignObject>
      ))}
    </svg>
  );
}

Object.assign(window, { Wordmark, Card, SectionLabel, BigNumber, Donut, ProgressRing, Spark, StackedBar, Chip, Delta, Tag, CategoryIcon, Sankey, Dh, dhText });
