/**
 * MissionPlanner.jsx — Waypoint editor, patrol route builder, geofence editor,
 * mission templates, scheduler, and live execution overlay.
 *
 * Sub-views: Map | Waypoints | Routes | Geofences | Templates | Schedule | Execute
 *
 * Canvas coordinate space:
 *   World frame (metres, ROS convention): x→east, y→north
 *   Canvas: cx = W/2 + pan.x + world.x*zoom,  cy = H/2 + pan.y - world.y*zoom
 *
 * Multi-robot: integrates with useFleet (imported lazily to avoid dep if unused).
 */

import { useState, useRef, useEffect, useCallback } from 'react';
import { useMissions } from '../hooks/useMissions.js';
import { useFleet }    from '../hooks/useFleet.js';

// ── Constants ────────────────────────────────────────────────────────────────

const VIEWS = ['Map','Waypoints','Routes','Geofences','Templates','Schedule','Execute'];

const ROUTE_TYPE_LABELS = { loop: 'Loop', oneshot: 'One-shot', pingpong: 'Ping-pong' };
const DAY_LABELS = ['Su','Mo','Tu','We','Th','Fr','Sa'];

// ── Canvas helpers ────────────────────────────────────────────────────────────

function worldToCanvas(wx, wy, cx, cy, zoom) {
  return { px: cx + wx * zoom, py: cy - wy * zoom };
}
function canvasToWorld(px, py, cx, cy, zoom) {
  return { x: (px - cx) / zoom, y: -(py - cy) / zoom };
}

// ── Map Canvas ───────────────────────────────────────────────────────────────

function PlannerCanvas({
  waypoints, routes, geofences, executions,
  robotData = {}, robots = [],
  mode,           // 'view'|'waypoint'|'geofence'
  activeRouteId,
  activeGeofenceId,
  onClickWorld,   // (x, y) → void
  onMoveWaypoint, // (id, x, y) → void
}) {
  const canvasRef = useRef(null);
  const [zoom,   setZoom]   = useState(30);
  const [pan,    setPan]    = useState({ x: 0, y: 0 });
  const dragging = useRef(null);   // { type:'pan'|'waypoint', id?, startX, startY }
  const polyPts  = useRef([]);     // in-progress geofence points

  const cx = useCallback((W) => W / 2 + pan.x, [pan.x]);
  const cy = useCallback((H) => H / 2 + pan.y, [pan.y]);

  // ── Render ─────────────────────────────────────────────────────────────────
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx   = canvas.getContext('2d');
    const W = canvas.width, H = canvas.height;
    const ox = cx(W), oy = cy(H);

    ctx.clearRect(0, 0, W, H);
    ctx.fillStyle = '#050510';
    ctx.fillRect(0, 0, W, H);

    // Grid
    ctx.strokeStyle = '#0d1b2a';
    ctx.lineWidth = 1;
    const gs = zoom;
    for (let x = (ox % gs + gs) % gs; x < W; x += gs) {
      ctx.beginPath(); ctx.moveTo(x,0); ctx.lineTo(x,H); ctx.stroke();
    }
    for (let y = (oy % gs + gs) % gs; y < H; y += gs) {
      ctx.beginPath(); ctx.moveTo(0,y); ctx.lineTo(W,y); ctx.stroke();
    }

    // Origin
    ctx.strokeStyle = '#1e3a4a';
    ctx.lineWidth = 1;
    ctx.beginPath(); ctx.moveTo(ox-12,oy); ctx.lineTo(ox+12,oy); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(ox,oy-12); ctx.lineTo(ox,oy+12); ctx.stroke();

    // ── Geofences ──────────────────────────────────────────────────────────
    for (const gf of geofences) {
      if (gf.points.length < 3) continue;
      ctx.beginPath();
      gf.points.forEach(({ x, y }, i) => {
        const p = worldToCanvas(x, y, ox, oy, zoom);
        i === 0 ? ctx.moveTo(p.px, p.py) : ctx.lineTo(p.px, p.py);
      });
      ctx.closePath();
      ctx.fillStyle   = gf.type === 'nogo' ? 'rgba(239,68,68,0.12)' : 'rgba(34,197,94,0.12)';
      ctx.strokeStyle = gf.type === 'nogo' ? '#ef4444' : '#22c55e';
      ctx.lineWidth = gf.id === activeGeofenceId ? 2 : 1;
      ctx.setLineDash(gf.id === activeGeofenceId ? [] : [4,4]);
      ctx.fill(); ctx.stroke();
      ctx.setLineDash([]);

      // Label
      const lx = gf.points.reduce((s,p)=>s+p.x,0)/gf.points.length;
      const ly = gf.points.reduce((s,p)=>s+p.y,0)/gf.points.length;
      const lp = worldToCanvas(lx, ly, ox, oy, zoom);
      ctx.fillStyle = gf.type === 'nogo' ? '#ef4444' : '#22c55e';
      ctx.font = '9px monospace';
      ctx.textAlign = 'center';
      ctx.fillText(gf.name, lp.px, lp.py);
    }

    // ── In-progress geofence ───────────────────────────────────────────────
    if (mode === 'geofence' && polyPts.current.length > 0) {
      ctx.beginPath();
      polyPts.current.forEach((p, i) => {
        i === 0 ? ctx.moveTo(p.px, p.py) : ctx.lineTo(p.px, p.py);
      });
      ctx.strokeStyle = '#f59e0b';
      ctx.lineWidth = 1.5;
      ctx.setLineDash([3,3]);
      ctx.stroke();
      ctx.setLineDash([]);
      polyPts.current.forEach(p => {
        ctx.fillStyle = '#f59e0b';
        ctx.beginPath();
        ctx.arc(p.px, p.py, 4, 0, Math.PI*2);
        ctx.fill();
      });
    }

    // ── Routes ─────────────────────────────────────────────────────────────
    const wpMap = Object.fromEntries(waypoints.map(w => [w.id, w]));
    for (const rt of routes) {
      const pts = rt.waypointIds.map(id => wpMap[id]).filter(Boolean);
      if (pts.length < 2) continue;
      const isActive = rt.id === activeRouteId;
      const exec = executions[rt.id];
      ctx.strokeStyle = rt.color ?? '#06b6d4';
      ctx.lineWidth = isActive ? 2.5 : 1.5;
      ctx.setLineDash(isActive ? [] : [6,3]);
      ctx.beginPath();
      pts.forEach((wp, i) => {
        const p = worldToCanvas(wp.x, wp.y, ox, oy, zoom);
        i === 0 ? ctx.moveTo(p.px, p.py) : ctx.lineTo(p.px, p.py);
      });
      if (rt.type === 'loop' || rt.type === 'pingpong') ctx.closePath();
      ctx.stroke();
      ctx.setLineDash([]);

      // Direction arrows on first segment
      if (pts.length >= 2) {
        const a = worldToCanvas(pts[0].x, pts[0].y, ox, oy, zoom);
        const b = worldToCanvas(pts[1].x, pts[1].y, ox, oy, zoom);
        const mx = (a.px + b.px)/2, my = (a.py + b.py)/2;
        const ang = Math.atan2(b.py - a.py, b.px - a.px);
        ctx.save();
        ctx.translate(mx, my);
        ctx.rotate(ang);
        ctx.fillStyle = rt.color ?? '#06b6d4';
        ctx.beginPath();
        ctx.moveTo(6, 0); ctx.lineTo(-4, -3); ctx.lineTo(-4, 3);
        ctx.closePath(); ctx.fill();
        ctx.restore();
      }

      // Execution progress highlight
      if (exec && exec.state === 'running' && exec.currentIdx < pts.length) {
        const cur = worldToCanvas(pts[exec.currentIdx].x, pts[exec.currentIdx].y, ox, oy, zoom);
        ctx.fillStyle = '#ffffff';
        ctx.shadowBlur = 12; ctx.shadowColor = rt.color ?? '#06b6d4';
        ctx.beginPath(); ctx.arc(cur.px, cur.py, 9, 0, Math.PI*2); ctx.fill();
        ctx.shadowBlur = 0;
        ctx.fillStyle = rt.color ?? '#06b6d4';
        ctx.font = 'bold 9px monospace';
        ctx.textAlign = 'center';
        ctx.fillText('▶', cur.px, cur.py + 3.5);
      }
    }

    // ── Waypoints ──────────────────────────────────────────────────────────
    for (const wp of waypoints) {
      const p = worldToCanvas(wp.x, wp.y, ox, oy, zoom);
      // Dwell ring
      if (wp.dwellTime > 0) {
        ctx.beginPath();
        ctx.arc(p.px, p.py, 10, 0, Math.PI * 2);
        ctx.strokeStyle = '#f59e0b44';
        ctx.lineWidth = 3;
        ctx.stroke();
      }
      // Dot
      ctx.fillStyle = '#06b6d4';
      ctx.shadowBlur = 6; ctx.shadowColor = '#06b6d4';
      ctx.beginPath(); ctx.arc(p.px, p.py, 5, 0, Math.PI*2); ctx.fill();
      ctx.shadowBlur = 0;
      // Label
      ctx.fillStyle = '#67e8f9';
      ctx.font = '9px monospace';
      ctx.textAlign = 'center';
      ctx.fillText(wp.label, p.px, p.py - 9);
    }

    // ── Robot positions from fleet ─────────────────────────────────────────
    robots.forEach((robot, i) => {
      const d = robotData[robot.id];
      if (!d?.pose) return;
      const p = worldToCanvas(d.pose.x, d.pose.y, ox, oy, zoom);
      const color = ['#f97316','#22c55e','#a855f7','#f59e0b'][i % 4];
      ctx.fillStyle = color;
      ctx.shadowBlur = 8; ctx.shadowColor = color;
      ctx.beginPath(); ctx.arc(p.px, p.py, 7, 0, Math.PI*2); ctx.fill();
      ctx.shadowBlur = 0;
      const arrowLen = Math.max(12, zoom * 0.4);
      ctx.strokeStyle = color;
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(p.px, p.py);
      ctx.lineTo(p.px + Math.cos(d.pose.yaw)*arrowLen, p.py - Math.sin(d.pose.yaw)*arrowLen);
      ctx.stroke();
      ctx.fillStyle = color;
      ctx.font = '8px monospace';
      ctx.textAlign = 'center';
      ctx.fillText(robot.name || robot.id, p.px, p.py + 16);
    });

    // ── Cursor hint ────────────────────────────────────────────────────────
    if (mode === 'waypoint') {
      ctx.strokeStyle = '#06b6d488';
      ctx.lineWidth = 1;
      ctx.setLineDash([2,2]);
      ctx.beginPath();
      ctx.arc(ox, oy, 8, 0, Math.PI*2);
      ctx.stroke();
      ctx.setLineDash([]);
    }

    // ── Scale bar ─────────────────────────────────────────────────────────
    const scaleM = zoom >= 20 ? 1 : zoom >= 5 ? 5 : 10;
    const scalePx = scaleM * zoom;
    const bx = 12, by = H - 16;
    ctx.strokeStyle = '#06b6d4';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(bx, by); ctx.lineTo(bx+scalePx, by);
    ctx.moveTo(bx, by-4); ctx.lineTo(bx, by+4);
    ctx.moveTo(bx+scalePx, by-4); ctx.lineTo(bx+scalePx, by+4);
    ctx.stroke();
    ctx.fillStyle = '#06b6d4';
    ctx.font = '9px monospace';
    ctx.textAlign = 'left';
    ctx.fillText(`${scaleM}m`, bx, by-7);
  }, [waypoints, routes, geofences, executions, robotData, robots, mode, activeRouteId, activeGeofenceId, zoom, pan, cx, cy]);

  // ── Mouse handlers ─────────────────────────────────────────────────────────
  const hitWaypoint = (px, py, W, H) => {
    const ox = cx(W), oy = cy(H);
    return waypoints.find(wp => {
      const p = worldToCanvas(wp.x, wp.y, ox, oy, zoom);
      return Math.hypot(p.px - px, p.py - py) < 8;
    });
  };

  const handleMouseDown = (e) => {
    const rect = canvasRef.current.getBoundingClientRect();
    const px = e.clientX - rect.left;
    const py = e.clientY - rect.top;
    const W  = canvasRef.current.width;
    const H  = canvasRef.current.height;

    if (mode === 'waypoint') {
      const hit = hitWaypoint(px, py, W, H);
      if (hit) {
        dragging.current = { type: 'waypoint', id: hit.id };
        return;
      }
    }
    dragging.current = { type: 'pan', startX: e.clientX - pan.x, startY: e.clientY - pan.y };
  };

  const handleMouseMove = (e) => {
    if (!dragging.current) return;
    if (dragging.current.type === 'pan') {
      setPan({ x: e.clientX - dragging.current.startX, y: e.clientY - dragging.current.startY });
    } else if (dragging.current.type === 'waypoint') {
      const rect = canvasRef.current.getBoundingClientRect();
      const px = e.clientX - rect.left;
      const py = e.clientY - rect.top;
      const W  = canvasRef.current.width;
      const H  = canvasRef.current.height;
      const { x, y } = canvasToWorld(px, py, cx(W), cy(H), zoom);
      onMoveWaypoint?.(dragging.current.id, x, y);
    }
  };

  const handleMouseUp = (e) => {
    if (dragging.current?.type === 'pan') {
      // only register click if barely moved
      const dx = Math.abs(e.clientX - (e.clientX - pan.x + dragging.current.startX - pan.x));
      // check if it was a click not a drag via movement check
    }
    dragging.current = null;
  };

  const handleClick = (e) => {
    const rect = canvasRef.current.getBoundingClientRect();
    const px = e.clientX - rect.left;
    const py = e.clientY - rect.top;
    const W  = canvasRef.current.width;
    const H  = canvasRef.current.height;
    const { x, y } = canvasToWorld(px, py, cx(W), cy(H), zoom);

    if (mode === 'waypoint') {
      if (!hitWaypoint(px, py, W, H)) {
        onClickWorld?.(x, y);
      }
    } else if (mode === 'geofence') {
      polyPts.current = [...polyPts.current, { px, py, wx: x, wy: y }];
      if (polyPts.current.length >= 3 && e.shiftKey) {
        // Shift+click to close polygon
        const pts = polyPts.current.map(p => ({ x: p.wx, y: p.wy }));
        onClickWorld?.(pts);
        polyPts.current = [];
      }
    }
  };

  const handleDblClick = (e) => {
    if (mode === 'geofence' && polyPts.current.length >= 3) {
      const pts = polyPts.current.map(p => ({ x: p.wx, y: p.wy }));
      onClickWorld?.(pts);
      polyPts.current = [];
    }
  };

  const handleWheel = (e) => {
    e.preventDefault();
    setZoom(z => Math.max(2, Math.min(200, z * (e.deltaY < 0 ? 1.2 : 0.85))));
  };

  return (
    <div className="relative">
      {/* Toolbar */}
      <div className="flex items-center gap-2 mb-2 flex-wrap">
        <div className="flex items-center gap-1 ml-auto">
          <button onClick={() => setZoom(z=>Math.min(z*1.5,200))}
            className="px-2 py-1 rounded border border-gray-700 text-gray-300 hover:border-cyan-700 text-sm">+</button>
          <span className="text-gray-500 text-xs w-14 text-center">{zoom.toFixed(0)}px/m</span>
          <button onClick={() => setZoom(z=>Math.max(z/1.5,2))}
            className="px-2 py-1 rounded border border-gray-700 text-gray-300 hover:border-cyan-700 text-sm">−</button>
          <button onClick={() => { setZoom(30); setPan({x:0,y:0}); }}
            className="px-2 py-1 rounded border border-gray-700 text-gray-400 text-xs ml-1">Reset</button>
        </div>
        {mode === 'waypoint' && (
          <span className="text-cyan-600 text-xs">Click map to place waypoint · Drag to move</span>
        )}
        {mode === 'geofence' && (
          <span className="text-amber-600 text-xs">Click to add vertices · Double-click to close polygon</span>
        )}
      </div>
      <div className="bg-gray-950 rounded-lg border border-cyan-950 overflow-hidden">
        <canvas
          ref={canvasRef} width={640} height={420}
          className={`w-full block ${mode==='waypoint'?'cursor-crosshair':mode==='geofence'?'cursor-crosshair':'cursor-grab active:cursor-grabbing'}`}
          onMouseDown={handleMouseDown}
          onMouseMove={handleMouseMove}
          onMouseUp={handleMouseUp}
          onMouseLeave={() => { dragging.current = null; }}
          onClick={handleClick}
          onDoubleClick={handleDblClick}
          onWheel={handleWheel}
        />
      </div>
      {/* Legend */}
      <div className="flex gap-4 text-xs text-gray-600 mt-1.5 flex-wrap">
        <span className="flex items-center gap-1"><div className="w-2 h-2 rounded-full bg-cyan-400"/>Waypoint</span>
        <span className="flex items-center gap-1"><div className="w-3 h-0.5 bg-green-500"/>Route</span>
        <span className="flex items-center gap-1"><div className="w-3 h-3 rounded-sm" style={{background:'rgba(239,68,68,0.3)',border:'1px solid #ef4444'}}/>No-go</span>
        <span className="flex items-center gap-1"><div className="w-3 h-3 rounded-sm" style={{background:'rgba(34,197,94,0.3)',border:'1px solid #22c55e'}}/>Allowed</span>
        <span className="flex items-center gap-1"><div className="w-2 h-2 rounded-full bg-orange-400"/>Robot</span>
      </div>
    </div>
  );
}

// ── Waypoints sub-view ────────────────────────────────────────────────────────

function WaypointsView({ waypoints, updateWaypoint, removeWaypoint, reorderWaypoints, setMapMode }) {
  const [editing, setEditing] = useState(null);
  const [editForm, setEditForm] = useState({});

  const startEdit = (wp) => { setEditing(wp.id); setEditForm({ label: wp.label, dwellTime: wp.dwellTime }); };
  const applyEdit = (id) => { updateWaypoint(id, { label: editForm.label, dwellTime: Number(editForm.dwellTime) }); setEditing(null); };

  return (
    <div className="space-y-3">
      <div className="flex items-center gap-2">
        <div className="text-cyan-700 text-xs font-bold tracking-widest">WAYPOINTS ({waypoints.length})</div>
        <button
          onClick={() => setMapMode('waypoint')}
          className="ml-auto px-3 py-1 rounded bg-cyan-950 border border-cyan-700 text-cyan-300 hover:bg-cyan-900 text-xs"
        >+ Place on Map</button>
      </div>
      {waypoints.length === 0 ? (
        <div className="text-gray-600 text-xs text-center py-6 border border-dashed border-gray-800 rounded">
          No waypoints. Click "Place on Map" then click the canvas.
        </div>
      ) : (
        <div className="space-y-1 max-h-72 overflow-y-auto">
          {waypoints.map((wp, i) => (
            <div key={wp.id} className="flex items-center gap-2 bg-gray-950 border border-gray-800 rounded px-3 py-2 text-xs">
              <span className="text-gray-600 w-5">{i+1}</span>
              {editing === wp.id ? (
                <>
                  <input
                    className="bg-gray-900 border border-cyan-800 rounded px-1.5 py-0.5 text-cyan-200 w-20 focus:outline-none text-xs"
                    value={editForm.label}
                    onChange={e => setEditForm(f=>({...f,label:e.target.value}))}
                  />
                  <input type="number" min="0" step="1"
                    className="bg-gray-900 border border-gray-700 rounded px-1.5 py-0.5 text-gray-200 w-16 focus:outline-none text-xs"
                    value={editForm.dwellTime}
                    onChange={e => setEditForm(f=>({...f,dwellTime:e.target.value}))}
                    placeholder="dwell s"
                  />
                  <button onClick={() => applyEdit(wp.id)} className="text-cyan-400 hover:text-cyan-200 px-1">✓</button>
                  <button onClick={() => setEditing(null)} className="text-gray-600 hover:text-gray-400 px-1">✕</button>
                </>
              ) : (
                <>
                  <span className="font-bold text-cyan-300 w-20 truncate">{wp.label}</span>
                  <span className="text-gray-500 font-mono flex-1">
                    ({wp.x.toFixed(1)}, {wp.y.toFixed(1)})
                  </span>
                  {wp.dwellTime > 0 && <span className="text-amber-500">{wp.dwellTime}s dwell</span>}
                  <button onClick={() => startEdit(wp)} className="text-gray-600 hover:text-cyan-400 px-1">✏</button>
                  <button onClick={() => removeWaypoint(wp.id)} className="text-gray-700 hover:text-red-500 px-1">✕</button>
                </>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Routes sub-view ────────────────────────────────────────────────────────────

function RoutesView({ waypoints, routes, addRoute, updateRoute, removeRoute, addWaypointToRoute, removeWaypointFromRoute, robots, setActiveRouteId }) {
  const [newName, setNewName] = useState('');
  const wpMap = Object.fromEntries(waypoints.map(w=>[w.id,w]));

  return (
    <div className="space-y-4">
      <div className="text-cyan-700 text-xs font-bold tracking-widest">PATROL ROUTES</div>

      {/* Create route */}
      <div className="flex gap-2">
        <input
          className="flex-1 bg-gray-900 border border-gray-700 rounded px-2 py-1 text-sm text-gray-200 focus:outline-none focus:border-cyan-700"
          placeholder="Route name…"
          value={newName}
          onChange={e => setNewName(e.target.value)}
          onKeyDown={e => { if (e.key==='Enter' && newName.trim()) { addRoute(newName.trim()); setNewName(''); }}}
        />
        <button
          disabled={!newName.trim()}
          onClick={() => { addRoute(newName.trim()); setNewName(''); }}
          className="px-3 py-1 rounded bg-cyan-950 border border-cyan-700 text-cyan-300 hover:bg-cyan-900 text-xs disabled:opacity-40"
        >Add Route</button>
      </div>

      {routes.length === 0 ? (
        <div className="text-gray-600 text-xs text-center py-6 border border-dashed border-gray-800 rounded">
          No routes defined. Create a route and add waypoints to it.
        </div>
      ) : (
        <div className="space-y-3">
          {routes.map(rt => (
            <div key={rt.id}
              className="bg-gray-950 border border-gray-800 rounded-lg p-3 space-y-2"
              style={{ borderLeftColor: rt.color, borderLeftWidth: 3 }}
            >
              {/* Route header */}
              <div className="flex items-center gap-2 flex-wrap">
                <span className="font-bold text-gray-200 text-sm">{rt.name}</span>
                <select
                  className="bg-gray-900 border border-gray-700 rounded px-1.5 py-0.5 text-xs text-gray-300 focus:outline-none"
                  value={rt.type}
                  onChange={e => updateRoute(rt.id, {type: e.target.value})}
                >
                  {Object.entries(ROUTE_TYPE_LABELS).map(([v,l]) => (
                    <option key={v} value={v}>{l}</option>
                  ))}
                </select>
                <select
                  className="bg-gray-900 border border-gray-700 rounded px-1.5 py-0.5 text-xs text-gray-300 focus:outline-none"
                  value={rt.robotId ?? ''}
                  onChange={e => updateRoute(rt.id, {robotId: e.target.value || null})}
                >
                  <option value="">— No robot —</option>
                  {robots.map(r => <option key={r.id} value={r.id}>{r.name||r.id}</option>)}
                </select>
                <button onClick={() => setActiveRouteId(rt.id)}
                  className="ml-auto text-xs text-cyan-600 hover:text-cyan-300 border border-gray-700 px-2 py-0.5 rounded">
                  Show
                </button>
                <button onClick={() => removeRoute(rt.id)}
                  className="text-gray-700 hover:text-red-500 text-xs px-1">✕</button>
              </div>

              {/* Waypoint sequence */}
              <div className="flex flex-wrap gap-1 items-center min-h-6">
                {rt.waypointIds.map((wid, idx) => {
                  const wp = wpMap[wid];
                  return (
                    <div key={`${wid}-${idx}`} className="flex items-center gap-0.5">
                      {idx > 0 && <span className="text-gray-700">→</span>}
                      <span className="bg-gray-900 border border-gray-700 rounded px-1.5 py-0.5 text-xs text-cyan-300 flex items-center gap-1">
                        {wp?.label ?? '?'}
                        <button onClick={() => removeWaypointFromRoute(rt.id, idx)}
                          className="text-gray-700 hover:text-red-500">×</button>
                      </span>
                    </div>
                  );
                })}
                {rt.type === 'loop' && rt.waypointIds.length >= 2 && (
                  <span className="text-gray-600 text-xs">↩</span>
                )}
              </div>

              {/* Add waypoint to route */}
              {waypoints.length > 0 && (
                <select
                  className="bg-gray-900 border border-gray-700 rounded px-2 py-0.5 text-xs text-gray-300 focus:outline-none w-full"
                  value=""
                  onChange={e => { if (e.target.value) addWaypointToRoute(rt.id, e.target.value); }}
                >
                  <option value="">+ Add waypoint…</option>
                  {waypoints.map(w => <option key={w.id} value={w.id}>{w.label}</option>)}
                </select>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Geofences sub-view ────────────────────────────────────────────────────────

function GeofencesView({ geofences, updateGeofence, removeGeofence, setMapMode, setActiveGeofenceId }) {
  const [pendingType, setPendingType] = useState('nogo');
  const [pendingName, setPendingName] = useState('');

  return (
    <div className="space-y-3">
      <div className="flex items-center gap-2 flex-wrap">
        <div className="text-cyan-700 text-xs font-bold tracking-widest">GEOFENCES</div>
        <div className="ml-auto flex gap-2 items-center">
          <input
            className="bg-gray-900 border border-gray-700 rounded px-2 py-1 text-xs text-gray-200 focus:outline-none w-28"
            placeholder="Name…"
            value={pendingName}
            onChange={e => setPendingName(e.target.value)}
          />
          <select
            className="bg-gray-900 border border-gray-700 rounded px-1.5 py-1 text-xs text-gray-300 focus:outline-none"
            value={pendingType}
            onChange={e => setPendingType(e.target.value)}
          >
            <option value="nogo">No-go zone</option>
            <option value="allowed">Allowed area</option>
          </select>
          <button
            onClick={() => {
              if (pendingName.trim()) setMapMode({ mode: 'geofence', type: pendingType, name: pendingName.trim() });
            }}
            disabled={!pendingName.trim()}
            className="px-2 py-1 rounded bg-cyan-950 border border-cyan-700 text-cyan-300 hover:bg-cyan-900 text-xs disabled:opacity-40"
          >Draw</button>
        </div>
      </div>

      {geofences.length === 0 ? (
        <div className="text-gray-600 text-xs text-center py-6 border border-dashed border-gray-800 rounded">
          No geofences. Enter a name, pick type, click Draw, then draw on the map.
        </div>
      ) : (
        <div className="space-y-1.5">
          {geofences.map(gf => (
            <div key={gf.id} className="flex items-center gap-2 bg-gray-950 border border-gray-800 rounded px-3 py-2 text-xs">
              <div className="w-2 h-2 rounded-sm shrink-0"
                style={{ background: gf.type==='nogo'?'#ef4444':'#22c55e' }} />
              <span className="font-bold text-gray-200 flex-1">{gf.name}</span>
              <span className={`text-xs px-1.5 rounded border ${gf.type==='nogo'?'bg-red-950 border-red-800 text-red-400':'bg-green-950 border-green-800 text-green-400'}`}>
                {gf.type==='nogo'?'no-go':'allowed'}
              </span>
              <span className="text-gray-600">{gf.points.length} pts</span>
              <button onClick={() => setActiveGeofenceId(gf.id)} className="text-gray-600 hover:text-cyan-400 px-1">🗺</button>
              <button onClick={() => removeGeofence(gf.id)} className="text-gray-700 hover:text-red-500 px-1">✕</button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Templates sub-view ────────────────────────────────────────────────────────

const BUILTIN_TEMPLATES = [
  { id: '__patrol',  name: 'Patrol',      description: 'Clockwise perimeter loop' },
  { id: '__escort',  name: 'Escort',      description: 'Follow a fixed escort path' },
  { id: '__dock',    name: 'Dock',        description: 'Navigate to charging dock' },
  { id: '__explore', name: 'Exploration', description: 'Systematic area coverage' },
];

function TemplatesView({ templates, saveTemplate, loadTemplate, removeTemplate, exportJSON, importJSON }) {
  const [saveName, setSaveName] = useState('');
  const [saveDesc, setSaveDesc] = useState('');
  const [importText, setImportText] = useState('');
  const [showImport, setShowImport] = useState(false);
  const [msg, setMsg] = useState(null);

  const showMsg = (m) => { setMsg(m); setTimeout(()=>setMsg(null), 3000); };

  const handleExport = () => {
    const json = exportJSON();
    const a = document.createElement('a');
    a.href = URL.createObjectURL(new Blob([json], {type:'application/json'}));
    a.download = 'saltybot-missions.json';
    a.click();
  };

  const handleImport = () => {
    try {
      importJSON(importText);
      setShowImport(false);
      setImportText('');
      showMsg('Imported successfully');
    } catch (e) {
      showMsg('Invalid JSON: ' + e.message);
    }
  };

  return (
    <div className="space-y-4">
      <div className="text-cyan-700 text-xs font-bold tracking-widest">MISSION TEMPLATES</div>

      {/* Save current state */}
      <div className="bg-gray-950 border border-gray-800 rounded-lg p-3 space-y-2">
        <div className="text-gray-500 text-xs font-bold">Save Current Mission</div>
        <div className="flex gap-2">
          <input
            className="flex-1 bg-gray-900 border border-gray-700 rounded px-2 py-1 text-sm text-gray-200 focus:outline-none focus:border-cyan-700"
            placeholder="Template name…"
            value={saveName} onChange={e=>setSaveName(e.target.value)}
          />
          <input
            className="flex-1 bg-gray-900 border border-gray-700 rounded px-2 py-1 text-sm text-gray-200 focus:outline-none focus:border-cyan-700"
            placeholder="Description (optional)"
            value={saveDesc} onChange={e=>setSaveDesc(e.target.value)}
          />
          <button
            disabled={!saveName.trim()}
            onClick={() => { saveTemplate(saveName.trim(), saveDesc); setSaveName(''); setSaveDesc(''); showMsg('Saved'); }}
            className="px-3 py-1 rounded bg-cyan-950 border border-cyan-700 text-cyan-300 hover:bg-cyan-900 text-xs disabled:opacity-40"
          >Save</button>
        </div>
      </div>

      {msg && <div className="text-green-400 text-xs">{msg}</div>}

      {/* User templates */}
      {templates.length > 0 && (
        <div className="space-y-1.5">
          <div className="text-gray-600 text-xs">Saved Templates</div>
          {templates.map(t => (
            <div key={t.id} className="flex items-center gap-2 bg-gray-950 border border-gray-800 rounded px-3 py-2 text-xs">
              <div className="flex-1">
                <span className="font-bold text-gray-200">{t.name}</span>
                {t.description && <span className="text-gray-600 ml-2">{t.description}</span>}
              </div>
              <span className="text-gray-700">{t.waypoints?.length??0}wp {t.routes?.length??0}rt</span>
              <button onClick={() => { loadTemplate(t.id); showMsg(`Loaded: ${t.name}`); }}
                className="text-cyan-600 hover:text-cyan-300 border border-gray-700 px-2 py-0.5 rounded text-xs">Load</button>
              <button onClick={() => removeTemplate(t.id)}
                className="text-gray-700 hover:text-red-500 px-1">✕</button>
            </div>
          ))}
        </div>
      )}

      {/* Built-in starters */}
      <div className="space-y-1.5">
        <div className="text-gray-600 text-xs">Mission Starters</div>
        {BUILTIN_TEMPLATES.map(t => (
          <div key={t.id} className="flex items-center gap-2 bg-gray-950 border border-gray-800 rounded px-3 py-2 text-xs">
            <div className="flex-1">
              <span className="font-bold text-gray-300">{t.name}</span>
              <span className="text-gray-600 ml-2">{t.description}</span>
            </div>
            <span className="text-gray-700 text-xs italic">starter</span>
          </div>
        ))}
      </div>

      {/* Import / Export */}
      <div className="flex gap-2 pt-1">
        <button onClick={handleExport}
          className="px-3 py-1.5 rounded border border-gray-700 text-gray-400 hover:text-gray-200 text-xs">
          Export JSON
        </button>
        <button onClick={() => setShowImport(s=>!s)}
          className="px-3 py-1.5 rounded border border-gray-700 text-gray-400 hover:text-gray-200 text-xs">
          Import JSON
        </button>
      </div>
      {showImport && (
        <div className="space-y-2">
          <textarea rows={5}
            className="w-full bg-gray-900 border border-gray-700 rounded px-2 py-1.5 text-xs text-gray-200 focus:outline-none font-mono"
            placeholder='Paste mission JSON here…'
            value={importText} onChange={e=>setImportText(e.target.value)}
          />
          <button onClick={handleImport}
            className="px-3 py-1 rounded bg-cyan-950 border border-cyan-700 text-cyan-300 hover:bg-cyan-900 text-xs">
            Import
          </button>
        </div>
      )}
    </div>
  );
}

// ── Schedule sub-view ─────────────────────────────────────────────────────────

function ScheduleView({ schedules, routes, robots, addSchedule, updateSchedule, removeSchedule }) {
  const [form, setForm] = useState({ routeId: '', robotId: '', time: '09:00', days: [1,2,3,4,5] });
  const set = (k,v) => setForm(f=>({...f,[k]:v}));

  const toggleDay = (d) => set('days', form.days.includes(d) ? form.days.filter(x=>x!==d) : [...form.days, d]);

  const handleAdd = () => {
    if (!form.routeId) return;
    addSchedule(form.routeId, form.robotId||null, form.time, form.days);
  };

  const routeMap  = Object.fromEntries(routes.map(r=>[r.id,r]));
  const robotMap  = Object.fromEntries(robots.map(r=>[r.id,r]));

  return (
    <div className="space-y-4">
      <div className="text-cyan-700 text-xs font-bold tracking-widest">MISSION SCHEDULE</div>

      {/* Add schedule */}
      <div className="bg-gray-950 border border-gray-800 rounded-lg p-3 space-y-3">
        <div className="text-gray-500 text-xs font-bold">Add Time Trigger</div>
        <div className="grid grid-cols-2 gap-2">
          <label className="space-y-1">
            <span className="text-gray-600 text-xs">Route</span>
            <select className="w-full bg-gray-900 border border-gray-700 rounded px-2 py-1 text-xs text-gray-200 focus:outline-none"
              value={form.routeId} onChange={e=>set('routeId',e.target.value)}>
              <option value="">— Select route —</option>
              {routes.map(r => <option key={r.id} value={r.id}>{r.name}</option>)}
            </select>
          </label>
          <label className="space-y-1">
            <span className="text-gray-600 text-xs">Robot</span>
            <select className="w-full bg-gray-900 border border-gray-700 rounded px-2 py-1 text-xs text-gray-200 focus:outline-none"
              value={form.robotId} onChange={e=>set('robotId',e.target.value)}>
              <option value="">— Any robot —</option>
              {robots.map(r => <option key={r.id} value={r.id}>{r.name||r.id}</option>)}
            </select>
          </label>
          <label className="space-y-1">
            <span className="text-gray-600 text-xs">Time</span>
            <input type="time" className="w-full bg-gray-900 border border-gray-700 rounded px-2 py-1 text-xs text-gray-200 focus:outline-none"
              value={form.time} onChange={e=>set('time',e.target.value)} />
          </label>
          <label className="space-y-1">
            <span className="text-gray-600 text-xs">Days</span>
            <div className="flex gap-1">
              {DAY_LABELS.map((d,i) => (
                <button key={i}
                  onClick={() => toggleDay(i)}
                  className={`w-6 h-6 rounded text-xs font-bold ${form.days.includes(i)?'bg-cyan-950 border border-cyan-700 text-cyan-300':'bg-gray-900 border border-gray-700 text-gray-600'}`}
                >{d}</button>
              ))}
            </div>
          </label>
        </div>
        <button
          disabled={!form.routeId}
          onClick={handleAdd}
          className="w-full py-1.5 rounded bg-cyan-950 border border-cyan-700 text-cyan-300 hover:bg-cyan-900 text-xs font-bold disabled:opacity-40"
        >Add Schedule</button>
      </div>

      {/* Schedule list */}
      {schedules.length === 0 ? (
        <div className="text-gray-600 text-xs text-center py-6 border border-dashed border-gray-800 rounded">
          No schedules configured.
        </div>
      ) : (
        <div className="space-y-1.5">
          {schedules.map(sc => {
            const rt = routeMap[sc.routeId];
            const rb = sc.robotId ? robotMap[sc.robotId] : null;
            return (
              <div key={sc.id} className="flex items-center gap-2 bg-gray-950 border border-gray-800 rounded px-3 py-2 text-xs">
                <button
                  onClick={() => updateSchedule(sc.id, { enabled: !sc.enabled })}
                  className={`w-8 h-4 rounded-full relative transition-colors ${sc.enabled?'bg-cyan-700':'bg-gray-700'}`}
                >
                  <span className={`absolute top-0.5 w-3 h-3 rounded-full bg-white transition-all ${sc.enabled?'left-4':'left-0.5'}`}/>
                </button>
                <span className="font-bold text-amber-300 w-12 shrink-0">{sc.time}</span>
                <span className="text-gray-500 text-xs">
                  {sc.days.map(d=>DAY_LABELS[d]).join(' ')}
                </span>
                <span className="text-cyan-300 flex-1 truncate">{rt?.name ?? '?'}</span>
                {rb && <span className="text-gray-500">{rb.name||rb.id}</span>}
                <button onClick={() => removeSchedule(sc.id)}
                  className="text-gray-700 hover:text-red-500 px-1">✕</button>
              </div>
            );
          })}
        </div>
      )}

      <div className="text-gray-700 text-xs">
        Note: Schedules are evaluated client-side. Keep this dashboard open for scheduled missions to trigger.
        For persistent scheduling, push routes to the robot via ROS2 nav stack.
      </div>
    </div>
  );
}

// ── Execute sub-view ──────────────────────────────────────────────────────────

function ExecuteView({ routes, waypoints, robots, connections, executions, publishRobot,
                       startExecution, pauseExecution, resumeExecution, abortExecution, advanceExecution }) {
  const wpMap = Object.fromEntries(waypoints.map(w=>[w.id,w]));

  const sendWaypoint = useCallback((robotId, wp) => {
    if (!robotId || !publishRobot) return;
    const cy2 = Math.cos(0), sy2 = Math.sin(0);
    publishRobot(robotId, '/goal_pose', 'geometry_msgs/PoseStamped', {
      header: { frame_id: 'map', stamp: { sec: 0, nanosec: 0 } },
      pose: {
        position: { x: wp.x, y: wp.y, z: 0 },
        orientation: { x: 0, y: 0, z: sy2, w: cy2 },
      },
    });
  }, [publishRobot]);

  const handleStart = (rt) => {
    const robotId = rt.robotId;
    startExecution(rt.id, robotId);
    // Send first waypoint
    const first = wpMap[rt.waypointIds[0]];
    if (first && robotId) sendWaypoint(robotId, first);
  };

  const handleAdvance = (rt) => {
    const exec = executions[rt.id];
    if (!exec) return;
    const nextIdx = exec.currentIdx + 1;
    const len = rt.waypointIds.length;
    if (nextIdx >= len) {
      if (rt.type === 'loop') {
        advanceExecution(rt.id, 0);
        const wp = wpMap[rt.waypointIds[0]];
        if (wp && exec.robotId) sendWaypoint(exec.robotId, wp);
      } else {
        abortExecution(rt.id); // mark done
      }
    } else {
      advanceExecution(rt.id, nextIdx);
      const wp = wpMap[rt.waypointIds[nextIdx]];
      if (wp && exec.robotId) sendWaypoint(exec.robotId, wp);
    }
  };

  return (
    <div className="space-y-3">
      <div className="text-cyan-700 text-xs font-bold tracking-widest">LIVE EXECUTION</div>

      {routes.length === 0 ? (
        <div className="text-gray-600 text-xs text-center py-6 border border-dashed border-gray-800 rounded">
          No routes defined. Create routes in the Routes tab first.
        </div>
      ) : (
        <div className="space-y-2">
          {routes.map(rt => {
            const exec = executions[rt.id];
            const robotId = exec?.robotId ?? rt.robotId;
            const robot = robots.find(r=>r.id===robotId);
            const connected = robotId && connections[robotId]?.connected;
            const pts = rt.waypointIds.map(id=>wpMap[id]).filter(Boolean);
            const state = exec?.state ?? 'idle';
            const progress = exec ? `${exec.currentIdx+1}/${pts.length}` : `0/${pts.length}`;

            return (
              <div key={rt.id} className="bg-gray-950 border border-gray-800 rounded-lg p-3 space-y-2"
                style={{ borderLeftColor: rt.color, borderLeftWidth: 3 }}>
                <div className="flex items-center gap-2 flex-wrap">
                  <span className="font-bold text-gray-200 text-sm">{rt.name}</span>
                  <span className={`text-xs px-1.5 py-0.5 rounded border font-bold ${
                    state==='running' ? 'bg-green-950 border-green-700 text-green-400' :
                    state==='paused'  ? 'bg-amber-950 border-amber-700 text-amber-400' :
                    state==='done'    ? 'bg-cyan-950 border-cyan-700 text-cyan-400' :
                    state==='aborted' ? 'bg-red-950 border-red-700 text-red-400' :
                    'bg-gray-900 border-gray-700 text-gray-500'
                  }`}>{state.toUpperCase()}</span>
                  <span className="text-gray-500 text-xs">{ROUTE_TYPE_LABELS[rt.type]}</span>
                  <span className="text-gray-600 text-xs ml-auto">{progress}</span>
                </div>

                {/* Robot assignment */}
                <div className="flex items-center gap-2 text-xs">
                  <span className="text-gray-600">Robot:</span>
                  {robot ? (
                    <span className={connected ? 'text-green-400' : 'text-red-400'}>
                      {connected ? '● ' : '○ '}{robot.name||robot.id}
                    </span>
                  ) : (
                    <span className="text-gray-600">— unassigned (go to Routes tab)</span>
                  )}
                </div>

                {/* Progress bar */}
                {pts.length > 0 && (
                  <div>
                    <div className="w-full h-1.5 bg-gray-800 rounded overflow-hidden">
                      <div className="h-full rounded transition-all" style={{
                        width: exec ? `${((exec.currentIdx+1)/pts.length)*100}%` : '0%',
                        background: rt.color
                      }} />
                    </div>
                    {exec && state==='running' && (
                      <div className="text-xs text-gray-500 mt-1">
                        → {wpMap[rt.waypointIds[exec.currentIdx]]?.label ?? '?'}
                      </div>
                    )}
                  </div>
                )}

                {/* Controls */}
                <div className="flex gap-2">
                  {state === 'idle' || state === 'done' || state === 'aborted' ? (
                    <button
                      disabled={!connected || pts.length === 0}
                      onClick={() => handleStart(rt)}
                      className="px-3 py-1 rounded bg-green-950 border border-green-700 text-green-300 hover:bg-green-900 text-xs disabled:opacity-40"
                    >▶ Start</button>
                  ) : state === 'running' ? (
                    <>
                      <button onClick={() => pauseExecution(rt.id)}
                        className="px-3 py-1 rounded bg-amber-950 border border-amber-700 text-amber-300 hover:bg-amber-900 text-xs">
                        ⏸ Pause</button>
                      <button onClick={() => handleAdvance(rt)}
                        className="px-3 py-1 rounded border border-gray-700 text-gray-400 hover:text-gray-200 text-xs">
                        ⏭ Next WP</button>
                      <button onClick={() => abortExecution(rt.id)}
                        className="px-3 py-1 rounded bg-red-950 border border-red-800 text-red-400 hover:bg-red-900 text-xs">
                        ⏹ Abort</button>
                    </>
                  ) : state === 'paused' ? (
                    <>
                      <button onClick={() => resumeExecution(rt.id)}
                        className="px-3 py-1 rounded bg-green-950 border border-green-700 text-green-300 hover:bg-green-900 text-xs">
                        ▶ Resume</button>
                      <button onClick={() => abortExecution(rt.id)}
                        className="px-3 py-1 rounded bg-red-950 border border-red-800 text-red-400 hover:bg-red-900 text-xs">
                        ⏹ Abort</button>
                    </>
                  ) : null}

                  {/* Send full patrol route */}
                  {connected && pts.length >= 2 && (state==='idle'||state==='done'||state==='aborted') && (
                    <button
                      onClick={() => {
                        const cy2 = Math.cos(0);
                        publishRobot(robotId, '/outdoor/waypoints', 'geometry_msgs/PoseArray', {
                          header: { frame_id:'map', stamp:{sec:0,nanosec:0} },
                          poses: pts.map(wp => ({
                            position:{x:wp.x,y:wp.y,z:0},
                            orientation:{x:0,y:0,z:0,w:1},
                          })),
                        });
                      }}
                      className="px-3 py-1 rounded border border-cyan-800 text-cyan-500 hover:text-cyan-300 text-xs"
                    >Send Patrol Route</button>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ── Root MissionPlanner ───────────────────────────────────────────────────────

export function MissionPlanner() {
  const missions = useMissions();
  const { robots, connections, robotData, publishRobot } = useFleet();

  const [view,            setView]            = useState('Map');
  const [mapMode,         setMapMode]         = useState('view');   // 'view'|'waypoint'|{mode:'geofence',...}
  const [activeRouteId,   setActiveRouteId]   = useState(null);
  const [activeGeofenceId,setActiveGeofenceId]= useState(null);

  const isGeofenceMode = typeof mapMode === 'object' && mapMode.mode === 'geofence';
  const canvasMode = mapMode === 'waypoint' ? 'waypoint' : isGeofenceMode ? 'geofence' : 'view';

  const handleClickWorld = useCallback((xOrPts, y) => {
    if (mapMode === 'waypoint') {
      missions.addWaypoint(xOrPts, y);
    } else if (isGeofenceMode && Array.isArray(xOrPts)) {
      missions.addGeofence(mapMode.name, mapMode.type, xOrPts);
      setMapMode('view');
    }
  }, [mapMode, isGeofenceMode, missions]);

  const setMapModeWrapped = useCallback((m) => {
    setMapMode(m);
    if (m !== 'waypoint') setView('Map');
  }, []);

  // Schedule runner — check every minute
  useEffect(() => {
    const check = () => {
      const now = new Date();
      const hhmm = `${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}`;
      missions.schedules.forEach(sc => {
        if (!sc.enabled) return;
        if (!sc.days.includes(now.getDay())) return;
        if (sc.time !== hhmm) return;
        const rt = missions.routes.find(r=>r.id===sc.routeId);
        if (!rt) return;
        const robotId = sc.robotId ?? rt.robotId;
        if (!robotId || !connections[robotId]?.connected) return;
        const exec = missions.executions[rt.id];
        if (exec?.state === 'running') return; // already running
        missions.startExecution(rt.id, robotId);
      });
    };
    const timer = setInterval(check, 60000);
    return () => clearInterval(timer);
  }, [missions, connections]);

  return (
    <div className="space-y-4">
      {/* Sub-nav */}
      <div className="flex gap-0.5 border-b border-gray-800 overflow-x-auto">
        {VIEWS.map(v => (
          <button key={v} onClick={() => setView(v)}
            className={`px-3 py-2 text-xs font-bold tracking-wider whitespace-nowrap border-b-2 transition-colors ${
              view === v
                ? 'border-cyan-500 text-cyan-300'
                : 'border-transparent text-gray-600 hover:text-gray-300'
            }`}
          >{v.toUpperCase()}</button>
        ))}
        {mapMode !== 'view' && (
          <button onClick={() => setMapMode('view')}
            className="ml-auto px-3 py-1 my-0.5 rounded border border-amber-800 text-amber-400 text-xs">
            ✕ Exit {canvasMode} mode
          </button>
        )}
      </div>

      {/* Map always visible */}
      <PlannerCanvas
        waypoints={missions.waypoints}
        routes={missions.routes}
        geofences={missions.geofences}
        executions={missions.executions}
        robots={robots}
        robotData={robotData}
        mode={canvasMode}
        activeRouteId={activeRouteId}
        activeGeofenceId={activeGeofenceId}
        onClickWorld={handleClickWorld}
        onMoveWaypoint={missions.updateWaypoint}
      />

      {/* Sub-view panel */}
      <div>
        {view === 'Waypoints' && (
          <WaypointsView
            waypoints={missions.waypoints}
            updateWaypoint={missions.updateWaypoint}
            removeWaypoint={missions.removeWaypoint}
            reorderWaypoints={missions.reorderWaypoints}
            setMapMode={() => setMapMode('waypoint')}
          />
        )}
        {view === 'Routes' && (
          <RoutesView
            waypoints={missions.waypoints}
            routes={missions.routes}
            addRoute={missions.addRoute}
            updateRoute={missions.updateRoute}
            removeRoute={missions.removeRoute}
            addWaypointToRoute={missions.addWaypointToRoute}
            removeWaypointFromRoute={missions.removeWaypointFromRoute}
            robots={robots}
            setActiveRouteId={setActiveRouteId}
          />
        )}
        {view === 'Geofences' && (
          <GeofencesView
            geofences={missions.geofences}
            updateGeofence={missions.updateGeofence}
            removeGeofence={missions.removeGeofence}
            setMapMode={setMapModeWrapped}
            setActiveGeofenceId={setActiveGeofenceId}
          />
        )}
        {view === 'Templates' && (
          <TemplatesView
            templates={missions.templates}
            saveTemplate={missions.saveTemplate}
            loadTemplate={missions.loadTemplate}
            removeTemplate={missions.removeTemplate}
            exportJSON={missions.exportJSON}
            importJSON={missions.importJSON}
          />
        )}
        {view === 'Schedule' && (
          <ScheduleView
            schedules={missions.schedules}
            routes={missions.routes}
            robots={robots}
            addSchedule={missions.addSchedule}
            updateSchedule={missions.updateSchedule}
            removeSchedule={missions.removeSchedule}
          />
        )}
        {view === 'Execute' && (
          <ExecuteView
            routes={missions.routes}
            waypoints={missions.waypoints}
            robots={robots}
            connections={connections}
            executions={missions.executions}
            publishRobot={publishRobot}
            startExecution={missions.startExecution}
            pauseExecution={missions.pauseExecution}
            resumeExecution={missions.resumeExecution}
            abortExecution={missions.abortExecution}
            advanceExecution={missions.advanceExecution}
          />
        )}
        {view === 'Map' && (
          <div className="flex flex-wrap gap-2 text-xs">
            <button onClick={() => setMapMode('waypoint')}
              className={`px-3 py-1.5 rounded border text-xs ${mapMode==='waypoint'?'bg-cyan-950 border-cyan-700 text-cyan-300':'border-gray-700 text-gray-500 hover:text-gray-300'}`}>
              + Place Waypoint
            </button>
            <button onClick={() => { setView('Waypoints'); setMapMode('waypoint'); }}
              className="px-3 py-1.5 rounded border border-gray-700 text-gray-500 hover:text-gray-300 text-xs">
              Manage Waypoints →
            </button>
            <button onClick={() => setView('Routes')}
              className="px-3 py-1.5 rounded border border-gray-700 text-gray-500 hover:text-gray-300 text-xs">
              Manage Routes →
            </button>
            <button onClick={() => setView('Execute')}
              className="px-3 py-1.5 rounded border border-gray-700 text-gray-500 hover:text-gray-300 text-xs">
              Execute →
            </button>
            <div className="text-gray-700 self-center ml-2">
              {missions.waypoints.length} wpts · {missions.routes.length} routes · {missions.geofences.length} fences
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
