/* ═══════════════════════════════════════════════════════════════════
   MigCharts.jsx — net-new presentational bits for Migrations. v1.0.0
   Ported from the Claude Design v2 package
   (_CLAUDE-DESIGN/_2026-06-12-v2-SaaS-Redesign/migrations-charts.jsx)
   — port, not redesign. StepRail (9-stage, workflow-status colors),
   tokenized LogConsole (--term-* layer, ported to tokens.css with this
   increment), MigStatusChip, HostBreadcrumb, CounterTile, PreflightRow,
   RollbackManifest. Status reads by ICON + LABEL + color (never color
   alone). Bare-global design ref (MIG_STATUS) rewritten to the app
   namespace — the only port delta besides the namespacing. NOTE: the
   StepRail paused/failed node foregrounds carry design-verbatim
   contrast pairings on the fixed --v-warn-fill / --v-poor-fill node
   fills (same class as --on-accent) — kept verbatim, not new semantic
   colors.
   Load order: SECOND of the five Mig modules (after MigData).
   Registers: window.WPSB.MigCharts = { MigStatusChip, HostBreadcrumb,
   HostEndpoint, StepRail, LogConsole, CounterTile, PreflightRow,
   RollbackManifest }.
   ═══════════════════════════════════════════════════════════════════ */
(function () {
const { MIG_STATUS } = window.WPSB.MigData;
const tx = (k, v, f) => (window.WPSB && window.WPSB.t) ? window.WPSB.t(k, v, f) : (f != null ? f : k);

/* one-time animation styles (pulse ring + blinking live dot), reduced-motion safe */
(function () {
  if (document.getElementById('mig-anim')) return;
  const s = document.createElement('style');
  s.id = 'mig-anim';
  s.textContent = [
    '@keyframes migPulse{0%,100%{box-shadow:0 0 0 0 color-mix(in oklch,var(--beam) 50%,transparent)}50%{box-shadow:0 0 0 7px color-mix(in oklch,var(--beam) 0%,transparent)}}',
    '@keyframes termBlink{0%,49%{opacity:1}50%,100%{opacity:0}}',
    '.mig-pulse{animation:migPulse 1.7s ease-in-out infinite}',
    '.mig-live-dot{animation:termBlink 1.1s steps(1) infinite}',
    '@media (prefers-reduced-motion: reduce){.mig-pulse,.mig-live-dot{animation:none!important}}',
  ].join('');
  document.head.appendChild(s);
})();

/* status chip — workflow axis (queued/running/paused/completed/failed) */
function MigStatusChip({ status, size = 'md' }) {
  const v = MIG_STATUS[status];
  const sm = size === 'sm';
  return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: sm ? 5 : 6,
    padding: sm ? '3px 9px 3px 8px' : '4px 11px 4px 9px', borderRadius: 999, whiteSpace: 'nowrap',
    background: 'color-mix(in oklch, ' + v.cf + ' 13%, transparent)', color: v.c,
    border: '1px solid color-mix(in oklch, ' + v.cf + ' 34%, transparent)',
    fontFamily: 'var(--font-mono)', fontWeight: 'var(--fw-tag)', fontSize: sm ? '.58rem' : '.64rem', letterSpacing: '.04em' } },
    v.pulse
      ? React.createElement('span', { className: 'mig-live-dot', style: { width: 7, height: 7, borderRadius: '50%', background: v.cf, flex: 'none' } })
      : React.createElement(WIcon, { name: v.icon, size: sm ? 12 : 13 }),
    v.label);
}

/* source → destination breadcrumb with host + env */
function HostEndpoint({ ep, role }) {
  return React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 } },
    React.createElement('span', { style: { width: 34, height: 34, borderRadius: 'var(--r-sm)', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'var(--surface-2)', color: 'var(--muted)', border: '1px solid var(--border)' } },
      React.createElement(WIcon, { name: 'server', size: 17 })),
    React.createElement('div', { style: { minWidth: 0 } },
      React.createElement('div', { className: 'wiz-eyebrow', style: { fontSize: '.52rem', marginBottom: 2, color: 'var(--dim)' } }, role),
      React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 7, flexWrap: 'wrap' } },
        React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.84rem', fontWeight: 'var(--fw-mono)', color: 'var(--text)' } }, ep.host),
        React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 4, fontFamily: 'var(--font-mono)', fontSize: '.58rem', letterSpacing: '.04em',
          textTransform: 'uppercase', color: 'var(--muted)', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 999, padding: '2px 7px' } },
          React.createElement(WIcon, { name: 'git-branch', size: 10 }), ep.env))));
}
function HostBreadcrumb({ source, dest }) {
  return React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 'var(--sp-4)', flexWrap: 'wrap' } },
    React.createElement(HostEndpoint, { ep: source, role: tx('page.migration.charts.source', null, 'Source') }),
    React.createElement('span', { style: { color: 'var(--beam)', display: 'flex', flex: 'none' } }, React.createElement(WIcon, { name: 'arrow-right', size: 18 })),
    React.createElement(HostEndpoint, { ep: dest, role: tx('page.migration.charts.destination', null, 'Destination') }));
}

/* 9-stage step rail — workflow-status colors. state: running|paused|failed */
function migStepStatus(i, current, state) {
  if (i < current) return 'done';
  if (i === current) return state === 'failed' ? 'failed' : state === 'paused' ? 'paused' : 'current';
  return 'upcoming';
}
function StepRail({ steps, current, state = 'running' }) {
  const NODE = 30;
  const palette = {
    done:     { bg: 'var(--wiz-step-done)', fg: 'var(--on-accent)', bd: 'var(--wiz-step-done)' },
    current:  { bg: 'var(--beam)',       fg: 'var(--on-accent)', bd: 'var(--beam)' },
    paused:   { bg: 'var(--v-warn-fill)',fg: '#1a1206',          bd: 'var(--v-warn-fill)' },
    failed:   { bg: 'var(--v-poor-fill)',fg: '#fff',             bd: 'var(--v-poor-fill)' },
    upcoming: { bg: 'var(--surface-2)',  fg: 'var(--dim)',       bd: 'var(--border-2)' },
  };
  return React.createElement('div', { role: 'group', 'aria-label': tx('page.migration.charts.stage_aria', { n: current + 1, total: steps.length }, 'Migration stage {n} of {total}'),
    style: { display: 'flex', alignItems: 'flex-start', overflowX: 'auto', paddingBottom: 4 } },
    steps.map((s, i) => {
      const st = migStepStatus(i, current, state);
      const p = palette[st];
      const icon = st === 'done' ? 'check' : st === 'failed' ? 'x' : st === 'paused' ? 'pause' : null;
      return React.createElement(React.Fragment, { key: s.key },
        React.createElement('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 7, flex: 'none', width: 84 } },
          React.createElement('span', { className: st === 'current' ? 'mig-pulse' : '',
            style: { width: NODE, height: NODE, borderRadius: '50%', background: p.bg, color: p.fg, border: '1.5px solid ' + p.bd, flex: 'none',
              display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'var(--font-mono)', fontWeight: 'var(--fw-bold)', fontSize: '.74rem' } },
            icon ? React.createElement(WIcon, { name: icon, size: 15, stroke: 3 }) : (i + 1)),
          React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.6rem', letterSpacing: '.02em', textAlign: 'center', lineHeight: 1.25,
            color: st === 'upcoming' ? 'var(--dim)' : st === 'current' ? 'var(--beam)' : 'var(--text-2)',
            fontWeight: st === 'current' ? 'var(--fw-bold)' : 'var(--fw-mono-small)' } }, s.short)),
        i < steps.length - 1 && React.createElement('span', { style: { flex: '1 0 18px', minWidth: 18, height: 2, marginTop: NODE / 2 - 1,
          background: i < current ? 'var(--wiz-rail-done)' : 'var(--border)', borderRadius: 2 } }));
    }));
}

/* tokenized live-log console (--term-*) */
const TERM_LV = {
  ok:   { c: 'var(--term-ok)',   tag: 'OK' },
  info: { c: 'var(--term-info)', tag: 'INFO' },
  warn: { c: 'var(--term-warn)', tag: 'WARN' },
  err:  { c: 'var(--term-err)',  tag: 'ERR' },
};
function LogConsole({ lines, live = true, height = 240 }) {
  return React.createElement('div', { style: { background: 'var(--term-bg)', border: '1px solid var(--term-border)', borderRadius: 'var(--r-lg)', overflow: 'hidden' } },
    // header
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10,
      padding: '9px 14px', borderBottom: '1px solid var(--term-border)', background: 'var(--term-bg-2)' } },
      React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 8, fontFamily: 'var(--font-mono)', fontSize: '.64rem', letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--term-dim)' } },
        React.createElement(WIcon, { name: 'terminal', size: 13, style: { color: 'var(--term-info)' } }), tx('page.migration.charts.live_log', null, 'Live log')),
      live && React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: '.6rem', color: 'var(--term-ok)' } },
        React.createElement('span', { className: 'mig-live-dot', style: { width: 6, height: 6, borderRadius: '50%', background: 'var(--term-ok)' } }), tx('page.migration.charts.streaming', null, 'streaming'))),
    // lines
    React.createElement('div', { style: { padding: '10px 14px', maxHeight: height, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 3 } },
      lines.map((ln, i) => {
        const lv = TERM_LV[ln.lv];
        return React.createElement('div', { key: i, style: { display: 'flex', gap: 10, alignItems: 'flex-start', fontFamily: 'var(--font-mono)', fontSize: '.74rem', lineHeight: 1.5 } },
          React.createElement('span', { style: { color: 'var(--term-dim)', flex: 'none', lineHeight: 1.5 } }, ln.t),
          React.createElement('span', { style: { color: lv.c, flex: 'none', fontWeight: 'var(--fw-bold)', minWidth: 42, lineHeight: 1.5 } }, '[' + lv.tag + ']'),
          React.createElement('span', { style: { color: 'var(--term-fg)', minWidth: 0, flex: 1, lineHeight: 1.5, wordBreak: 'break-word' } }, ln.msg));
      }),
      live && React.createElement('div', { style: { display: 'flex', gap: 10, alignItems: 'center', fontFamily: 'var(--font-mono)', fontSize: '.74rem', marginTop: 2 } },
        React.createElement('span', { style: { color: 'var(--term-dim)' } }, '›'),
        React.createElement('span', { className: 'mig-live-dot', style: { width: 8, height: 15, background: 'var(--term-fg)', display: 'inline-block', borderRadius: 1 } }))));
}

/* counter tile (DB rows / media / plugins / 404s-caught) — each gets a distinct
   accent so the stats read as separate, colorful tiles (Throughput stays cyan). */
function CounterTile({ icon, label, value, color, warn }) {
  const c = color || (warn ? 'var(--warn)' : 'var(--beam)');
  return React.createElement('div', { style: { background: 'color-mix(in oklch, ' + c + ' 9%, var(--surface))', border: '1px solid color-mix(in oklch, ' + c + ' 32%, transparent)',
    borderRadius: 'var(--r-sm)', padding: '11px 13px', display: 'flex', alignItems: 'center', gap: 10 } },
    React.createElement('span', { style: { width: 30, height: 30, borderRadius: 'var(--r-sm)', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'color-mix(in oklch, ' + c + ' 16%, transparent)', color: c, border: '1px solid color-mix(in oklch, ' + c + ' 30%, transparent)' } }, React.createElement(WIcon, { name: icon, size: 16 })),
    React.createElement('div', { style: { minWidth: 0 } },
      React.createElement('div', { style: { fontFamily: 'var(--font-brand)', fontWeight: 'var(--fw-bold)', fontSize: '1.05rem', color: c, fontVariantNumeric: 'tabular-nums', lineHeight: 1.1 } }, value),
      React.createElement('div', { className: 'wiz-eyebrow', style: { fontSize: '.52rem', marginTop: 2, color: 'var(--muted)' } }, label)));
}

/* preflight check row — pass/warn by icon + label + color */
function PreflightRow({ v, label, detail }) {
  const meta = v === 'pass' ? { c: 'var(--v-good)', icon: 'check-circle' } : v === 'warn' ? { c: 'var(--v-warn)', icon: 'alert-triangle' } : { c: 'var(--v-poor)', icon: 'x-circle' };
  return React.createElement('div', { style: { display: 'flex', alignItems: 'flex-start', gap: 11, padding: '10px 0', borderBottom: '1px solid var(--border)' } },
    React.createElement('span', { style: { color: meta.c, flex: 'none', marginTop: 1 } }, React.createElement(WIcon, { name: meta.icon, size: 17 })),
    React.createElement('div', { style: { flex: 1, minWidth: 0 } },
      React.createElement('div', { style: { fontSize: '.86rem', fontWeight: 'var(--fw-medium)', color: 'var(--text)' } }, label),
      React.createElement('div', { style: { fontSize: '.78rem', color: 'var(--muted)', marginTop: 1 } }, detail)),
    React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.6rem', letterSpacing: '.06em', textTransform: 'uppercase', color: meta.c, flex: 'none', marginTop: 2 } }, v));
}

/* dual-side rollback manifest */
function RollbackManifest({ rows, onToast, tone = 'warn' }) {
  const accent = tone === 'err' ? 'var(--red)' : 'var(--warn)';
  return React.createElement('div', { style: { border: '1px solid color-mix(in oklch, ' + accent + ' 30%, transparent)', borderRadius: 'var(--r-lg)', overflow: 'hidden', background: 'var(--surface)' } },
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 9, padding: '11px 14px', background: 'color-mix(in oklch, ' + accent + ' 9%, var(--surface))', borderBottom: '1px solid color-mix(in oklch, ' + accent + ' 24%, transparent)' } },
      React.createElement(WIcon, { name: 'rotate-ccw', size: 15, style: { color: accent } }),
      React.createElement('span', { style: { fontWeight: 'var(--fw-label)', fontSize: '.84rem', color: 'var(--text)' } }, tx('page.migration.charts.rollback_manifest', null, 'Rollback manifest')),
      React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.6rem', color: 'var(--muted)' } }, tx('page.migration.charts.dual_side', null, 'dual-side'))),
    rows.map((r, i) => React.createElement('div', { key: i, style: { display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', padding: '11px 14px', borderBottom: i < rows.length - 1 ? '1px solid var(--border)' : 'none' } },
      React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.58rem', letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--muted)', minWidth: 78, flex: 'none' } }, r.side),
      React.createElement('div', { style: { flex: 1, minWidth: 0 } },
        React.createElement('div', { style: { fontSize: '.82rem', color: 'var(--text)' } }, r.point),
        React.createElement('div', { style: { fontFamily: 'var(--font-mono)', fontSize: '.68rem', color: 'var(--muted)', marginTop: 1 } }, r.host + ' · ' + r.size + ' · ' + r.at)),
      React.createElement('button', { type: 'button', className: 'wiz-btn wiz-btn-secondary wiz-focusable', style: { fontSize: '.68rem', padding: '6px 12px' },
        onClick: () => onToast && onToast({ kind: 'success', text: tx('page.migration.charts.restoring', { side: r.side.toLowerCase(), point: r.point }, 'Restoring {side} from {point}…') }) },
        React.createElement(WIcon, { name: 'rotate-ccw', size: 13 }), tx('page.migration.charts.restore', null, 'Restore'))))
  );
}

window.WPSB = window.WPSB || {};
window.WPSB.MigCharts = { MigStatusChip, HostBreadcrumb, HostEndpoint, StepRail, LogConsole, CounterTile, PreflightRow, RollbackManifest };
console.log('[WPSB] MigCharts v1.0.0 loaded');
})();
