// Custom hooks: specialized data fetchers + useDashboardData aggregator.
// Loaded as a <script type="text/babel"> before panel.jsx.
// Depends on: React (useState, useCallback), get() from api.js

function useHealth() {
  const [health, setHealth] = useState(null);
  const [connected, setConnected] = useState(false);
  const refresh = useCallback(async () => {
    const h = await get("/health");
    setConnected(!!h);
    setHealth(h);
    return !!h;
  }, []);
  return { health, connected, refresh };
}

function useBudget() {
  const [budget, setBudget] = useState(null);
  const [costs, setCosts] = useState(null);
  const refresh = useCallback(async () => {
    const [b, c] = await Promise.all([get("/v1/budget"), get("/dashboard/costs")]);
    setBudget(b);
    setCosts(c);
  }, []);
  return { budget, costs, refresh };
}

function useModels() {
  const [models, setModels] = useState([]);
  const refresh = useCallback(async () => {
    const m = await get("/v1/models");
    setModels(m?.data || []);
  }, []);
  return { models, refresh };
}

function useProviders() {
  const [providers, setProviders] = useState([]);
  const refresh = useCallback(async () => {
    const p = await get("/dashboard/providers");
    setProviders(p?.providers || []);
  }, []);
  return { providers, refresh };
}

function useResources() {
  const [accounts, setAccounts] = useState([]);
  const [vms, setVMs] = useState([]);
  const [context, setContext] = useState(null);
  const refresh = useCallback(async () => {
    const [a, v, ctx] = await Promise.all([
      get("/dashboard/accounts"),
      get("/dashboard/vms"),
      get("/v1/context/stats"),
    ]);
    setAccounts(a?.accounts || []);
    setVMs(v?.vms || []);
    setContext(ctx);
  }, []);
  return { accounts, vms, context, refresh };
}

function useLogs() {
  const [logs, setLogs] = useState([]);
  const [logsError, setLogsError] = useState(null);
  const [logsSource, setLogsSource] = useState(null);
  const refresh = useCallback(async () => {
    try {
      const l = await get("/dashboard/logs?lines=50");
      setLogs(l?.logs || []);
      setLogsError(l?.error || null);
      setLogsSource(l?.source || null);
    } catch (e) {
      setLogsError(e.message);
      setLogs([]);
    }
  }, []);
  return { logs, logsError, logsSource, refresh };
}

const normalizeDashboardTheme = (theme) => (theme === "dark" ? "dark" : "white");

const getInitialDashboardTheme = () => {
  const prefersDark = globalThis.matchMedia?.("(prefers-color-scheme: dark)")?.matches;
  return prefersDark ? "dark" : "white";
};

const applyDashboardTheme = (theme) => {
  const normalizedTheme = normalizeDashboardTheme(theme);
  const root = globalThis.document?.documentElement;

  if (root) {
    root.dataset.theme = normalizedTheme;
    root.style.colorScheme = normalizedTheme === "dark" ? "dark" : "light";
  }

  return normalizedTheme;
};

// Helper functions for URL parameters
const getUrlParams = () => {
  const params = new URLSearchParams(globalThis.location.search);
  return {
    projectId: params.get('project') || null,
    ticketId: params.get('ticket') || null,
    toolId: params.get('tool') || null,
    lastAction: params.get('action') || null,
    viewMode: params.get('view') || null,
    context: params.get('context') || null,
    filterStatus: params.get('status') || null,
    filterAgent: params.get('agent') || null,
    searchQuery: params.get('search') || null,
  };
};

const DASHBOARD_TAB_ALIASES = {
  human: "tasks",
  tickets: "tasks",
};

const DASHBOARD_VALID_TABS = new Set(["home", "overview", "projects", "tasks", "voice", "accounts", "models", "vms", "tools", "environments", "users", "setup", "diagnostics", "system"]);

const normalizeDashboardTab = (tab) => {
  const normalized = DASHBOARD_TAB_ALIASES[tab] || tab || "home";
  return DASHBOARD_VALID_TABS.has(normalized) ? normalized : "home";
};

const normalizeDashboardAction = (action, legacyTaskRoute = false) => {
  if (legacyTaskRoute) return "navigate_to_tasks";
  if (action === "navigate_to_human" || action === "navigate_to_tickets") return "navigate_to_tasks";
  return action || null;
};

const normalizeDashboardContext = (context, legacyTaskRoute = false) => {
  if (legacyTaskRoute) return "tasks";
  if (!context) return null;
  return DASHBOARD_TAB_ALIASES[context] || context;
};

const _setOrDelete = (url, key, value) => {
  if (value) { url.searchParams.set(key, value); } else { url.searchParams.delete(key); }
};

const updateUrlParams = (params, usePush) => {
  const url = new URL(globalThis.location);
  _setOrDelete(url, 'project', params.projectId);
  _setOrDelete(url, 'ticket', params.ticketId);
  _setOrDelete(url, 'tool', params.toolId);
  _setOrDelete(url, 'action', params.lastAction);
  _setOrDelete(url, 'view', params.viewMode);
  _setOrDelete(url, 'context', params.context);
  _setOrDelete(url, 'status', params.filterStatus);
  _setOrDelete(url, 'agent', params.filterAgent);
  _setOrDelete(url, 'search', params.searchQuery);
  if (usePush) {
    globalThis.history.pushState({}, '', url);
  } else {
    globalThis.history.replaceState({}, '', url);
  }
};

function useDashboardData() {
  // Read initial tab from URL hash
  const getInitialRoute = () => {
    let hash = globalThis.location.hash.replace("#", "");
    const tab = normalizeDashboardTab(hash);

    return { tab };
  };

  const initialRoute = getInitialRoute();
  const urlParams = getUrlParams();
  const [tab, setTabState] = useState(initialRoute.tab);
  const [lastRefresh, setLastRefresh] = useState(null);
  const [selectedProject, setSelectedProject] = useState(urlParams.projectId);
  const [selectedTicket, setSelectedTicket] = useState(urlParams.ticketId);
  const [selectedTool, setSelectedTool] = useState(urlParams.toolId);
  const [lastAction, setLastAction] = useState(normalizeDashboardAction(urlParams.lastAction));
  const [viewMode, setViewMode] = useState(urlParams.viewMode);
  const [context, setContext] = useState(normalizeDashboardContext(urlParams.context));
  const [filterStatus, setFilterStatus] = useState(urlParams.filterStatus || "");
  const [filterAgent, setFilterAgent] = useState(urlParams.filterAgent || "");
  const [searchQuery, setSearchQuery] = useState(urlParams.searchQuery || "");
  const canonicalizedUrlRef = React.useRef(false);
  const [theme, setThemeState] = useState(getInitialDashboardTheme);

  // Track navigation history
  const [navigationHistory, setNavigationHistory] = useState([]);

  // Helper to build current URL params object from latest state
  // We use refs so the helper always reads fresh values without re-creating callbacks
  const stateRef = React.useRef({});
  stateRef.current = {
    projectId: selectedProject, ticketId: selectedTicket, toolId: selectedTool,
    lastAction, viewMode, context, filterStatus, filterAgent, searchQuery,
  };
  const _pushUrl = useCallback((overrides) => {
    updateUrlParams({ ...stateRef.current, ...overrides }, true);
  }, []);
  const _replaceUrl = useCallback((overrides) => {
    updateUrlParams({ ...stateRef.current, ...overrides }, false);
  }, []);

  useEffect(() => {
    applyDashboardTheme(theme);
  }, [theme]);

  const toggleTheme = useCallback(() => {
    setThemeState((currentTheme) => (currentTheme === "dark" ? "white" : "dark"));
  }, []);

  useEffect(() => {
    if (canonicalizedUrlRef.current) return;
    canonicalizedUrlRef.current = true;

    const currentUrl = new URL(globalThis.location.href);
    const currentHash = currentUrl.hash.replace("#", "") || "home";
    const currentAction = currentUrl.searchParams.get("action");
    const currentContext = currentUrl.searchParams.get("context");
    const legacyTaskRoute = (
      currentHash === "human"
      || currentHash === "tickets"
      || currentAction === "navigate_to_human"
      || currentAction === "navigate_to_tickets"
      || currentContext === "human"
      || currentContext === "tickets"
    );

    const canonicalTab = legacyTaskRoute ? "tasks" : normalizeDashboardTab(currentHash);
    const canonicalAction = normalizeDashboardAction(currentAction, legacyTaskRoute);
    const canonicalContext = normalizeDashboardContext(currentContext, legacyTaskRoute);

    if (
      canonicalTab !== currentHash
      || canonicalAction !== currentAction
      || canonicalContext !== currentContext
    ) {
      setTabState(canonicalTab);
      setLastAction(canonicalAction);
      setContext(canonicalContext);
      globalThis.location.hash = canonicalTab;
      _replaceUrl({ lastAction: canonicalAction, context: canonicalContext });
    }
  }, []);

  // Sync tab changes to URL
  const setTab = useCallback((newTab) => {
    const normalizedTab = normalizeDashboardTab(newTab);
    setTabState(normalizedTab);
    const newAction = `navigate_to_${normalizedTab}`;
    setLastAction(newAction);
    setContext(normalizedTab);
    globalThis.location.hash = normalizedTab;
    _pushUrl({ lastAction: newAction, context: normalizedTab });
    
    // Update navigation history
    setNavigationHistory(prev => [...prev.slice(-9), {
      tab: normalizedTab,
      timestamp: new Date().toISOString(),
      projectId: selectedProject,
      ticketId: selectedTicket,
      toolId: selectedTool
    }]);
  }, [selectedProject, selectedTicket, selectedTool, _pushUrl]);

  // Sync project selection to URL
  const setSelectedProjectWithUrl = useCallback((projectId) => {
    setSelectedProject(projectId);
    setLastAction('select_project');
    _pushUrl({ projectId, lastAction: 'select_project' });
  }, [_pushUrl]);

  // Sync ticket selection to URL
  const setSelectedTicketWithUrl = useCallback((ticketId) => {
    setSelectedTicket(ticketId);
    setLastAction('select_ticket');
    _pushUrl({ ticketId, lastAction: 'select_ticket' });
  }, [_pushUrl]);

  // Sync tool selection to URL
  const setSelectedToolWithUrl = useCallback((toolId) => {
    setSelectedTool(toolId);
    setLastAction('select_tool');
    _pushUrl({ toolId, lastAction: 'select_tool' });
  }, [_pushUrl]);

  // Update view mode
  const setViewModeWithUrl = useCallback((newViewMode) => {
    setViewMode(newViewMode);
    setLastAction('change_view');
    _pushUrl({ viewMode: newViewMode, lastAction: 'change_view' });
  }, [_pushUrl]);

  // Update context
  const setContextWithUrl = useCallback((newContext) => {
    setContext(newContext);
    _pushUrl({ context: newContext });
  }, [_pushUrl]);

  // Sync filter status to URL
  const setFilterStatusWithUrl = useCallback((newStatus) => {
    setFilterStatus(newStatus);
    _pushUrl({ filterStatus: newStatus });
  }, [_pushUrl]);

  // Sync filter agent to URL
  const setFilterAgentWithUrl = useCallback((newAgent) => {
    setFilterAgent(newAgent);
    _pushUrl({ filterAgent: newAgent });
  }, [_pushUrl]);

  // Sync search query to URL (use replaceState to avoid flooding history)
  const setSearchQueryWithUrl = useCallback((newQuery) => {
    setSearchQuery(newQuery);
    _replaceUrl({ searchQuery: newQuery });
  }, [_replaceUrl]);

  // Keyboard shortcuts for tab navigation
  useEffect(() => {
    const SHORTCUTS = {
      h: "home",
      o: "overview",
      p: "projects",
      t: "tasks",
      k: "tickets",
      q: "tools",
      d: "diagnostics",
      s: "system",
      e: "environments",
      u: "users",
    };
    const handleKeyDown = (e) => {
      // Skip when typing in inputs, textareas, or contenteditable
      const tag = (e.target.tagName || "").toLowerCase();
      if (tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable) return;
      // Skip when modifier keys are held (Ctrl, Alt, Meta)
      if (e.ctrlKey || e.altKey || e.metaKey) return;

      const key = e.key.toLowerCase();
      if (key === "?") {
        // Show shortcut help in console
        console.log("[Proxym Shortcuts] h=Home o=Overview p=Projects t=Tasks k=Tickets q=Tools d=Diagnostics s=System e=Environments u=Users r=Refresh D=DarkMode");
        return;
      }
      if (key === "r") {
        e.preventDefault();
        refresh();
        return;
      }
      if (key === "d" && e.shiftKey) {
        // Shift+D = toggle dark mode
        e.preventDefault();
        toggleTheme();
        return;
      }
      if (SHORTCUTS[key]) {
        e.preventDefault();
        setTab(SHORTCUTS[key]);
      }
    };
    globalThis.addEventListener("keydown", handleKeyDown);
    return () => globalThis.removeEventListener("keydown", handleKeyDown);
  }, [setTab, refresh, toggleTheme]);

  // Listen to browser back/forward for hash changes
  useEffect(() => {
    const handleHashChange = () => {
      let newTab = globalThis.location.hash.replace("#", "") || "home";
      const normalizedTab = normalizeDashboardTab(newTab);
      setTabState(normalizedTab);
    };
    globalThis.addEventListener("hashchange", handleHashChange);
    return () => globalThis.removeEventListener("hashchange", handleHashChange);
  }, []);

  // Listen to browser back/forward for URL parameter changes
  useEffect(() => {
    const handlePopState = () => {
      const params = getUrlParams();
      setSelectedProject(params.projectId);
      setSelectedTicket(params.ticketId);
      setSelectedTool(params.toolId);
      setLastAction(params.lastAction);
      setViewMode(params.viewMode);
      setContext(params.context);
      setFilterStatus(params.filterStatus || "");
      setFilterAgent(params.filterAgent || "");
      setSearchQuery(params.searchQuery || "");
      // Also update hash-based tab
      const newTab = globalThis.location.hash.replace("#", "") || "home";
      setTabState(normalizeDashboardTab(newTab));
    };
    globalThis.addEventListener("popstate", handlePopState);
    return () => globalThis.removeEventListener("popstate", handlePopState);
  }, []);

  const healthHook = useHealth();
  const budgetHook = useBudget();
  const modelsHook = useModels();
  const providersHook = useProviders();
  const resourcesHook = useResources();
  const logsHook = useLogs();

  const refresh = useCallback(async () => {
    const isUp = await healthHook.refresh();
    if (isUp) {
      await Promise.all([budgetHook.refresh(), modelsHook.refresh(), providersHook.refresh(), resourcesHook.refresh(), logsHook.refresh()]);
    }
    setLastRefresh(new Date());
  }, [healthHook.refresh, budgetHook.refresh, modelsHook.refresh, providersHook.refresh, resourcesHook.refresh, logsHook.refresh]);

  useEffect(() => {
    refresh();
    const i = setInterval(refresh, 15000);
    return () => clearInterval(i);
  }, [refresh]);

  return {
    tab, setTab,
    selectedProject, setSelectedProject: setSelectedProjectWithUrl,
    selectedTicket, setSelectedTicket: setSelectedTicketWithUrl,
    selectedTool, setSelectedTool: setSelectedToolWithUrl,
    lastAction, setLastAction,
    viewMode, setViewMode: setViewModeWithUrl,
    context, setContext: setContextWithUrl,
    filterStatus, setFilterStatus: setFilterStatusWithUrl,
    filterAgent, setFilterAgent: setFilterAgentWithUrl,
    searchQuery, setSearchQuery: setSearchQueryWithUrl,
    navigationHistory,
    theme,
    toggleTheme,
    health: healthHook.health,
    connected: healthHook.connected,
    budget: budgetHook.budget,
    costs: budgetHook.costs,
    models: modelsHook.models,
    providers: providersHook.providers,
    accounts: resourcesHook.accounts,
    vms: resourcesHook.vms,
    resourcesContext: resourcesHook.context,
    logs: logsHook.logs,
    logsError: logsHook.logsError,
    logsSource: logsHook.logsSource,
    lastRefresh, refresh,
  };
}
