/* global React */
// ============================================================
// FEATURES — 3D WIREFRAME VISUALISATIONS
//
// One minimal, monochrome wireframe-style animation per
// accordion item. All loops are continuous; transitions
// between items are handled by the parent (fade + scale).
//
// Aesthetic rules (shared):
//   - Outline only, no fills (or extremely faint fills)
//   - Single brand-blue stroke color
//   - No textures, gradients only used for traveling beams
//   - Smooth, slow motion
//   - SVG used for vector wireframes; CSS 3D for floating
//     elements (card, orbits) that benefit from preserve-3d
// ============================================================

const FEAT_STROKE = "rgba(140,160,246,0.92)";
const FEAT_STROKE_DIM = "rgba(140,160,246,0.30)";
const FEAT_NODE = "rgba(140,160,246,1)";

// ============================================================
// VIS 1 — Wireframe rotating globe with pulsing nodes + beams
// ============================================================
function VisGlobe3D() {
  const R = 110;

  // Meridians: 8 vertical great-circles, each at a different
  // phase. We animate `rx` 0 → R → 0 → -R → 0 cyclically (we
  // can't go negative on rx, so we run 0→R→0 staggered with
  // 8 meridians ⇒ the union appears as a continuously rotating
  // sphere).
  const MERIDIANS = [0, 1, 2, 3, 4, 5, 6, 7];
  const PERIOD = 9; // seconds for one full rotation
  // Each meridian's rx cycles 0→R→0 in PERIOD/2 seconds,
  // staggered by (PERIOD/2) / MERIDIANS.length.
  const STAGGER = (PERIOD / 2) / MERIDIANS.length;

  // Parallels: ellipses at constant y, ry shrunk by cos(lat).
  const PARALLELS = [-60, -30, 0, 30, 60];

  // Nodes: lat/lng pairs. We animate cx by an ellipse-path
  // animateMotion so each node travels along its parallel.
  // Position on globe: longitude offset starts at "lng".
  const NODES = [
    { lat:  20, lng:   0, dur: PERIOD,        delay: 0     },
    { lat: -10, lng:  45, dur: PERIOD * 1.1,  delay: 1.0   },
    { lat:  45, lng:  90, dur: PERIOD * 0.9,  delay: 2.4   },
    { lat: -35, lng: 135, dur: PERIOD * 1.05, delay: 0.6   },
    { lat:  10, lng: 180, dur: PERIOD,        delay: 3.2   },
    { lat:  60, lng: 225, dur: PERIOD * 0.95, delay: 4.0   },
    { lat: -25, lng: 270, dur: PERIOD * 1.1,  delay: 1.6   },
    { lat:  30, lng: 315, dur: PERIOD * 0.9,  delay: 5.0   },
  ];

  return (
    <div className="vis3d-scene" style={{ display:"flex", alignItems:"center", justifyContent:"center", width:"100%", height:"100%" }}>
      <svg viewBox="-150 -150 300 300" width="100%" height="100%" style={{ maxWidth: 540, maxHeight: 540 }}>
        {/* Outline */}
        <circle cx="0" cy="0" r={R} fill="none" stroke={FEAT_STROKE} strokeWidth="1"/>

        {/* Parallels */}
        {PARALLELS.map((lat) => {
          const y  = -R * Math.sin(lat * Math.PI / 180);
          const rx = R  * Math.cos(lat * Math.PI / 180);
          const ry = rx * 0.18; // perspective squash
          return (
            <ellipse
              key={`par-${lat}`}
              cx="0" cy={y} rx={rx} ry={ry}
              fill="none" stroke={FEAT_STROKE_DIM} strokeWidth="0.7"
            />
          );
        })}

        {/* Meridians — animated rx for rotation illusion */}
        {MERIDIANS.map((i) => (
          <ellipse
            key={`mer-${i}`}
            cx="0" cy="0" rx={R} ry={R}
            fill="none" stroke={FEAT_STROKE_DIM} strokeWidth="0.7"
          >
            <animate
              attributeName="rx"
              values={`0;${R};0`}
              keyTimes="0;0.5;1"
              dur={`${PERIOD/2}s`}
              begin={`${-STAGGER * i}s`}
              repeatCount="indefinite"
              calcMode="spline"
              keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
            />
          </ellipse>
        ))}

        {/* Nodes — orbit along their parallel via animateMotion */}
        {NODES.map((n, i) => {
          const ry = R * Math.cos(n.lat * Math.PI / 180);
          const y  = -R * Math.sin(n.lat * Math.PI / 180);
          // Define a path: ellipse starting at lng offset
          // Path: M(ry,y) a(ry, ry*0.18) ...
          const pathId = `globe-orbit-${i}`;
          return (
            <g key={`node-${i}`}>
              <defs>
                <path
                  id={pathId}
                  d={`M ${ry} ${y} A ${ry} ${ry*0.18} 0 1 1 ${-ry} ${y} A ${ry} ${ry*0.18} 0 1 1 ${ry} ${y}`}
                />
              </defs>
              <circle r="2.2" fill={FEAT_NODE}>
                <animate
                  attributeName="r"
                  values="1.4;2.6;1.4"
                  dur="2.6s"
                  begin={`${n.delay/2}s`}
                  repeatCount="indefinite"
                />
                <animateMotion
                  dur={`${n.dur}s`}
                  begin={`${-n.delay}s`}
                  repeatCount="indefinite"
                >
                  <mpath href={`#${pathId}`}/>
                </animateMotion>
              </circle>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ============================================================
// VIS 2 — Concentric rings emanating from a center point.
// Reads as a SPEI ping going out instantly.
// ============================================================
function VisRings3D() {
  const RINGS = [0, 1, 2, 3, 4];      // 5 rings
  const PERIOD = 2.6;                 // seconds per ring lifecycle
  const STAGGER = PERIOD / RINGS.length;
  const MAX = 140;

  return (
    <div className="vis3d-scene" style={{ display:"flex", alignItems:"center", justifyContent:"center", width:"100%", height:"100%" }}>
      <svg viewBox="-150 -150 300 300" width="100%" height="100%" style={{ maxWidth: 360, maxHeight: 360 }}>
        {/* Center dot */}
        <circle cx="0" cy="0" r="4" fill={FEAT_NODE}>
          <animate attributeName="r" values="3;5.5;3" dur="2.6s" repeatCount="indefinite"/>
        </circle>
        {/* Inner glow ring (subtle, stays put) */}
        <circle cx="0" cy="0" r="10" fill="none" stroke={FEAT_STROKE_DIM} strokeWidth="0.8"/>

        {/* Expanding rings */}
        {RINGS.map((i) => (
          <circle key={i} cx="0" cy="0" r="20" fill="none" stroke={FEAT_STROKE} strokeWidth="1">
            <animate
              attributeName="r"
              values={`8;${MAX}`}
              dur={`${PERIOD}s`}
              begin={`${-STAGGER * i}s`}
              repeatCount="indefinite"
              calcMode="spline"
              keySplines="0.16 1 0.3 1"
            />
            <animate
              attributeName="opacity"
              values="0;0.95;0"
              keyTimes="0;0.15;1"
              dur={`${PERIOD}s`}
              begin={`${-STAGGER * i}s`}
              repeatCount="indefinite"
            />
            <animate
              attributeName="stroke-width"
              values="1.4;0.4"
              dur={`${PERIOD}s`}
              begin={`${-STAGGER * i}s`}
              repeatCount="indefinite"
            />
          </circle>
        ))}
      </svg>
    </div>
  );
}

// ============================================================
// VIS 3 — Floating wireframe credit-card style rectangle
// rotating slowly on its Y axis, with a gentle vertical bob.
// ============================================================
function VisCard3D() {
  return (
    <div className="vis3d-scene vis3d-card-scene">
      <div className="vis3d-card-orbit">
        <div className="vis3d-card">
          {/* Subtle inner detail — a single thin strip + chip-sized square */}
          <span className="vis3d-card-strip"/>
          <span className="vis3d-card-chip"/>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// VIS 4 — Elegant currency selector: a single large symbol
// centered in the panel that morphs through $ → € → £ → ¥
// in a continuous 6s loop (1.5s per symbol). Crossfade with
// a subtle scale "breathe". A small label below echoes the
// active currency code in sync (USD → EUR → GBP → CNY).
// ============================================================
function VisOrbit3D() {
  const CYCLE = 6; // seconds for full loop (4 × 1.5s)
  const SYMS = [
    { ch: "$", code: "USD", offset: 0   },
    { ch: "€", code: "EUR", offset: 1.5 },
    { ch: "£", code: "GBP", offset: 3.0 },
    { ch: "¥", code: "CNY", offset: 4.5 },
  ];

  return (
    <div className="vis3d-scene vis3d-cur-scene">
      <div className="vis3d-cur-stack">
        {SYMS.map((s, i) => (
          <div
            key={i}
            className="vis3d-cur-item"
            style={{
              "--dur": `${CYCLE}s`,
              "--delay": `${s.offset - CYCLE}s`,
            }}
          >
            <span className="vis3d-cur-glyph">{s.ch}</span>
            <span className="vis3d-cur-code">{s.code}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ============================================================
// VIS 5 — 3D perspective floor with vertical wireframe bars
// rising and falling asynchronously, glowing at their peaks.
// All in SVG with manually-projected grid coordinates so the
// perspective is exact and bars sit flush on the floor.
// ============================================================
function VisLineChart3D() {
  const W = 460, H = 280;
  // Floor frame (a perspective trapezoid)
  const FAR_Y  = 76,   NEAR_Y = 246;
  const FAR_W  = 220,  NEAR_W = 440;
  const CX = W / 2;
  const COLS = 8;
  const ROWS = 6;

  // Project a (col, row) grid intersection to screen coords.
  // row 0 = far edge, row ROWS = near edge.
  const gridPos = (col, row) => {
    const t = row / ROWS;
    const y = FAR_Y + (NEAR_Y - FAR_Y) * t;
    const halfW = (FAR_W + (NEAR_W - FAR_W) * t) / 2;
    const x = (CX - halfW) + (2 * halfW) * (col / COLS);
    return { x, y };
  };

  // Bars sit centered between cols at floor row 3.5 (middle).
  // Each gets its own height-keyframe sequence so the row feels
  // alive and asynchronous, like live tesorería data.
  const ROW = 3.5;
  const HEIGHTS = [
    [40, 90, 55, 130, 75, 100, 60, 110, 50],
    [70, 30, 110, 60, 95, 50, 130, 80, 60],
    [50, 120, 80, 40, 95, 70, 110, 55, 90],
    [90, 60, 130, 80, 50, 110, 70, 95, 65],
    [60, 100, 50, 120, 75, 105, 60, 85, 110],
    [110, 50, 90, 70, 130, 60, 95, 75, 100],
    [80, 130, 60, 95, 50, 110, 70, 90, 55],
    [50, 70, 110, 80, 60, 95, 130, 75, 90],
  ];
  const DURS = [4.4, 4.0, 5.2, 4.6, 4.8, 4.2, 5.4, 4.6];

  // Foreshortening of the bar width at row 3.5
  const tMid = ROW / ROWS;
  const cellW = ((FAR_W + (NEAR_W - FAR_W) * tMid)) / COLS;
  const BAR_W = cellW * 0.42;

  return (
    <div className="vis3d-scene" style={{ display:"flex", alignItems:"center", justifyContent:"center", width:"100%", height:"100%" }}>
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%" style={{ maxWidth: 520 }}>
        <defs>
          <radialGradient id="bar-glow" cx="50%" cy="50%" r="50%">
            <stop offset="0%"   stopColor="rgba(5,48,206,0.9)"/>
            <stop offset="55%"  stopColor="rgba(5,48,206,0.35)"/>
            <stop offset="100%" stopColor="rgba(5,48,206,0)"/>
          </radialGradient>
        </defs>

        {/* Floor grid — horizontal rows (depth lines) */}
        {Array.from({ length: ROWS + 1 }).map((_, r) => {
          const a = gridPos(0, r);
          const b = gridPos(COLS, r);
          // Far lines fainter, near lines brighter — depth cue.
          const op = 0.10 + 0.18 * (r / ROWS);
          return (
            <line
              key={`row-${r}`}
              x1={a.x} y1={a.y} x2={b.x} y2={b.y}
              stroke={`rgba(5,48,206,${op})`} strokeWidth="0.7"
            />
          );
        })}
        {/* Floor grid — vertical columns (perspective lines) */}
        {Array.from({ length: COLS + 1 }).map((_, c) => {
          const a = gridPos(c, 0);
          const b = gridPos(c, ROWS);
          return (
            <line
              key={`col-${c}`}
              x1={a.x} y1={a.y} x2={b.x} y2={b.y}
              stroke={FEAT_STROKE_DIM} strokeWidth="0.7"
            />
          );
        })}

        {/* Bars + glowing tops */}
        {Array.from({ length: COLS }).map((_, c) => {
          const base = gridPos(c + 0.5, ROW);
          const seq  = HEIGHTS[c];
          const dur  = DURS[c];
          const ys   = seq.map((h) => base.y - h);
          const valuesH = seq.join(";");
          const valuesY = ys.join(";");
          return (
            <g key={`bar-${c}`}>
              {/* Faint shadow at base */}
              <ellipse
                cx={base.x} cy={base.y + 2}
                rx={BAR_W * 0.55} ry={BAR_W * 0.16}
                fill="rgba(5,48,206,0.10)"
              />
              {/* Wireframe rectangle bar */}
              <rect
                x={base.x - BAR_W / 2}
                width={BAR_W}
                y={base.y - seq[0]}
                height={seq[0]}
                fill="rgba(5,48,206,0.04)"
                stroke={FEAT_STROKE}
                strokeWidth="1"
              >
                <animate attributeName="height" values={valuesH} dur={`${dur}s`} repeatCount="indefinite" calcMode="spline" keySplines={Array(seq.length - 1).fill("0.45 0 0.55 1").join(";")}/>
                <animate attributeName="y"      values={valuesY} dur={`${dur}s`} repeatCount="indefinite" calcMode="spline" keySplines={Array(seq.length - 1).fill("0.45 0 0.55 1").join(";")}/>
              </rect>

              {/* Glowing top — large soft halo */}
              <circle cx={base.x} r={BAR_W * 0.85} fill="url(#bar-glow)" opacity="0.55">
                <animate attributeName="cy" values={valuesY} dur={`${dur}s`} repeatCount="indefinite" calcMode="spline" keySplines={Array(seq.length - 1).fill("0.45 0 0.55 1").join(";")}/>
              </circle>
              {/* Glowing top — bright core dot */}
              <circle cx={base.x} r="2.6" fill={FEAT_NODE}>
                <animate attributeName="cy" values={valuesY} dur={`${dur}s`} repeatCount="indefinite" calcMode="spline" keySplines={Array(seq.length - 1).fill("0.45 0 0.55 1").join(";")}/>
              </circle>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// Export all
Object.assign(window, {
  VisGlobe3D, VisRings3D, VisCard3D, VisOrbit3D, VisLineChart3D,
});
