// transitions.jsx — V1.22.0 (Janik 2026-04-27)
//
// React-Helper-Components für Cortex's Animation-System (transitions.css).
// Kapseln die Trigger-Logik für Patterns die JS brauchen (re-mount-Animation,
// open/close state-machine etc.). Pure-CSS-Patterns (t-resize, t-icon-swap)
// brauchen keinen Helper — werden direkt mit Klassen genutzt.

// ─────────────────────────────────────────────────────────────────────────
// 1. AnimatedNumber — wraps t-digit-group (Number pop-in)
//
// Re-rendert mit fresh animation jedes Mal wenn `value` sich ändert.
// Stagger-data-attribute pro digit (max 7 digits, dann verschwendet kein delay).
// ─────────────────────────────────────────────────────────────────────────
function AnimatedNumber({ value, dirX = 0, dirY = 1, className = '' }) {
  const [key, setKey] = React.useState(0);
  const prev = React.useRef(value);
  React.useEffect(() => {
    if (prev.current !== value) {
      setKey((k) => k + 1);
      prev.current = value;
    }
  }, [value]);
  const text = String(value ?? '');
  return (
    <span
      key={key}
      className={`t-digit-group is-animating ${className}`}
      style={{ '--digit-dir-x': dirX, '--digit-dir-y': dirY }}
    >
      {text.split('').map((d, i) => (
        <span key={i} className="t-digit" data-stagger={i || undefined}>{d}</span>
      ))}
    </span>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 2. TextSwap — wraps t-text-swap (3-phase JS state-swap)
//
// Wenn `value` sich ändert: alte Text rauf+blur (exit), Text wechseln,
// neuer Text von unten rein (enter). Reduced-motion ⇒ instant swap.
// ─────────────────────────────────────────────────────────────────────────
function TextSwap({ value, className = '' }) {
  const [shown, setShown] = React.useState(value);
  const [phase, setPhase] = React.useState('idle'); // 'idle' | 'exit' | 'enter-start'
  const ref = React.useRef(null);
  const prev = React.useRef(value);
  React.useEffect(() => {
    if (prev.current === value) return;
    setPhase('exit');
    const t1 = setTimeout(() => {
      setShown(value);
      setPhase('enter-start');
      // force reflow + remove start so transition kicks in
      requestAnimationFrame(() => {
        if (ref.current) ref.current.offsetHeight; // force reflow
        setPhase('idle');
      });
    }, 200);
    prev.current = value;
    return () => clearTimeout(t1);
  }, [value]);
  const cls = `t-text-swap ${phase === 'exit' ? 'is-exit' : phase === 'enter-start' ? 'is-enter-start' : ''} ${className}`.trim();
  return <span ref={ref} className={cls}>{shown}</span>;
}

// ─────────────────────────────────────────────────────────────────────────
// 3. TransitionModal — wraps t-modal (scale + fade)
//
// Komponiert mit dem existing fixed inset-0 backdrop. Das innere modal-card
// bekommt t-modal + open/closing classes. Render-Out-Logik via 150ms delay
// damit die close-Animation komplett läuft bevor unmount.
//
// V1.23 (Janik 2026-04-27): initial-phase IMMER 'closed' damit auch beim
// ersten Mount-mit-open=true die Open-Animation läuft (vorher: phase='open'
// → keine Transition, weil .is-open schon aktiv).
// ─────────────────────────────────────────────────────────────────────────
function TransitionModal({ open, onClose, children, backdropClassName = '', cardClassName = '', backdropStyle = {} }) {
  const [render, setRender] = React.useState(open);
  const [phase, setPhase] = React.useState('closed');
  React.useEffect(() => {
    if (open) {
      setRender(true);
      // next tick: trigger open animation
      requestAnimationFrame(() => requestAnimationFrame(() => setPhase('open')));
    } else if (render) {
      setPhase('closing');
      const t = setTimeout(() => { setRender(false); setPhase('closed'); }, 150);
      return () => clearTimeout(t);
    }
  }, [open, render]);
  if (!render) return null;
  const cardCls = `t-modal ${phase === 'open' ? 'is-open' : phase === 'closing' ? 'is-closing' : ''} ${cardClassName}`.trim();
  return (
    <div
      className={`fixed inset-0 z-[1000] flex items-center justify-center p-4 ${backdropClassName}`}
      style={{ background: 'rgba(11, 15, 25, 0.55)', backdropFilter: 'blur(6px)', ...backdropStyle }}
      onClick={onClose}
    >
      <div className={cardCls} onClick={(e) => e.stopPropagation()}>
        {children}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 4. DropdownMenu — wraps t-dropdown (origin-aware open/close)
//
// origin: 'top-left' | 'top-right' | 'top-center' | 'bottom-left' |
//         'bottom-right' | 'bottom-center'
// ─────────────────────────────────────────────────────────────────────────
function DropdownMenu({ open, origin = 'top-left', children, className = '', style = {} }) {
  const [render, setRender] = React.useState(open);
  const [phase, setPhase] = React.useState('closed');
  React.useEffect(() => {
    if (open) {
      setRender(true);
      requestAnimationFrame(() => requestAnimationFrame(() => setPhase('open')));
    } else if (render) {
      setPhase('closing');
      const t = setTimeout(() => { setRender(false); setPhase('closed'); }, 150);
      return () => clearTimeout(t);
    }
  }, [open, render]);
  if (!render) return null;
  const cls = `t-dropdown ${phase === 'open' ? 'is-open' : phase === 'closing' ? 'is-closing' : ''} ${className}`.trim();
  return <div className={cls} data-origin={origin} style={style}>{children}</div>;
}

// ─────────────────────────────────────────────────────────────────────────
// 5. PanelReveal — wraps t-panel-slide (translate + fade + blur)
//
// `translateY` configurable via prop (default 24px). Geeignet für sub-Panels
// die "auf dem Lead-Detail aufklappen".
// ─────────────────────────────────────────────────────────────────────────
function PanelReveal({ open, children, translateY = 24, className = '' }) {
  return (
    <div
      className={`t-panel-slide ${className}`}
      data-open={open ? 'true' : 'false'}
      style={{ '--panel-translate-y': `${translateY}px` }}
    >
      {children}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 6. NotificationBadge — wraps t-badge (slide-in + spring-pop)
//
// Wird IN dem Trigger-Element platziert (z.B. Bell-Icon). Trigger braucht
// position: relative damit das Badge sich anchored.
// ─────────────────────────────────────────────────────────────────────────
function NotificationBadge({ open, count, className = '', dotClassName = '' }) {
  // V1.23 (Janik 2026-04-27): dotClassName erweitert damit caller die
  // visuelle Hülle (Farbe/Padding/Border) beibehält und nur die Position
  // + Transitions vom Helper kommen.
  const defaultDot = 'min-w-[14px] h-[14px] px-1 rounded-full bg-[#3465E3] text-white text-[9.5px] font-semibold flex items-center justify-center ring-2 ring-white';
  const dotCls = `t-badge-dot ${dotClassName || defaultDot}`.trim();
  return (
    <span className={`t-badge ${className}`} data-open={open ? 'true' : 'false'}>
      <span className={dotCls}>{count}</span>
    </span>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 7. IconSwap — wraps t-icon-swap (state="a"|"b" mit scale+blur swap)
//
// Children: zwei Icon-Elemente mit data-icon="a" + data-icon="b".
// ─────────────────────────────────────────────────────────────────────────
function IconSwap({ state, children, className = '' }) {
  return (
    <span className={`t-icon-swap ${className}`} data-state={state}>
      {children}
    </span>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// Window-Export für Prototype-shared usage
// ─────────────────────────────────────────────────────────────────────────
Object.assign(window, {
  AnimatedNumber,
  TextSwap,
  TransitionModal,
  DropdownMenu,
  PanelReveal,
  NotificationBadge,
  IconSwap,
});
