/* eslint-disable no-undef */
// =====================================================
// Clairaut equation viz: y = x*p + psi(p)
// Default: psi(p) = -p^2/4 ; general y = Cx - C^2/4; envelope y = x^2
// Each line touches envelope at (C/2, C^2/4)
// =====================================================

const CLAIRAUT_PRESETS = {
  'square4': {
    label:     "ψ(p) = −p²/4",
    formula:   "y = xp − p²/4",
    psi:    p => -p * p / 4,
    psiP:   p => -p / 2,
    envX:   C => C / 2,
    envY:   C => (C / 2) * (C / 2),
    envFn:  x => x * x,
    envLabel: 'y = x²',
  },
  'square2': {
    label:     "ψ(p) = −p²/2",
    formula:   "y = xp − p²/2",
    psi:    p => -p * p / 2,
    psiP:   p => -p,
    envX:   C => C,
    envY:   C => C * C / 2,
    envFn:  x => x * x / 2,
    envLabel: 'y = x²/2',
  },
  'cubic': {
    label:     "ψ(p) = p³/3",
    formula:   "y = xp + p³/3",
    psi:    p => p ** 3 / 3,
    psiP:   p => p * p,
    envX:   C => -C * C,
    envY:   C => -C * C * C / 3 - C * (C * C),
    envFn:  null,
    envLabel: 'параметр.',
  },
  'cos': {
    label:     "ψ(p) = cos p",
    formula:   "y = xp + cos p",
    psi:    p => Math.cos(p),
    psiP:   p => -Math.sin(p),
    envX:   C => Math.sin(C),
    envY:   C => C * Math.sin(C) + Math.cos(C),
    envFn:  null,
    envLabel: 'параметр.',
  },
};

function ClairautViz() {
  const [presetKey, setPresetKey] = useState('square4');
  const [nLines, setNLines] = useState(16);
  const [showEnv, setShowEnv] = useState(true);
  const [selectedC, setSelectedC] = useState(2.0);

  const P = CLAIRAUT_PRESETS[presetKey];

  const canvasRef = useCanvas((ctx, W, H) => {
    const T = makeTransform({ xMin: -3, xMax: 3, yMin: -2, yMax: 5, W, H, pad: 38 });
    drawAxes(ctx, T, { tickStep: 1, xLabel: 'x', yLabel: 'y' });

    // Draw family of lines: y = Cx + psi(C)
    // colors going through a hue gradient
    const Cmin = -3, Cmax = 3;
    for (let i = 0; i < nLines; i++) {
      const t = nLines > 1 ? i / (nLines - 1) : 0.5;
      const C = Cmin + t * (Cmax - Cmin);
      const psi = P.psi(C);
      const y1 = C * T.xMin + psi;
      const y2 = C * T.xMax + psi;
      // gradient from teal to magenta — deep but visible on cream
      const hue = 175 + t * 145; // 175 teal -> 320 magenta-pink
      ctx.save();
      ctx.strokeStyle = `hsla(${hue}, 55%, 45%, 0.55)`;
      ctx.lineWidth = 1.3;
      ctx.beginPath();
      ctx.moveTo(T.X(T.xMin), T.Y(y1));
      ctx.lineTo(T.X(T.xMax), T.Y(y2));
      ctx.stroke();
      ctx.restore();
    }

    // Envelope (singular solution)
    if (showEnv) {
      const samples = 200;
      const pts = [];
      if (P.envFn) {
        for (let i = 0; i <= samples; i++) {
          const x = T.xMin + (i / samples) * (T.xMax - T.xMin);
          pts.push([x, P.envFn(x)]);
        }
      } else {
        for (let i = 0; i <= samples; i++) {
          const C = -6 + (i / samples) * 12;
          pts.push([P.envX(C), P.envY(C)]);
        }
      }
      drawPath(ctx, T, pts, { color: '#b8581f', lineWidth: 3.2 });

      // tangency dots for several C values
      for (const C of [-1.5, -0.75, 0, 0.75, 1.5]) {
        const tx = P.envX(C), ty = P.envY(C);
        if (tx > T.xMin && tx < T.xMax && ty > T.yMin && ty < T.yMax) {
          drawDot(ctx, T, tx, ty, { color: '#a8392c', stroke: '#fbf6e9', r: 4 });
        }
      }
    }

    // Highlighted line at C = selectedC
    const C = selectedC;
    const psi = P.psi(C);
    drawPath(ctx, T, [[T.xMin, C * T.xMin + psi], [T.xMax, C * T.xMax + psi]], { color: '#2a5e9e', lineWidth: 3 });
    // tangency point on envelope
    if (showEnv) {
      const tx = P.envX(C), ty = P.envY(C);
      drawDot(ctx, T, tx, ty, { color: '#a8392c', stroke: '#fbf6e9', r: 5.5 });
    }
  }, [presetKey, nLines, showEnv, selectedC]);

  return (
    <VizWrap
      title="Уравнение Клеро"
      formula={P.formula}
      captionUnder="Общее решение — семейство прямых y = Cx + ψ(C). Особое решение — огибающая, в каждой точке которой касается одна из прямых семейства. Там нарушается единственность задачи Коши."
      controls={
        <React.Fragment>
          <h4>Функция ψ(p)</h4>
          <ButtonGroup
            options={[
              { value: 'square4', label: '−p²/4' },
              { value: 'square2', label: '−p²/2' },
              { value: 'cubic',   label: 'p³/3' },
              { value: 'cos',     label: 'cos p' },
            ]}
            value={presetKey}
            setValue={setPresetKey}
          />

          <h4>Семейство прямых</h4>
          <Slider label="Число прямых" value={nLines} setValue={setNLines} min={2} max={40} step={1} formatter={(v) => Math.round(v)} />
          <Slider label="Выделенная C" value={selectedC} setValue={setSelectedC} min={-3} max={3} step={0.05} />

          <h4>Особое решение</h4>
          <Toggle label="Огибающая" value={showEnv} setValue={setShowEnv} />
          <div className="ctl-note">
            Точка касания: <span style={{ color: '#a8392c', fontFamily: 'JetBrains Mono, monospace' }}>
              ({P.envX(selectedC).toFixed(2)}, {P.envY(selectedC).toFixed(2)})
            </span>
          </div>
        </React.Fragment>
      }
    >
      <canvas ref={canvasRef} />
    </VizWrap>
  );
}

window.ClairautViz = ClairautViz;
