// components.jsx — shared UI atoms

const { useMemo, useState, useRef, useEffect } = React;

// ─── Logo ────────────────────────────────────────────────────────────────────
function Logo({ size = 22 }) {
  return (
    <div className="logo" style={{ fontSize: size }}>
      <span className="logo-dot" aria-hidden="true"></span>
      <span className="logo-word">reuseit</span>
      <span className="logo-mark">/index</span>
    </div>
  );
}

// ─── Icons (minimal, custom strokes — not a generic icon set) ────────────────
const Icon = ({ d, size = 16, fill = 'none', className }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={fill}
       stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"
       className={className}>
    {typeof d === 'string' ? <path d={d} /> : d}
  </svg>
);

const ICONS = {
  dash:    'M4 13l5-5 4 4 7-8 M4 20h16',
  cat:     'M4 5h7v7H4z M13 5h7v4h-7z M13 11h7v9h-7z M4 14h7v6H4z',
  detail:  'M4 4h12l4 4v12H4z M14 4v6h6',
  watch:   'M12 4l2.5 5.2 5.7.8-4.1 4 1 5.7L12 17l-5.1 2.7 1-5.7-4.1-4 5.7-.8z',
  settings:'M12 8.5a3.5 3.5 0 100 7 3.5 3.5 0 000-7z M19.4 13.5a7.5 7.5 0 000-3l2.1-1.6-2-3.4-2.5.8a7.5 7.5 0 00-2.6-1.5L13.9 2h-3.8l-.5 2.6a7.5 7.5 0 00-2.6 1.5l-2.5-.8-2 3.4 2.1 1.6a7.5 7.5 0 000 3l-2.1 1.6 2 3.4 2.5-.8a7.5 7.5 0 002.6 1.5l.5 2.6h3.8l.5-2.6a7.5 7.5 0 002.6-1.5l2.5.8 2-3.4z',
  search:  'M11 4a7 7 0 105.6 11.2L21 19.5 M11 4a7 7 0 017 7',
  arrow:   'M5 12h14 M13 6l6 6-6 6',
  up:      'M7 17L17 7 M9 7h8v8',
  down:    'M7 7l10 10 M9 17h8v-8',
  bookmark:'M6 4h12v17l-6-4-6 4z',
  bookmarkFill: <><path d="M6 4h12v17l-6-4-6 4z" fill="currentColor"/></>,
  globe:   'M12 3a9 9 0 100 18 9 9 0 000-18z M3 12h18 M12 3a14 14 0 010 18 M12 3a14 14 0 000 18',
  euro:    'M17 6a6 6 0 100 12 M4 10h9 M4 14h9',
  download:'M12 4v12 M7 11l5 5 5-5 M5 20h14',
  share:   'M8 12a3 3 0 11-3-3 3 3 0 013 3z M19 5a3 3 0 11-3-3 3 3 0 013 3z M19 19a3 3 0 11-3-3 3 3 0 013 3z M7.5 10.5l9-5 M7.5 13.5l9 5',
  filter:  'M4 5h16 M7 12h10 M10 19h4',
  grid:    'M4 4h7v7H4z M13 4h7v7h-7z M4 13h7v7H4z M13 13h7v7h-7z',
  offer:   'M4 5h16v4H4z M4 11h16v9H4z M9 15h6',
  history: 'M12 8v4l3 2 M12 3a9 9 0 109 9 M3 7l3-3 3 3',
  upload:  'M12 16V4 M7 9l5-5 5 5 M5 20h14',
  plus:    'M12 5v14 M5 12h14',
  trash:   'M5 7h14 M9 7V4h6v3 M7 7l1 13h8l1-13',
  edit:    'M4 20h4l10-10-4-4L4 16z M14 6l4 4',
  chevron: 'M6 9l6 6 6-6',
};

// ─── Pill / Badge ────────────────────────────────────────────────────────────
function Pill({ children, tone = 'default', className = '', ...rest }) {
  return <span className={`pill pill-${tone} ${className}`} {...rest}>{children}</span>;
}

// ─── Trend arrow with delta ──────────────────────────────────────────────────
function Trend({ value, suffix = '%' }) {
  const up = value >= 0;
  return (
    <span className={`trend ${up ? 'trend-up' : 'trend-down'}`}>
      <Icon d={up ? ICONS.up : ICONS.down} size={12} />
      {Math.abs(value).toFixed(1)}{suffix}
    </span>
  );
}

// ─── Currency ────────────────────────────────────────────────────────────────
function fmtPrice(n, cur = '€') {
  if (n == null) return '—';
  return cur + n.toLocaleString('en-DE');
}

// ─── Sparkline ───────────────────────────────────────────────────────────────
function Sparkline({ data, w = 80, h = 28, stroke = 'var(--accent)', fill = true, yDomain, fluid = false }) {
  const min = yDomain ? yDomain[0] : Math.min(...data);
  const max = yDomain ? yDomain[1] : Math.max(...data);
  const range = max - min || 1;
  const step = w / (data.length - 1);
  const pts = data.map((v, i) => [i * step, h - ((v - min) / range) * (h - 4) - 2]);
  const line = pts.map((p, i) => `${i ? 'L' : 'M'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const area = `${line} L${w},${h} L0,${h} Z`;
  const sizeProps = fluid
    ? { width: '100%', height: h, viewBox: `0 0 ${w} ${h}` }
    : { width: w, height: h };
  return (
    <svg {...sizeProps} className="sparkline" preserveAspectRatio="none" style={fluid ? { display: 'block' } : undefined}>
      {fill && <path d={area} fill={stroke} fillOpacity="0.12" />}
      <path d={line} fill="none" stroke={stroke} strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
}

// ─── Big interactive area chart with hover ───────────────────────────────────
function PriceChart({ series, range, currency = '€', yDomain }) {
  const hostRef = useRef(null);
  const [w, setW] = useState(800);
  const [hover, setHover] = useState(null);
  const h = 240;
  const pad = { l: 44, r: 16, t: 24, b: 28 };

  useEffect(() => {
    if (!hostRef.current) return;
    const ro = new ResizeObserver((entries) => {
      setW(Math.max(320, Math.floor(entries[0].contentRect.width)));
    });
    ro.observe(hostRef.current);
    return () => ro.disconnect();
  }, []);

  const labels = useMemo(() => {
    if (range === 'monthly') return ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    if (range === 'weekly')  return Array.from({length: series.length}, (_, i) => `W${i+1}`);
    return Array.from({length: series.length}, (_, i) => `D${i+1}`);
  }, [range, series.length]);

  const min = Math.min(...series);
  const max = Math.max(...series);
  const range01 = (max - min) || 1;
  // tidy y-grid — use shared domain if provided so sibling variant charts align
  const yMin = yDomain ? yDomain[0] : Math.floor(min / 100) * 100;
  const yMax = yDomain ? yDomain[1] : Math.ceil(max / 100) * 100;
  const ySteps = 4;
  const ticks = Array.from({length: ySteps + 1}, (_, i) => yMin + (yMax - yMin) * i / ySteps);

  const innerW = w - pad.l - pad.r;
  const innerH = h - pad.t - pad.b;
  const step = innerW / (series.length - 1);

  const pts = series.map((v, i) => [
    pad.l + i * step,
    pad.t + innerH - ((v - yMin) / (yMax - yMin || 1)) * innerH,
  ]);
  const line = pts.map((p, i) => `${i ? 'L' : 'M'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const area = `${line} L${pad.l + innerW},${pad.t + innerH} L${pad.l},${pad.t + innerH} Z`;
  const peakIdx = series.indexOf(max);

  function onMove(e) {
    const rect = e.currentTarget.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const i = Math.round((x - pad.l) / step);
    if (i >= 0 && i < series.length) setHover(i);
  }

  return (
    <div ref={hostRef} className="chart-host">
      <svg width={w} height={h} onMouseMove={onMove} onMouseLeave={() => setHover(null)}>
        <defs>
          <linearGradient id="cgrad" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%"  stopColor="var(--accent)" stopOpacity=".42" />
            <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
          </linearGradient>
        </defs>

        {/* y grid */}
        {ticks.map((t, i) => {
          const y = pad.t + innerH - ((t - yMin) / (yMax - yMin || 1)) * innerH;
          return (
            <g key={i}>
              <line x1={pad.l} x2={w - pad.r} y1={y} y2={y} stroke="var(--rule)" strokeDasharray="2 4" />
              <text x={pad.l - 8} y={y + 3} textAnchor="end" className="ax-y">{currency}{t}</text>
            </g>
          );
        })}

        {/* area + line */}
        <path d={area} fill="url(#cgrad)" />
        <path d={line} fill="none" stroke="var(--accent)" strokeWidth="1.6" />

        {/* dots */}
        {pts.map((p, i) => (
          <circle key={i} cx={p[0]} cy={p[1]} r={hover === i ? 3.2 : 1.8}
            fill="var(--accent)" stroke="var(--bg)" strokeWidth="1" />
        ))}

        {/* x labels */}
        {labels.map((lab, i) => {
          if (range === 'weekly' && i % 4 !== 0 && i !== labels.length - 1) return null;
          if (range === 'daily' && i % 5 !== 0 && i !== labels.length - 1) return null;
          return (
            <text key={i} x={pad.l + i * step} y={h - 8} textAnchor="middle" className="ax-x">{lab}</text>
          );
        })}

        {/* peak callout */}
        {hover === null && (
          <g transform={`translate(${pts[peakIdx][0]}, ${pts[peakIdx][1] - 18})`}>
            <rect x="-26" y="-13" width="52" height="20" rx="6" fill="var(--accent-strong)" />
            <text x="0" y="1" textAnchor="middle" className="callout">{currency}{max}</text>
            <path d="M-4 7 L0 12 L4 7 Z" fill="var(--accent-strong)" />
          </g>
        )}

        {/* hover tooltip */}
        {hover !== null && pts[hover] && (
          <g>
            <line x1={pts[hover][0]} x2={pts[hover][0]} y1={pad.t} y2={pad.t + innerH}
                  stroke="var(--accent)" strokeOpacity=".35" strokeDasharray="2 2" />
            <g transform={`translate(${Math.min(pts[hover][0], w - pad.r - 80)}, ${pad.t})`}>
              <rect x="0" y="0" width="92" height="42" rx="8" fill="var(--surface)" stroke="var(--rule)" />
              <text x="10" y="16" className="tip-lbl">{labels[hover]}</text>
              <text x="10" y="32" className="tip-val">{currency}{series[hover]}</text>
            </g>
          </g>
        )}
      </svg>
    </div>
  );
}

// ─── Product visual placeholder (since we don't have real images) ────────────
function ProductGlyph({ product, size = 120, tone = 'cream' }) {
  const cat = product.cat;
  const stripe = `repeating-linear-gradient(135deg, var(--placeholder-stripe) 0 1px, transparent 1px 8px)`;
  let shape;
  switch (cat) {
    case 'phones':
      shape = (
        <rect x="36" y="14" width="48" height="92" rx="10"
              fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
      );
      break;
    case 'tablets':
      shape = (
        <rect x="20" y="18" width="80" height="84" rx="8"
              fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
      );
      break;
    case 'laptops':
      shape = (
        <g>
          <rect x="18" y="26" width="84" height="54" rx="4"
                fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
          <rect x="10" y="80" width="100" height="10" rx="3"
                fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
        </g>
      );
      break;
    case 'desktops':
      shape = (
        <g>
          <rect x="22" y="20" width="76" height="50" rx="3"
                fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
          <rect x="50" y="74" width="20" height="14"
                fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
          <rect x="38" y="88" width="44" height="6" rx="2"
                fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
        </g>
      );
      break;
    case 'watches':
      shape = (
        <g>
          <rect x="40" y="34" width="40" height="52" rx="10"
                fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
          <path d="M48 34 L52 18 L68 18 L72 34" fill="none"
                stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
          <path d="M48 86 L52 102 L68 102 L72 86" fill="none"
                stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
        </g>
      );
      break;
    case 'audio':
      shape = (
        <g>
          <circle cx="60" cy="60" r="34" fill="var(--placeholder-fill)"
                  stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
          <circle cx="60" cy="60" r="14" fill="none"
                  stroke="var(--placeholder-stroke)" strokeWidth="1.5" />
        </g>
      );
      break;
    default:
      shape = <rect x="20" y="20" width="80" height="80" rx="6"
                    fill="var(--placeholder-fill)" stroke="var(--placeholder-stroke)" />;
  }
  return (
    <div className={`pglyph pglyph-${tone}`} style={{ width: size, height: size }}>
      <div className="pglyph-stripe" style={{ backgroundImage: stripe }}></div>
      <svg viewBox="0 0 120 120" width={size} height={size}>{shape}</svg>
      <div className="pglyph-cap">{product.cat.toUpperCase()}</div>
    </div>
  );
}

Object.assign(window, {
  Logo, Icon, ICONS, Pill, Trend, fmtPrice, Sparkline, PriceChart, ProductGlyph,
});
