// Elevation Chart — render a GPX's elevation profile and export it as PNG.

window.TOOL_HANDLERS['route-elevation'] = function RouteElevationTool() {
  const G = window.MMGpx;
  const S = window.MMSports;
  const [filename, setFilename] = React.useState('');
  const [points, setPoints] = React.useState(null);
  const [color, setColor] = React.useState('#0e9488');
  const [bg, setBg] = React.useState('#ffffff');
  const [width, setWidth] = React.useState(1200);
  const [height, setHeight] = React.useState(360);

  const onFile = async (file) => {
    if (!file) return;
    try {
      const text = await file.text();
      const tracks = G.parseGPX(text);
      const pts = G.flattenPoints(tracks).filter((p) => Number.isFinite(p.ele));
      if (pts.length < 2) throw new Error('No elevation data found in this file.');
      setPoints(pts); setFilename(file.name);
    } catch (e) {
      alert(e.message);
    }
  };

  const exportPng = () => {
    if (!points) return;
    const canvas = document.createElement('canvas');
    canvas.width = width; canvas.height = height;
    const ctx = canvas.getContext('2d');
    ctx.fillStyle = bg; ctx.fillRect(0, 0, width, height);

    const eles = points.map((p) => p.ele);
    const minE = Math.min(...eles), maxE = Math.max(...eles);
    const dE = Math.max(1, maxE - minE);
    const cum = [0];
    for (let i = 1; i < points.length; i++) {
      cum.push(cum[i - 1] + G.haversine(points[i - 1].lat, points[i - 1].lon, points[i].lat, points[i].lon));
    }
    const total = cum[cum.length - 1] || 1;
    const pad = 40;
    const xAt = (i) => pad + (cum[i] / total) * (width - pad * 2);
    const yAt = (i) => height - pad - ((points[i].ele - minE) / dE) * (height - pad * 2);

    // Filled gradient under the line.
    const grad = ctx.createLinearGradient(0, pad, 0, height - pad);
    grad.addColorStop(0, color + 'aa');
    grad.addColorStop(1, color + '11');
    ctx.beginPath();
    ctx.moveTo(xAt(0), height - pad);
    for (let i = 0; i < points.length; i++) ctx.lineTo(xAt(i), yAt(i));
    ctx.lineTo(xAt(points.length - 1), height - pad);
    ctx.closePath();
    ctx.fillStyle = grad; ctx.fill();

    // Stroke
    ctx.beginPath();
    ctx.moveTo(xAt(0), yAt(0));
    for (let i = 1; i < points.length; i++) ctx.lineTo(xAt(i), yAt(i));
    ctx.lineWidth = 2.5; ctx.strokeStyle = color; ctx.lineJoin = 'round'; ctx.lineCap = 'round';
    ctx.stroke();

    // Axis labels
    ctx.fillStyle = '#475569'; ctx.font = '600 14px sans-serif';
    ctx.fillText(`${maxE.toFixed(0)} m`, pad, pad - 8);
    ctx.fillText(`${minE.toFixed(0)} m`, pad, height - pad + 18);
    ctx.textAlign = 'right';
    ctx.fillText(`${(total / 1000).toFixed(2)} km`, width - pad, height - pad + 18);
    ctx.textAlign = 'left';

    canvas.toBlob((blob) => {
      if (blob) window.downloadBlob(blob, (filename.replace(/\.gpx$/i, '') || 'elevation') + '.png');
    }, 'image/png');
  };

  if (!points) {
    return (
      <div className="mini-tool sport-tool">
        <S.SportsToolHeader title="Elevation Chart" sub="Export your route's elevation profile as a PNG." icon="mountain" accent="#0e9488" />
        <window.Dropzone onFile={onFile} title="Drop a .gpx file" hint="must contain elevation (<ele>) data" accept=".gpx" />
      </div>
    );
  }

  const stats = G.computeStats(points);

  return (
    <div className="mini-tool sport-tool">
      <S.SportsToolHeader title="Elevation Chart" sub={filename} icon="mountain" accent="#0e9488" />

      <G.ElevationChart points={points} height={260} color={color} title="Preview" />

      <div className="gpx-stats">
        <G.StatTile label="Distance"  value={`${(stats.distanceM / 1000).toFixed(2)} km`} />
        <G.StatTile label="Elev gain" value={`${stats.gainM.toFixed(0)} m`} />
        <G.StatTile label="Elev loss" value={`${stats.lossM.toFixed(0)} m`} />
        <G.StatTile label="Range"     value={`${stats.minEle?.toFixed(0) ?? '—'} – ${stats.maxEle?.toFixed(0) ?? '—'} m`} />
      </div>

      <div className="sport-input-grid">
        <div className="mini-field">
          <label className="mini-label">Line color</label>
          <input type="color" className="mini-input" value={color} onChange={(e) => setColor(e.target.value)} style={{ height: 36, padding: 4 }} />
        </div>
        <div className="mini-field">
          <label className="mini-label">Background</label>
          <input type="color" className="mini-input" value={bg} onChange={(e) => setBg(e.target.value)} style={{ height: 36, padding: 4 }} />
        </div>
        <div className="mini-field">
          <label className="mini-label">Width (px)</label>
          <input type="number" min="400" max="3000" step="100" className="mini-input" value={width} onChange={(e) => setWidth(Number(e.target.value) || 1200)} />
        </div>
        <div className="mini-field">
          <label className="mini-label">Height (px)</label>
          <input type="number" min="200" max="1200" step="20" className="mini-input" value={height} onChange={(e) => setHeight(Number(e.target.value) || 360)} />
        </div>
      </div>

      <div className="cmp-actions">
        <button className="btn btn-secondary" onClick={() => setPoints(null)}>
          <window.Icon name="upload" size={16} /> Another file
        </button>
        <button className="btn btn-primary" onClick={exportPng}>
          <window.Icon name="download" size={16} /> Download PNG
        </button>
      </div>
    </div>
  );
};
