// lvpai-scene.jsx — 程序化真实感风景生成器（玉龙雪山·蓝月谷）
// 多层山脊 + 大气透视 + 雪顶 + 湖面倒影 + 云层 + 阳光 + 前景松林。
// 由 seed 决定构图（山形/云/水/光/前景），同一 tone 也能生成各异的画面。

function lvMul(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0; var t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
function lvLerp(a, b, t) { return a + (b - a) * t; }
function lvHex(h) { h = h.replace('#', ''); return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)]; }
function lvRgb(a) { return '#' + a.map(function (x) { return Math.max(0, Math.min(255, Math.round(x))).toString(16).padStart(2, '0'); }).join(''); }
function lvMix(a, b, t) { var A = lvHex(a), B = lvHex(b); return lvRgb([lvLerp(A[0], B[0], t), lvLerp(A[1], B[1], t), lvLerp(A[2], B[2], t)]); }

// base palette per tone: sky gradient + nearest-mountain dark + sun + flags
const SCENE_PAL = {
  lake: { skyTop: '#e8f2ed', skyBot: '#bfe0d6', dark: '#1d5046', sun: '#fffdf5', glow: '#f4fbf8', snow: true, water: '#3f7e70' },
  snow: { skyTop: '#eef4fa', skyBot: '#cbdcec', dark: '#33506b', sun: '#ffffff', glow: '#f0f6fc', snow: true, water: '#4e6b88' },
  gold: { skyTop: '#fce7d0', skyBot: '#f3c88a', dark: '#6d4222', sun: '#fff2cf', glow: '#ffeec8', snow: true, water: '#b07e3f' },
  dusk: { skyTop: '#e7ddf0', skyBot: '#bba8d4', dark: '#2c2350', sun: '#f6ecd4', glow: '#ddccef', snow: true, water: '#5b4b80' },
  pine: { skyTop: '#dde9e3', skyBot: '#aecabd', dark: '#143229', sun: '#f3f7ef', glow: '#e3efe9', snow: false, water: '#2f5d52' },
  stone:{ skyTop: '#f1ece2', skyBot: '#dcd2c1', dark: '#564c3b', sun: '#fffaf0', glow: '#f6f1e8', snow: true, water: '#8a7c61' },
};

function Scene({ tone = 'lake', seed = 0.5, style }) {
  const p = SCENE_PAL[tone] || SCENE_PAL.lake;
  const uid = React.useMemo(() => 's' + Math.random().toString(36).slice(2, 8), []);

  const model = React.useMemo(() => {
    const rand = lvMul(Math.floor((seed % 1) * 1e6) + 7);
    const X0 = -40, X1 = 440, W = X1 - X0;

    // scene flags
    const hasWater = rand() > 0.42;
    const cloudy = rand() > 0.45;
    const overcast = tone === 'snow' && rand() > 0.5;
    const hasPines = !hasWater && (tone === 'pine' || rand() > 0.55);
    const sunrise = tone === 'gold';
    const horizon = hasWater ? 150 + Math.floor(rand() * 16) : 300;

    // sun
    const sun = {
      x: 70 + rand() * 260,
      y: sunrise ? 96 + rand() * 22 : 38 + rand() * 50,
      r: (sunrise ? 30 : 16) + rand() * 12,
      show: !overcast,
    };

    // ridge builder
    function ridge(baseY, amp, seg, peaky) {
      const pts = [];
      let peakAt = peaky ? Math.floor(seg * (0.3 + rand() * 0.4)) : -1;
      for (let i = 0; i <= seg; i++) {
        const x = X0 + W * i / seg;
        let h = (0.2 + rand() * 0.7) * amp;
        if (i === peakAt) h = amp * (1.05 + rand() * 0.25);
        if (i === peakAt - 1 || i === peakAt + 1) h = amp * (0.7 + rand() * 0.2);
        pts.push([Math.round(x), Math.round(baseY - h)]);
      }
      const minY = Math.min.apply(null, pts.map(q => q[1]));
      return { pts, minY };
    }

    // 5 layers far→near; nearest tall & peaky
    const bottom = hasWater ? horizon : 305;
    const layers = [];
    const defs = [
      { baseY: horizon === 300 ? 150 : horizon, amp: 22, seg: 9, peaky: false, t: 0.22 },
      { baseY: horizon === 300 ? 168 : horizon + 2, amp: 40, seg: 8, peaky: false, t: 0.40 },
      { baseY: horizon === 300 ? 186 : horizon + 4, amp: 64, seg: 7, peaky: true, t: 0.60 },
      { baseY: horizon === 300 ? 210 : horizon + 8, amp: 92, seg: 6, peaky: true, t: 0.82 },
      { baseY: horizon === 300 ? 250 : horizon + 14, amp: 120, seg: 6, peaky: true, t: 1.0 },
    ];
    defs.forEach((d, k) => {
      const r = ridge(d.baseY, d.amp, d.seg, d.peaky);
      const color = lvMix(p.skyBot, p.dark, d.t);
      const ptsStr = r.pts.map(q => q.join(',')).join(' ') + ` ${X1},${bottom} ${X0},${bottom}`;
      // snow line for the two nearest peaky ridges
      const snowLine = (p.snow && k >= 3) ? r.minY + d.amp * (0.30 + rand() * 0.12) : null;
      layers.push({ ptsStr, color, snowLine, pts: r.pts, k, near: k === 4 });
    });

    // clouds
    const clouds = [];
    if (cloudy) {
      const n = 1 + Math.floor(rand() * 3);
      for (let i = 0; i < n; i++) clouds.push({ x: 30 + rand() * 340, y: 22 + rand() * 60, rx: 30 + rand() * 46, ry: 7 + rand() * 8, o: 0.28 + rand() * 0.4 });
    }

    // foreground pines
    const pines = [];
    if (hasPines) {
      const n = 3 + Math.floor(rand() * 5);
      for (let i = 0; i < n; i++) { const x = 20 + rand() * 360, h = 40 + rand() * 55; pines.push({ x, h, w: 9 + rand() * 7 }); }
    }

    // birds
    const birds = rand() > 0.72 ? Array.from({ length: 2 + Math.floor(rand() * 3) }, () => ({ x: 60 + rand() * 240, y: 40 + rand() * 40, s: 4 + rand() * 3 })) : [];

    return { hasWater, horizon, sun, layers, clouds, pines, birds, warm: sunrise || tone === 'gold' };
  }, [seed, tone]);

  const { hasWater, horizon, sun, layers, clouds, pines, birds } = model;

  return (
    <svg viewBox="0 0 400 300" preserveAspectRatio="xMidYMid slice"
      style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block', ...style }}>
      <defs>
        <linearGradient id={uid + 'sky'} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor={p.skyTop} /><stop offset="1" stopColor={p.skyBot} />
        </linearGradient>
        <linearGradient id={uid + 'wat'} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor={lvMix(p.skyBot, p.water, 0.4)} /><stop offset="1" stopColor={lvMix(p.water, '#0a1410', 0.35)} />
        </linearGradient>
        <radialGradient id={uid + 'glow'} cx="0.5" cy="0.5" r="0.5">
          <stop offset="0" stopColor={p.glow} stopOpacity="0.9" /><stop offset="1" stopColor={p.glow} stopOpacity="0" />
        </radialGradient>
        <filter id={uid + 'blur'} x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="6" /></filter>
        {layers.filter(l => l.snowLine != null).map(l => (
          <clipPath key={l.k} id={uid + 'clip' + l.k}><polygon points={l.ptsStr} /></clipPath>
        ))}
      </defs>

      {/* sky */}
      <rect x="0" y="0" width="400" height={hasWater ? horizon : 300} fill={`url(#${uid}sky)`} />
      {/* sun glow + disc */}
      {sun.show && <g>
        <rect x={sun.x - 100} y={sun.y - 100} width="200" height="200" fill={`url(#${uid}glow)`} />
        <circle cx={sun.x} cy={sun.y} r={sun.r} fill={p.sun} opacity="0.95" />
      </g>}
      {/* clouds */}
      {clouds.map((c, i) => (
        <ellipse key={i} cx={c.x} cy={c.y} rx={c.rx} ry={c.ry} fill="#ffffff" opacity={c.o} filter={`url(#${uid}blur)`} />
      ))}
      {/* birds */}
      {birds.map((b, i) => (
        <path key={i} d={`M${b.x - b.s} ${b.y} Q${b.x} ${b.y - b.s * 0.8} ${b.x} ${b.y} Q${b.x} ${b.y - b.s * 0.8} ${b.x + b.s} ${b.y}`}
          stroke={lvMix(p.dark, p.skyBot, 0.35)} strokeWidth="1.2" fill="none" strokeLinecap="round" opacity="0.55" />
      ))}

      {/* mountain layers (far→near) */}
      {layers.map(l => (
        <g key={l.k}>
          <polygon points={l.ptsStr} fill={l.color} />
          {l.snowLine != null && (
            <rect x="-40" y="0" width="480" height={l.snowLine} fill={p.snow ? lvMix('#ffffff', p.skyBot, 0.12) : '#fff'} opacity="0.92" clipPath={`url(#${uid}clip${l.k})`} />
          )}
        </g>
      ))}

      {/* water + reflection */}
      {hasWater && <g>
        <rect x="0" y={horizon} width="400" height={300 - horizon} fill={`url(#${uid}wat)`} />
        {/* mirrored nearest ridge */}
        <g opacity="0.30" transform={`translate(0 ${2 * horizon}) scale(1 -1)`}>
          <polygon points={layers[4].ptsStr} fill={layers[4].color} />
        </g>
        {/* sun glitter */}
        {sun.show && <rect x={sun.x - 14} y={horizon} width="28" height={300 - horizon} fill={p.sun} opacity="0.14" />}
        {/* shimmer */}
        <g fill="#ffffff">
          <rect x="0" y={horizon + 8} width="400" height="1.4" opacity="0.12" />
          <rect x="0" y={horizon + 24} width="400" height="1.4" opacity="0.08" />
          <rect x="0" y={horizon + 44} width="400" height="1.4" opacity="0.05" />
        </g>
        <rect x="0" y={horizon - 1} width="400" height="1.6" fill="#ffffff" opacity="0.34" />
      </g>}

      {/* foreground pines */}
      {pines.map((t, i) => (
        <g key={i} fill={lvMix(p.dark, '#0a1410', 0.25)}>
          <polygon points={`${t.x},${300 - t.h} ${t.x - t.w},${300} ${t.x + t.w},${300}`} />
          <polygon points={`${t.x},${300 - t.h - 8} ${t.x - t.w * 0.7},${300 - t.h * 0.5} ${t.x + t.w * 0.7},${300 - t.h * 0.5}`} />
        </g>
      ))}

      {/* color grade */}
      <rect x="0" y="0" width="400" height="300" fill={model.warm ? '#ff9a3c' : '#3a6ea0'} opacity="0.05" />
    </svg>
  );
}

window.Scene = Scene;
window.SCENE_PAL = SCENE_PAL;
