// Activity Share Card — generate a transparent PNG of your run (route +
// stats) ready to drop into Instagram Stories, X, etc. A free re-build of
// Strava's subscribers-only Share Activity feature.
//
// Renders directly to a canvas with NO background fill, so the exported
// PNG carries a real alpha channel. The preview shows a checkerboard so
// users can see the transparency.

const STRAVA_ORANGE = '#fc4c02';

const SHARE_SIZES = {
  story:     { w: 1080, h: 1920, label: 'Story · 1080×1920 · 9:16' },
  square:    { w: 1080, h: 1080, label: 'Square · 1080×1080 · 1:1' },
  landscape: { w: 1920, h: 1080, label: 'Landscape · 1920×1080 · 16:9' },
  postcard:  { w: 1500, h: 2100, label: 'Postcard · 1500×2100 · A6' },
};

const LAYOUTS = [
  { id: 'route-stats', label: 'Route + 3 stats',  needsRoute: true },
  { id: 'route-grid',  label: 'Route + 6 stats',  needsRoute: true },
  { id: 'stats-trio',  label: 'Stats trio',       needsRoute: false },
  { id: 'stats-grid',  label: 'Stats grid (6)',   needsRoute: false },
  { id: 'hero',        label: 'Hero distance',    needsRoute: false },
  { id: 'route-only',  label: 'Route only',       needsRoute: true },
];

window.TOOL_HANDLERS['activity-share'] = function ActivityShareTool() {
  const G = window.MMGpx;
  const S = window.MMSports;
  const canvasRef = React.useRef(null);

  const [filename, setFilename] = React.useState('');
  const [tracks, setTracks] = React.useState(null);
  const [error, setError] = React.useState('');

  // Manual stat overrides — used when there's no GPX or to add HR/cal.
  const [manualMode, setManualMode] = React.useState(false);
  const [m, setM] = React.useState({
    distance: '10.00',
    time: '55:11',
    pace: '5:31',
    elev: '28',
    kcal: '775',
    hr: '186',
  });

  const [layout, setLayout]       = React.useState('route-stats');
  const [size, setSize]           = React.useState('story');
  const [routeColor, setRouteCol] = React.useState(STRAVA_ORANGE);
  const [textColor, setTextCol]   = React.useState('#ffffff');
  const [accent, setAccent]       = React.useState(STRAVA_ORANGE);
  const [label, setLabel]         = React.useState('MY RUN');
  const [showLabel, setShowLabel] = React.useState(true);
  const [unit, setUnit]           = React.useState('km');
  const [showElev, setShowElev]   = React.useState(true);
  const [showCal, setShowCal]     = React.useState(true);
  const [showHr, setShowHr]       = React.useState(false);
  const [routeStroke, setStroke]  = React.useState(14);

  // ----- File handling -----
  const onFile = async (f) => {
    if (!f) return;
    setError('');
    try {
      const text = await f.text();
      const parsed = G.parseGPX(text);
      if (!parsed.length) throw new Error('No tracks in this GPX file.');
      setTracks(parsed); setFilename(f.name);
      setManualMode(false);
    } catch (e) { setError(e.message); }
  };

  const points = React.useMemo(() => tracks ? G.flattenPoints(tracks) : [], [tracks]);
  const stats = React.useMemo(() => points.length ? G.computeStats(points) : null, [points]);

  // ----- Compute display values from GPX or manual -----
  const display = React.useMemo(() => {
    let distM = 0, durS = 0, paceSecPerKm = 0, gainM = 0;
    if (stats && !manualMode) {
      distM = stats.distanceM;
      durS  = stats.durationS;
      paceSecPerKm = durS && distM ? durS / (distM / 1000) : 0;
      gainM = stats.gainM;
    } else {
      // Manual: distance assumed in km, time mm:ss or hh:mm:ss.
      distM = (Number(m.distance) || 0) * 1000;
      durS  = S.parseTimeToSeconds(m.time) || 0;
      paceSecPerKm = S.parseTimeToSeconds(m.pace) || (durS && distM ? durS / (distM / 1000) : 0);
      gainM = Number(m.elev) || 0;
    }

    // Convert distance + pace to selected unit.
    const distVal = unit === 'mi' ? distM / 1609.344 : distM / 1000;
    const distStr = `${distVal.toFixed(2)} ${unit}`;
    const paceUnitSec = unit === 'mi' ? S.paceKmToMile(paceSecPerKm) : paceSecPerKm;
    const paceStr = `${S.formatPace(paceUnitSec)} /${unit}`;

    // Strava-style "55m 11s" / "1h 32m" — no leading zeros.
    let timeStr = '—';
    if (durS > 0) {
      const t = Math.round(durS);
      const h = Math.floor(t / 3600), mn = Math.floor((t % 3600) / 60), sc = t % 60;
      timeStr = h > 0 ? `${h}h ${mn}m` : `${mn}m ${sc}s`;
    }

    return {
      distance: distStr,
      time: timeStr,
      pace: paceStr,
      elev: `${Math.round(gainM)} m`,
      kcal: `${m.kcal} Cal`,
      hr: `${m.hr} bpm`,
    };
  }, [stats, manualMode, m, unit]);

  // ----- Drawing primitives -----
  const fontFamily = '"Inter", "Helvetica Neue", Helvetica, Arial, sans-serif';

  function projectRoute(pts, x, y, w, h, pad = 20) {
    return G.projectToSVG(pts, w, h, pad).map((p) => ({ x: x + p.x, y: y + p.y }));
  }
  function strokeRoute(ctx, pts, color, lw) {
    if (pts.length < 2) return;
    ctx.save();
    ctx.strokeStyle = color;
    ctx.lineWidth = lw;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.shadowColor = 'rgba(0,0,0,.18)';
    ctx.shadowBlur = lw * 0.7;
    ctx.beginPath();
    pts.forEach((p, i) => i === 0 ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y));
    ctx.stroke();
    ctx.restore();
    // start/end dots
    const r = Math.max(6, lw * 0.55);
    [{ p: pts[0], c: '#22c55e' }, { p: pts[pts.length - 1], c: '#ef4444' }].forEach(({ p, c }) => {
      ctx.beginPath();
      ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
      ctx.fillStyle = c; ctx.fill();
      ctx.lineWidth = Math.max(2, lw * 0.18); ctx.strokeStyle = '#ffffff';
      ctx.stroke();
    });
  }
  function fillText(ctx, text, x, y, sizePx, weight = 400, align = 'left', color) {
    ctx.font = `${weight} ${sizePx}px ${fontFamily}`;
    ctx.textAlign = align;
    ctx.textBaseline = 'top';
    ctx.fillStyle = color;
    ctx.fillText(text, x, y);
  }
  function withAlpha(hex, alpha) {
    if (!/^#[0-9a-f]{6}$/i.test(hex)) return hex;
    const a = Math.round(alpha * 255).toString(16).padStart(2, '0');
    return hex + a;
  }
  function drawBrand(ctx, w, h, x, y, opts) {
    if (!opts.showLabel) return;
    const sizeS = Math.round(h * 0.018);
    const padX = 14, padY = 8;
    ctx.font = `900 ${sizeS}px ${fontFamily}`;
    ctx.textBaseline = 'top';
    const metrics = ctx.measureText(opts.label);
    const boxW = metrics.width + padX * 2;
    const boxH = sizeS + padY * 2;
    ctx.save();
    ctx.fillStyle = opts.accent;
    // rounded rect
    const r = boxH / 2;
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.arcTo(x + boxW, y, x + boxW, y + boxH, r);
    ctx.arcTo(x + boxW, y + boxH, x, y + boxH, r);
    ctx.arcTo(x, y + boxH, x, y, r);
    ctx.arcTo(x, y, x + boxW, y, r);
    ctx.closePath();
    ctx.fill();
    ctx.fillStyle = '#ffffff';
    ctx.fillText(opts.label, x + padX, y + padY);
    ctx.restore();
    return { width: boxW, height: boxH };
  }
  function drawStat(ctx, x, y, label, value, opts) {
    const labelSize = Math.round(opts.h * 0.0125);
    const valueSize = Math.round(opts.h * 0.034);
    fillText(ctx, label, x, y, labelSize, 700, 'left', withAlpha(opts.textColor, 0.7));
    fillText(ctx, value, x, y + labelSize + 6, valueSize, 900, 'left', opts.textColor);
    return labelSize + valueSize + 10;
  }

  // ----- Layouts -----
  function layoutRouteStats(ctx, w, h, hasRoute) {
    const padX = w * 0.07, padY = h * 0.06;
    const routeBoxH = h * (hasRoute ? 0.55 : 0);
    if (hasRoute && points.length) {
      const proj = projectRoute(points, padX, padY, w - padX * 2, routeBoxH, 20);
      strokeRoute(ctx, proj, routeColor, routeStroke);
    }
    // Brand badge under route
    const brandY = padY + routeBoxH + h * 0.04;
    drawBrand(ctx, w, h, padX, brandY, { showLabel, label, accent });

    // 3 stats row
    const rowY = brandY + h * 0.06;
    const cols = [
      { l: 'Distance', v: display.distance },
      { l: 'Pace',     v: display.pace },
      { l: 'Time',     v: display.time },
    ];
    const colW = (w - padX * 2) / cols.length;
    cols.forEach((c, i) => drawStat(ctx, padX + colW * i, rowY, c.l, c.v, { textColor, h }));
  }

  function layoutRouteGrid(ctx, w, h, hasRoute) {
    const padX = w * 0.07, padY = h * 0.06;
    const routeBoxH = h * (hasRoute ? 0.42 : 0);
    if (hasRoute && points.length) {
      const proj = projectRoute(points, padX, padY, w - padX * 2, routeBoxH, 20);
      strokeRoute(ctx, proj, routeColor, routeStroke);
    }
    const brandY = padY + routeBoxH + h * 0.03;
    drawBrand(ctx, w, h, padX, brandY, { showLabel, label, accent });

    const rowY = brandY + h * 0.06;
    const stats = [
      { l: 'Distance', v: display.distance },
      { l: 'Pace',     v: display.pace },
      { l: 'Time',     v: display.time },
    ];
    if (showCal)  stats.push({ l: 'Cal',       v: display.kcal });
    if (showElev) stats.push({ l: 'Elev Gain', v: display.elev });
    if (showHr)   stats.push({ l: 'Avg HR',    v: display.hr });

    const cols = 3;
    const colW = (w - padX * 2) / cols;
    const rowH = h * 0.09;
    stats.forEach((c, i) => {
      const r = Math.floor(i / cols), col = i % cols;
      drawStat(ctx, padX + colW * col, rowY + rowH * r, c.l, c.v, { textColor, h });
    });
  }

  function layoutStatsTrio(ctx, w, h) {
    const padX = w * 0.07;
    const cy = h * 0.5;
    drawBrand(ctx, w, h, padX, cy - h * 0.075, { showLabel, label, accent });

    const cols = [
      { l: 'Distance', v: display.distance },
      { l: 'Pace',     v: display.pace },
      { l: 'Time',     v: display.time },
    ];
    const colW = (w - padX * 2) / cols.length;
    const rowY = cy + h * 0.01;
    cols.forEach((c, i) => drawStat(ctx, padX + colW * i, rowY, c.l, c.v, { textColor, h }));
  }

  function layoutStatsGrid(ctx, w, h) {
    const padX = w * 0.07;
    const top = h * 0.32;
    drawBrand(ctx, w, h, padX, top - h * 0.06, { showLabel, label, accent });

    const stats = [
      { l: 'Distance', v: display.distance },
      { l: 'Pace',     v: display.pace },
      { l: 'Time',     v: display.time },
    ];
    if (showCal)  stats.push({ l: 'Cal',       v: display.kcal });
    if (showElev) stats.push({ l: 'Elev Gain', v: display.elev });
    if (showHr)   stats.push({ l: 'Avg HR',    v: display.hr });

    const cols = 3;
    const colW = (w - padX * 2) / cols;
    const rowH = h * 0.09;
    stats.forEach((c, i) => {
      const r = Math.floor(i / cols), col = i % cols;
      drawStat(ctx, padX + colW * col, top + rowH * r, c.l, c.v, { textColor, h });
    });
  }

  function layoutHero(ctx, w, h) {
    const padX = w * 0.07;
    drawBrand(ctx, w, h, padX, h * 0.36, { showLabel, label, accent });

    // Big distance number
    const numSize = Math.round(h * 0.16);
    const unitSize = Math.round(h * 0.04);
    const distNum = display.distance.split(' ')[0];
    ctx.font = `900 ${numSize}px ${fontFamily}`;
    ctx.textBaseline = 'top';
    ctx.textAlign = 'left';
    ctx.fillStyle = textColor;
    ctx.fillText(distNum, padX, h * 0.42);
    ctx.font = `700 ${unitSize}px ${fontFamily}`;
    ctx.fillStyle = withAlpha(textColor, 0.65);
    const dW = ctx.measureText(distNum).width;
    ctx.font = `900 ${numSize}px ${fontFamily}`;
    const numW = ctx.measureText(distNum).width;
    ctx.font = `700 ${unitSize}px ${fontFamily}`;
    ctx.fillText(unit, padX + numW + 14, h * 0.42 + numSize - unitSize - 6);

    // Stats row below the big number
    const subY = h * 0.42 + numSize + h * 0.02;
    const cols = [
      { l: 'Pace', v: display.pace },
      { l: 'Time', v: display.time },
    ];
    if (showElev) cols.push({ l: 'Elev', v: display.elev });
    const colW = (w - padX * 2) / cols.length;
    cols.forEach((c, i) => drawStat(ctx, padX + colW * i, subY, c.l, c.v, { textColor, h }));
  }

  function layoutRouteOnly(ctx, w, h) {
    const padX = w * 0.07, padY = h * 0.06;
    if (points.length) {
      const proj = projectRoute(points, padX, padY, w - padX * 2, h - padY * 2, 30);
      strokeRoute(ctx, proj, routeColor, routeStroke);
    }
    drawBrand(ctx, w, h, padX, h - padY - 56, { showLabel, label, accent });
  }

  // ----- Main render -----
  const render = React.useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const { w, h } = SHARE_SIZES[size];
    canvas.width = w; canvas.height = h;
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, w, h);
    const hasRoute = points.length >= 2 && !manualMode;

    if (layout === 'route-stats')  layoutRouteStats(ctx, w, h, hasRoute);
    else if (layout === 'route-grid') layoutRouteGrid(ctx, w, h, hasRoute);
    else if (layout === 'stats-trio') layoutStatsTrio(ctx, w, h);
    else if (layout === 'stats-grid') layoutStatsGrid(ctx, w, h);
    else if (layout === 'hero')       layoutHero(ctx, w, h);
    else if (layout === 'route-only') layoutRouteOnly(ctx, w, h);
  }, [size, layout, points, manualMode, display, textColor, routeColor, accent, label, showLabel, showCal, showElev, showHr, routeStroke]);

  React.useEffect(() => { render(); }, [render]);

  const download = () => {
    const canvas = canvasRef.current; if (!canvas) return;
    canvas.toBlob((blob) => {
      if (!blob) return;
      window.downloadBlob(blob, (filename.replace(/\.gpx$/i, '') || 'activity') + '-share.png');
    }, 'image/png');
    window.mmTrackComplete?.('activity-share', { success: true });
  };

  // ----- UI -----
  const layoutsForState = LAYOUTS.filter((l) => !l.needsRoute || (points.length >= 2 && !manualMode));
  const sizeMeta = SHARE_SIZES[size];

  return (
    <div className="mini-tool sport-tool">
      <S.SportsToolHeader title="Activity Share Card" sub="Transparent PNG of your route + stats — paste straight into Stories." icon="image" accent="#fc4c02" />

      {/* Source */}
      <div className="share-source-row">
        <div style={{ flex: 1 }}>
          {tracks ? (
            <div className="share-source-loaded">
              <window.Icon name="check" size={14} strokeWidth={2.5} />
              <span style={{ fontWeight: 700 }}>{filename}</span>
              <span className="cmp-meta" style={{ marginLeft: 8 }}>
                {(stats.distanceM / 1000).toFixed(2)} km · {points.length.toLocaleString()} pts
              </span>
              <button className="filter-pill" onClick={() => { setTracks(null); setFilename(''); }} style={{ marginLeft: 'auto' }}>
                <window.Icon name="x" size={12} /> Remove
              </button>
            </div>
          ) : (
            <window.Dropzone onFile={onFile}
                             title="Drop a .gpx file"
                             hint="or fill in stats manually below"
                             accept=".gpx,application/gpx+xml,application/xml" />
          )}
          {error && <div style={{ marginTop: 10, color: '#c8321f', fontSize: 13 }}>{error}</div>}
        </div>
        <button type="button" className={`sport-mode-btn ${manualMode ? 'active' : ''}`}
                onClick={() => setManualMode((v) => !v)}
                style={{ alignSelf: 'flex-start', marginLeft: 12 }}>
          {manualMode ? 'Manual ON' : 'Use manual stats'}
        </button>
      </div>

      {manualMode && (
        <div className="sport-input-grid" style={{ marginTop: 14 }}>
          <div className="mini-field">
            <label className="mini-label">Distance (km)</label>
            <input type="number" className="mini-input" value={m.distance} step="0.01"
                   onChange={(e) => setM({ ...m, distance: e.target.value })} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Time</label>
            <input type="text" className="mini-input" value={m.time} placeholder="55:11"
                   onChange={(e) => setM({ ...m, time: e.target.value })} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Pace (mm:ss / km)</label>
            <input type="text" className="mini-input" value={m.pace}
                   onChange={(e) => setM({ ...m, pace: e.target.value })} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Elev gain (m)</label>
            <input type="number" className="mini-input" value={m.elev}
                   onChange={(e) => setM({ ...m, elev: e.target.value })} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Calories</label>
            <input type="number" className="mini-input" value={m.kcal}
                   onChange={(e) => setM({ ...m, kcal: e.target.value })} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Avg HR</label>
            <input type="number" className="mini-input" value={m.hr}
                   onChange={(e) => setM({ ...m, hr: e.target.value })} />
          </div>
        </div>
      )}

      {/* Preview */}
      <div className={`share-preview-wrap share-aspect-${size}`}>
        <div className="share-preview-stage">
          <canvas ref={canvasRef} className="share-preview-canvas" />
        </div>
        <div className="share-preview-meta">
          <span>{sizeMeta.label}</span>
          <span className="share-meta-sep">·</span>
          <span>Transparent PNG</span>
        </div>
      </div>

      {/* Customisation */}
      <div className="share-controls">
        <div className="share-ctl-group">
          <label className="mini-label">Layout</label>
          <div className="share-pill-row">
            {layoutsForState.map((l) => (
              <button key={l.id} type="button"
                      className={`sport-mode-btn ${layout === l.id ? 'active' : ''}`}
                      onClick={() => setLayout(l.id)}>{l.label}</button>
            ))}
          </div>
        </div>

        <div className="share-ctl-group">
          <label className="mini-label">Canvas size</label>
          <div className="share-pill-row">
            {Object.entries(SHARE_SIZES).map(([k, v]) => (
              <button key={k} type="button"
                      className={`sport-mode-btn ${size === k ? 'active' : ''}`}
                      onClick={() => setSize(k)}>{v.label.split(' · ')[0]}</button>
            ))}
          </div>
        </div>

        <div className="sport-input-grid" style={{ marginTop: 8 }}>
          <div className="mini-field">
            <label className="mini-label">Route colour</label>
            <input type="color" className="mini-input" value={routeColor}
                   onChange={(e) => setRouteCol(e.target.value)} style={{ height: 36, padding: 4 }} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Text colour</label>
            <input type="color" className="mini-input" value={textColor}
                   onChange={(e) => setTextCol(e.target.value)} style={{ height: 36, padding: 4 }} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Badge colour</label>
            <input type="color" className="mini-input" value={accent}
                   onChange={(e) => setAccent(e.target.value)} style={{ height: 36, padding: 4 }} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Distance unit</label>
            <select className="mini-input" value={unit} onChange={(e) => setUnit(e.target.value)}>
              <option value="km">km</option>
              <option value="mi">mi</option>
            </select>
          </div>
          <div className="mini-field">
            <label className="mini-label">Badge label</label>
            <input type="text" className="mini-input" maxLength="24"
                   value={label} onChange={(e) => setLabel(e.target.value.toUpperCase())} />
          </div>
          <div className="mini-field">
            <label className="mini-label">Route line width</label>
            <input type="number" min="4" max="40" className="mini-input"
                   value={routeStroke} onChange={(e) => setStroke(Math.max(4, Math.min(40, Number(e.target.value) || 14)))} />
          </div>
        </div>

        <div className="share-toggle-row">
          <label className="pw-opt"><input type="checkbox" checked={showLabel} onChange={(e) => setShowLabel(e.target.checked)} /> Show badge</label>
          <label className="pw-opt"><input type="checkbox" checked={showElev} onChange={(e) => setShowElev(e.target.checked)} /> Show Elev Gain</label>
          <label className="pw-opt"><input type="checkbox" checked={showCal} onChange={(e) => setShowCal(e.target.checked)} /> Show Calories</label>
          <label className="pw-opt"><input type="checkbox" checked={showHr} onChange={(e) => setShowHr(e.target.checked)} /> Show Avg HR</label>
        </div>

        <div className="share-presets">
          <span className="mini-label" style={{ marginBottom: 0, marginRight: 8 }}>Quick themes:</span>
          <button type="button" className="share-preset" onClick={() => { setRouteCol('#fc4c02'); setTextCol('#ffffff'); setAccent('#fc4c02'); }}>Strava orange</button>
          <button type="button" className="share-preset" onClick={() => { setRouteCol('#22c55e'); setTextCol('#ffffff'); setAccent('#16a34a'); }}>MagicTools green</button>
          <button type="button" className="share-preset" onClick={() => { setRouteCol('#000000'); setTextCol('#000000'); setAccent('#000000'); }}>Mono dark</button>
          <button type="button" className="share-preset" onClick={() => { setRouteCol('#ffffff'); setTextCol('#ffffff'); setAccent('#ffffff'); }}>Mono light</button>
          <button type="button" className="share-preset" onClick={() => { setRouteCol('#2563eb'); setTextCol('#ffffff'); setAccent('#1d4ed8'); }}>Cobalt</button>
        </div>
      </div>

      <div className="cmp-actions">
        <button className="btn btn-primary" onClick={download}>
          <window.Icon name="download" size={16} /> Download transparent PNG
        </button>
      </div>

      <div className="sport-helper">
        Tip: in Instagram Stories, add this PNG as a sticker on top of your race photo. Because the background is fully transparent, only the route and text show — no white box.
      </div>
    </div>
  );
};
