// Shared building blocks for the "Tours virtuels stations de ski" page
// Animated snow, chairlift, mountain SVG layers, skier trails.
// All components are pure presentational; pass in colors so they adapt
// to each visual direction (Cinématique / Éditorial / Carte).

// -----------------------------------------------------------------------------
// Inject keyframes once
if (typeof document !== 'undefined' && !document.getElementById('ski-anim-styles')) {
  const css = document.createElement('style');
  css.id = 'ski-anim-styles';
  css.textContent = `
    @keyframes ski-snowfall {
      0%   { transform: translate3d(0,-20px,0); opacity: 0; }
      8%   { opacity: var(--op,0.8); }
      90%  { opacity: var(--op,0.8); }
      100% { transform: translate3d(var(--drift,20px), var(--dist,1200px), 0); opacity: 0; }
    }
    @keyframes ski-lift-cable {
      0%   { transform: translate3d(0,0,0); }
      100% { transform: translate3d(var(--lift-dx, -120px), var(--lift-dy, 60px), 0); }
    }
    @keyframes ski-lift-cable-up {
      0%   { transform: translate3d(0,0,0); }
      100% { transform: translate3d(var(--lift-dx, 120px), var(--lift-dy, -60px), 0); }
    }
    @keyframes ski-chair-sway {
      0%,100% { transform: rotate(-2deg); }
      50%     { transform: rotate(2deg); }
    }
    @keyframes ski-skier-down {
      0%   { transform: translate3d(0,0,0); opacity: 0; }
      5%   { opacity: 1; }
      95%  { opacity: 1; }
      100% { transform: translate3d(var(--skier-dx,400px), var(--skier-dy,800px), 0); opacity: 0; }
    }
    @keyframes ski-pulse {
      0%,100% { transform: scale(1); opacity: 0.7; }
      50%     { transform: scale(1.15); opacity: 0.4; }
    }
    @keyframes ski-glow {
      0%,100% { opacity: 0.4; }
      50%     { opacity: 0.9; }
    }
    @keyframes ski-float-slow {
      0%,100% { transform: translateY(0); }
      50%     { transform: translateY(-12px); }
    }
  `;
  document.head.appendChild(css);
}

// -----------------------------------------------------------------------------
// SnowField, random falling flakes inside a parent (parent must be position:relative)
const SnowField = ({ count = 80, color = '#ffffff', sizeRange = [2,5], speedRange = [6,16], areaHeight = 1200, blur = false }) => {
  // Generated once per mount so positions are stable.
  const flakes = React.useMemo(() => (
    Array.from({length: count}).map((_,i) => {
      const size = sizeRange[0] + Math.random() * (sizeRange[1]-sizeRange[0]);
      const dur = speedRange[0] + Math.random() * (speedRange[1]-speedRange[0]);
      return {
        i,
        left: Math.random() * 100,                 // %
        delay: -Math.random() * dur,               // negative so they start mid-air
        dur,
        size,
        opacity: 0.4 + Math.random() * 0.6,
        drift: (Math.random() * 80 - 40),          // px sideways
        dist: areaHeight + Math.random() * 200,    // px down
      };
    })
  ), [count, areaHeight]);

  return (
    <div style={{position:'absolute',inset:0,overflow:'hidden',pointerEvents:'none'}}>
      {flakes.map(f => (
        <div key={f.i} style={{
          position:'absolute',
          top: -10,
          left: `${f.left}%`,
          width: f.size,
          height: f.size,
          borderRadius:'50%',
          background: color,
          filter: blur ? 'blur(0.5px)' : 'none',
          boxShadow: blur ? `0 0 ${f.size*2}px ${color}80` : 'none',
          opacity: 0,
          '--op': f.opacity,
          '--drift': `${f.drift}px`,
          '--dist': `${f.dist}px`,
          animation: `ski-snowfall ${f.dur}s linear ${f.delay}s infinite`,
        }}/>
      ))}
    </div>
  );
};

// -----------------------------------------------------------------------------
// Chairlift, animated chairlift along a diagonal cable.
// Both directions: chairs going up AND chairs coming down on the parallel return line.
// Pass `theme` colors: { cable, pole, chair, chairAccent, glow }
const Chairlift = ({
  start = {x: 10, y: 80},   // % of viewBox 1000x600
  end   = {x: 90, y: 25},
  chairs = 5,
  speed = 18,               // seconds for a chair to traverse
  theme = {},
  poles = true,
}) => {
  const c = {
    cable: '#1a2240',
    pole: '#0a1840',
    chair: '#0a1840',
    chairAccent: '#48d2b1',
    glow: 'transparent',
    ...theme,
  };
  // Compute the parallel return-line offset perpendicular to the cable
  const dx = end.x - start.x;
  const dy = end.y - start.y;
  const len = Math.hypot(dx, dy);
  const nx = -dy / len, ny = dx / len; // unit normal
  const offset = 2.4; // % units in viewBox
  const start2 = { x: start.x + nx*offset, y: start.y + ny*offset };
  const end2   = { x: end.x   + nx*offset, y: end.y   + ny*offset };

  // px deltas for the chair animation (scaled to the 1000x600 viewBox)
  const liftDx = dx * 10;          // 1% of viewBox width = 10 (since width=1000)
  const liftDy = dy * 6;           // 1% of viewBox height = 6 (since height=600)

  const ChairUp = ({offset:o}) => (
    <g style={{
      animation: `ski-lift-cable-up ${speed}s linear ${-o*speed}s infinite`,
      '--lift-dx': `${liftDx}px`,
      '--lift-dy': `${liftDy}px`,
    }}>
      <g transform={`translate(${start.x*10} ${start.y*6})`}>
        {/* hanger arm */}
        <line x1="0" y1="0" x2="0" y2="8" stroke={c.chair} strokeWidth="1.2" strokeLinecap="round"/>
        <g style={{transformOrigin:'0px 4px',animation:'ski-chair-sway 3.5s ease-in-out infinite'}}>
          <line x1="0" y1="0" x2="0" y2="9" stroke={c.chair} strokeWidth="1.4" strokeLinecap="round"/>
          {/* chair body */}
          <rect x="-7" y="9" width="14" height="3.2" rx="0.6" fill={c.chair}/>
          {/* seat back */}
          <rect x="-7" y="5" width="2" height="7" rx="0.5" fill={c.chair}/>
          {/* footrest */}
          <line x1="-6" y1="12.5" x2="6" y2="12.5" stroke={c.chair} strokeWidth="0.8"/>
          {/* tiny accent */}
          <rect x="-6" y="9.7" width="12" height="0.8" fill={c.chairAccent}/>
        </g>
      </g>
    </g>
  );

  const ChairDown = ({offset:o}) => (
    <g style={{
      animation: `ski-lift-cable ${speed}s linear ${-o*speed}s infinite`,
      '--lift-dx': `${-liftDx}px`,
      '--lift-dy': `${-liftDy}px`,
    }}>
      <g transform={`translate(${end2.x*10} ${end2.y*6})`}>
        <line x1="0" y1="0" x2="0" y2="8" stroke={c.chair} strokeWidth="1.2" strokeLinecap="round"/>
        <g style={{transformOrigin:'0px 4px',animation:'ski-chair-sway 3.5s ease-in-out 1.2s infinite'}}>
          <line x1="0" y1="0" x2="0" y2="9" stroke={c.chair} strokeWidth="1.4" strokeLinecap="round"/>
          <rect x="-7" y="9" width="14" height="3.2" rx="0.6" fill={c.chair}/>
          <rect x="5" y="5" width="2" height="7" rx="0.5" fill={c.chair}/>
          <line x1="-6" y1="12.5" x2="6" y2="12.5" stroke={c.chair} strokeWidth="0.8"/>
          <rect x="-6" y="9.7" width="12" height="0.8" fill={c.chairAccent}/>
        </g>
      </g>
    </g>
  );

  const chairOffsets = Array.from({length: chairs}).map((_,i) => i/chairs);

  return (
    <svg viewBox="0 0 1000 600" style={{position:'absolute',inset:0,width:'100%',height:'100%',overflow:'visible',pointerEvents:'none'}} preserveAspectRatio="none">
      {/* glow */}
      {c.glow !== 'transparent' && (
        <line x1={start.x*10} y1={start.y*6} x2={end.x*10} y2={end.y*6}
          stroke={c.glow} strokeWidth="3" opacity="0.5" filter="blur(4px)"/>
      )}
      {/* cables */}
      <line x1={start.x*10}  y1={start.y*6}  x2={end.x*10}  y2={end.y*6}  stroke={c.cable} strokeWidth="0.8"/>
      <line x1={start2.x*10} y1={start2.y*6} x2={end2.x*10} y2={end2.y*6} stroke={c.cable} strokeWidth="0.8"/>
      {/* poles */}
      {poles && Array.from({length:4}).map((_,i) => {
        const t = 0.2 + i*0.2;
        const x = (start.x + (end.x-start.x)*t) * 10;
        const y = (start.y + (end.y-start.y)*t) * 6;
        const groundY = 600;
        return (
          <g key={i}>
            <line x1={x} y1={y} x2={x} y2={groundY} stroke={c.pole} strokeWidth="1.2" opacity="0.5"/>
            <line x1={x-6} y1={y-2} x2={x+6} y2={y-2} stroke={c.pole} strokeWidth="1.6" strokeLinecap="round"/>
          </g>
        );
      })}
      {/* chairs */}
      {chairOffsets.map((o,i) => <ChairUp key={`u${i}`} offset={o}/>)}
      {chairOffsets.map((o,i) => <ChairDown key={`d${i}`} offset={o}/>)}
    </svg>
  );
};

// -----------------------------------------------------------------------------
// MountainLayers, stacked silhouettes. Pass an array of {color, points, opacity, blur}
// `points` is a sequence of "x,y" pairs in a 1000x600 viewBox; we close to baseline.
const MountainLayers = ({ layers = [] }) => (
  <svg viewBox="0 0 1000 600" style={{position:'absolute',inset:0,width:'100%',height:'100%'}} preserveAspectRatio="none">
    {layers.map((l,i) => (
      <path key={i}
        d={`M0,600 L0,${l.points[0].y} ${l.points.map(p=>`L${p.x},${p.y}`).join(' ')} L1000,600 Z`}
        fill={l.color}
        opacity={l.opacity ?? 1}
        style={l.blur ? {filter:`blur(${l.blur}px)`} : undefined}
      />
    ))}
  </svg>
);

// -----------------------------------------------------------------------------
// Pines, scattered pine-tree silhouettes
const Pines = ({ trees = [], color = '#0a1840', opacity = 1 }) => (
  <svg viewBox="0 0 1000 600" style={{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}} preserveAspectRatio="none">
    {trees.map((t,i) => {
      const w = t.w || 14;
      const h = t.h || 36;
      return (
        <g key={i} transform={`translate(${t.x} ${t.y})`} opacity={t.opacity ?? opacity}>
          <polygon points={`0,${-h*0.05} ${-w/2},${h*0.4} ${-w/3},${h*0.4} ${-w/1.6},${h*0.75} ${-w/2.2},${h*0.75} ${-w/1.4},${h} ${w/1.4},${h} ${w/2.2},${h*0.75} ${w/1.6},${h*0.75} ${w/3},${h*0.4} ${w/2},${h*0.4}`}
            fill={color}/>
        </g>
      );
    })}
  </svg>
);

// -----------------------------------------------------------------------------
// SkierTrail, a winding ski track that descends through a section
const SkierTrail = ({ d, color = '#ffffff', width = 4, dashed = true, glow = false }) => (
  <svg viewBox="0 0 1000 600" style={{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}} preserveAspectRatio="none">
    {glow && <path d={d} fill="none" stroke={color} strokeWidth={width*2.4} opacity="0.35" style={{filter:'blur(8px)'}}/>}
    <path d={d} fill="none" stroke={color} strokeWidth={width}
      strokeDasharray={dashed ? `${width*2} ${width*1.5}` : 'none'} strokeLinecap="round" opacity="0.85"/>
  </svg>
);

// -----------------------------------------------------------------------------
// TopoLines, topographic contour lines for the "Carte" direction
const TopoLines = ({ color = '#0a1840', opacity = 0.12 }) => (
  <svg viewBox="0 0 1000 600" style={{position:'absolute',inset:0,width:'100%',height:'100%',pointerEvents:'none'}} preserveAspectRatio="none">
    {Array.from({length: 10}).map((_,i) => {
      const r = 60 + i*55;
      return (
        <ellipse key={i} cx="500" cy="320" rx={r*1.4} ry={r*0.6}
          fill="none" stroke={color} strokeWidth="1" opacity={opacity * (1 - i*0.05)}/>
      );
    })}
  </svg>
);

// -----------------------------------------------------------------------------
// Star sky, for the cinematic night-mode hero
const StarField = ({ count = 60, color = '#ffffff' }) => {
  const stars = React.useMemo(() => Array.from({length: count}).map((_,i) => ({
    i, x: Math.random()*100, y: Math.random()*60, r: 0.4 + Math.random()*1.6,
    d: 1.5 + Math.random()*3, delay: -Math.random()*4,
  })), [count]);
  return (
    <div style={{position:'absolute',inset:0,pointerEvents:'none'}}>
      {stars.map(s => (
        <div key={s.i} style={{
          position:'absolute', left:`${s.x}%`, top:`${s.y}%`,
          width: s.r*2, height: s.r*2, borderRadius:'50%', background: color,
          boxShadow:`0 0 ${s.r*4}px ${color}80`,
          animation:`ski-glow ${s.d}s ease-in-out ${s.delay}s infinite`,
        }}/>
      ))}
    </div>
  );
};

window.SnowField = SnowField;
window.Chairlift = Chairlift;
window.MountainLayers = MountainLayers;
window.Pines = Pines;
window.SkierTrail = SkierTrail;
window.TopoLines = TopoLines;
window.StarField = StarField;
