/**
 * useMissions.js — Mission planner state management.
 *
 * Manages waypoints, patrol routes, geofences, templates, schedules.
 * Persists to localStorage. Provides JSON export/import.
 *
 * Data shapes:
 *   Waypoint:  { id, label, x, y, dwellTime }  (x,y in metres, world frame)
 *   Route:     { id, name, waypointIds[], type, robotId, color }
 *              type: 'loop' | 'oneshot' | 'pingpong'
 *   Geofence:  { id, name, type, points[{x,y}], color }
 *              type: 'nogo' | 'allowed'
 *   Template:  { id, name, description, waypoints[], routes[], geofences[] }
 *   Schedule:  { id, routeId, robotId, time, days[], enabled }
 *              days: 0-6 (Sun-Sat), time: 'HH:MM'
 *   Execution: { routeId, robotId, currentIdx, state, startedAt, paused }
 *              state: 'idle'|'running'|'paused'|'done'|'aborted'
 */

import { useState, useCallback, useEffect, useRef } from 'react';

const STORAGE_KEY = 'saltybot_missions_v1';
const EXEC_KEY    = 'saltybot_executions_v1';

const ROUTE_COLORS = ['#06b6d4','#f97316','#22c55e','#a855f7','#f59e0b','#ec4899'];

function genId() {
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`;
}

function loadState() {
  try {
    const s = JSON.parse(localStorage.getItem(STORAGE_KEY));
    if (s && typeof s === 'object') return s;
  } catch {}
  return { waypoints: [], routes: [], geofences: [], templates: [], schedules: [] };
}

function saveState(state) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
}

export function useMissions() {
  const [waypoints,  setWaypoints]  = useState(() => loadState().waypoints);
  const [routes,     setRoutes]     = useState(() => loadState().routes);
  const [geofences,  setGeofences]  = useState(() => loadState().geofences);
  const [templates,  setTemplates]  = useState(() => loadState().templates);
  const [schedules,  setSchedules]  = useState(() => loadState().schedules);
  const [executions, setExecutions] = useState({});   // { [routeId]: Execution }

  // Persist on every change
  useEffect(() => {
    saveState({ waypoints, routes, geofences, templates, schedules });
  }, [waypoints, routes, geofences, templates, schedules]);

  // ── Waypoints ────────────────────────────────────────────────────────────

  const addWaypoint = useCallback((x, y, label) => {
    const wp = { id: genId(), label: label ?? `WP${Date.now().toString(36).slice(-4).toUpperCase()}`, x, y, dwellTime: 0 };
    setWaypoints(w => [...w, wp]);
    return wp.id;
  }, []);

  const updateWaypoint = useCallback((id, patch) => {
    setWaypoints(w => w.map(wp => wp.id === id ? { ...wp, ...patch } : wp));
  }, []);

  const removeWaypoint = useCallback((id) => {
    setWaypoints(w => w.filter(wp => wp.id !== id));
    // Remove from any routes
    setRoutes(r => r.map(rt => ({ ...rt, waypointIds: rt.waypointIds.filter(wid => wid !== id) })));
  }, []);

  const reorderWaypoints = useCallback((fromIdx, toIdx) => {
    setWaypoints(w => {
      const arr = [...w];
      const [item] = arr.splice(fromIdx, 1);
      arr.splice(toIdx, 0, item);
      return arr;
    });
  }, []);

  // ── Routes ───────────────────────────────────────────────────────────────

  const addRoute = useCallback((name, waypointIds = [], type = 'loop') => {
    const id = genId();
    const color = ROUTE_COLORS[Math.floor(Math.random() * ROUTE_COLORS.length)];
    setRoutes(r => [...r, { id, name, waypointIds, type, robotId: null, color }]);
    return id;
  }, []);

  const updateRoute = useCallback((id, patch) => {
    setRoutes(r => r.map(rt => rt.id === id ? { ...rt, ...patch } : rt));
  }, []);

  const removeRoute = useCallback((id) => {
    setRoutes(r => r.filter(rt => rt.id !== id));
    setSchedules(s => s.filter(sc => sc.routeId !== id));
  }, []);

  const addWaypointToRoute = useCallback((routeId, waypointId) => {
    setRoutes(r => r.map(rt =>
      rt.id === routeId
        ? { ...rt, waypointIds: [...rt.waypointIds, waypointId] }
        : rt
    ));
  }, []);

  const removeWaypointFromRoute = useCallback((routeId, idx) => {
    setRoutes(r => r.map(rt =>
      rt.id === routeId
        ? { ...rt, waypointIds: rt.waypointIds.filter((_, i) => i !== idx) }
        : rt
    ));
  }, []);

  // ── Geofences ────────────────────────────────────────────────────────────

  const addGeofence = useCallback((name, type, points) => {
    const id = genId();
    const color = type === 'nogo' ? '#ef444488' : '#22c55e88';
    setGeofences(g => [...g, { id, name, type, points, color }]);
    return id;
  }, []);

  const updateGeofence = useCallback((id, patch) => {
    setGeofences(g => g.map(gf => gf.id === id ? { ...gf, ...patch } : gf));
  }, []);

  const removeGeofence = useCallback((id) => {
    setGeofences(g => g.filter(gf => gf.id !== id));
  }, []);

  // ── Templates ────────────────────────────────────────────────────────────

  const saveTemplate = useCallback((name, description = '') => {
    const id = genId();
    setTemplates(t => [
      ...t.filter(x => x.name !== name),
      { id, name, description, waypoints, routes, geofences },
    ]);
    return id;
  }, [waypoints, routes, geofences]);

  const loadTemplate = useCallback((id) => {
    setTemplates(t => {
      const tmpl = t.find(x => x.id === id);
      if (!tmpl) return t;
      setWaypoints(tmpl.waypoints);
      setRoutes(tmpl.routes);
      setGeofences(tmpl.geofences);
      return t;
    });
  }, []);

  const removeTemplate = useCallback((id) => {
    setTemplates(t => t.filter(x => x.id !== id));
  }, []);

  // ── Schedules ────────────────────────────────────────────────────────────

  const addSchedule = useCallback((routeId, robotId, time, days = [1,2,3,4,5]) => {
    const id = genId();
    setSchedules(s => [...s, { id, routeId, robotId, time, days, enabled: true }]);
    return id;
  }, []);

  const updateSchedule = useCallback((id, patch) => {
    setSchedules(s => s.map(sc => sc.id === id ? { ...sc, ...patch } : sc));
  }, []);

  const removeSchedule = useCallback((id) => {
    setSchedules(s => s.filter(sc => sc.id !== id));
  }, []);

  // ── Executions ───────────────────────────────────────────────────────────

  const startExecution = useCallback((routeId, robotId) => {
    setExecutions(e => ({
      ...e,
      [routeId]: { routeId, robotId, currentIdx: 0, state: 'running', startedAt: Date.now(), paused: false },
    }));
  }, []);

  const pauseExecution = useCallback((routeId) => {
    setExecutions(e => ({
      ...e,
      [routeId]: { ...e[routeId], state: 'paused', paused: true },
    }));
  }, []);

  const resumeExecution = useCallback((routeId) => {
    setExecutions(e => ({
      ...e,
      [routeId]: { ...e[routeId], state: 'running', paused: false },
    }));
  }, []);

  const abortExecution = useCallback((routeId) => {
    setExecutions(e => ({
      ...e,
      [routeId]: { ...e[routeId], state: 'aborted' },
    }));
  }, []);

  const advanceExecution = useCallback((routeId, idx) => {
    setExecutions(e => ({
      ...e,
      [routeId]: { ...e[routeId], currentIdx: idx },
    }));
  }, []);

  // ── JSON export / import ─────────────────────────────────────────────────

  const exportJSON = useCallback(() => {
    return JSON.stringify({ waypoints, routes, geofences, templates, schedules }, null, 2);
  }, [waypoints, routes, geofences, templates, schedules]);

  const importJSON = useCallback((json) => {
    const data = JSON.parse(json);
    if (data.waypoints)  setWaypoints(data.waypoints);
    if (data.routes)     setRoutes(data.routes);
    if (data.geofences)  setGeofences(data.geofences);
    if (data.templates)  setTemplates(data.templates);
    if (data.schedules)  setSchedules(data.schedules);
  }, []);

  return {
    // State
    waypoints, routes, geofences, templates, schedules, executions,
    // Waypoints
    addWaypoint, updateWaypoint, removeWaypoint, reorderWaypoints,
    // Routes
    addRoute, updateRoute, removeRoute, addWaypointToRoute, removeWaypointFromRoute,
    // Geofences
    addGeofence, updateGeofence, removeGeofence,
    // Templates
    saveTemplate, loadTemplate, removeTemplate,
    // Schedules
    addSchedule, updateSchedule, removeSchedule,
    // Executions
    startExecution, pauseExecution, resumeExecution, abortExecution, advanceExecution,
    // I/O
    exportJSON, importJSON,
  };
}
