// 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 };
}

// 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,
  };
};

const DASHBOARD_TAB_ALIASES = {
  overview: "home",
  diagnostics: "system",
};

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

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

const updateUrlParams = (projectId, ticketId, toolId, lastAction, viewMode, context) => {
  const url = new URL(globalThis.location);
  
  // Update project parameter
  if (projectId) {
    url.searchParams.set('project', projectId);
  } else {
    url.searchParams.delete('project');
  }
  
  // Update ticket parameter
  if (ticketId) {
    url.searchParams.set('ticket', ticketId);
  } else {
    url.searchParams.delete('ticket');
  }
  
  // Update tool parameter
  if (toolId) {
    url.searchParams.set('tool', toolId);
  } else {
    url.searchParams.delete('tool');
  }
  
  // Update action parameter
  if (lastAction) {
    url.searchParams.set('action', lastAction);
  } else {
    url.searchParams.delete('action');
  }
  
  // Update view mode parameter
  if (viewMode) {
    url.searchParams.set('view', viewMode);
  } else {
    url.searchParams.delete('view');
  }
  
  // Update context parameter
  if (context) {
    url.searchParams.set('context', context);
  } else {
    url.searchParams.delete('context');
  }
  
  globalThis.history.replaceState({}, '', url);
};

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

    const systemSection = hash === "diagnostics" ? "diagnostics" : "overview";
    const tab = hash === "diagnostics"
      ? "system"
      : normalizeDashboardTab(hash);

    return { tab, systemSection };
  };

  const initialRoute = getInitialRoute();
  const [tab, setTabState] = useState(initialRoute.tab);
  const [systemSection, setSystemSection] = useState(initialRoute.systemSection);
  const [lastRefresh, setLastRefresh] = useState(null);
  const [selectedProject, setSelectedProject] = useState(getUrlParams().projectId);
  const [selectedTicket, setSelectedTicket] = useState(getUrlParams().ticketId);
  const [selectedTool, setSelectedTool] = useState(getUrlParams().toolId);
  const [lastAction, setLastAction] = useState(getUrlParams().lastAction);
  const [viewMode, setViewMode] = useState(getUrlParams().viewMode);
  const [context, setContext] = useState(getUrlParams().context);

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

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

  // Sync project selection to URL
  const setSelectedProjectWithUrl = useCallback((projectId) => {
    setSelectedProject(projectId);
    setLastAction('select_project');
    updateUrlParams(projectId, selectedTicket, selectedTool, 'select_project', viewMode, context);
  }, [selectedTicket, selectedTool, viewMode, context]);

  // Sync ticket selection to URL
  const setSelectedTicketWithUrl = useCallback((ticketId) => {
    setSelectedTicket(ticketId);
    setLastAction('select_ticket');
    updateUrlParams(selectedProject, ticketId, selectedTool, 'select_ticket', viewMode, context);
  }, [selectedProject, selectedTool, viewMode, context]);

  // Sync tool selection to URL
  const setSelectedToolWithUrl = useCallback((toolId) => {
    setSelectedTool(toolId);
    setLastAction('select_tool');
    updateUrlParams(selectedProject, selectedTicket, toolId, 'select_tool', viewMode, context);
  }, [selectedProject, selectedTicket, viewMode, context]);

  // Update view mode
  const setViewModeWithUrl = useCallback((newViewMode) => {
    setViewMode(newViewMode);
    setLastAction('change_view');
    updateUrlParams(selectedProject, selectedTicket, selectedTool, 'change_view', newViewMode, context);
  }, [selectedProject, selectedTicket, selectedTool, context]);

  // Update context
  const setContextWithUrl = useCallback((newContext) => {
    setContext(newContext);
    updateUrlParams(selectedProject, selectedTicket, selectedTool, lastAction, viewMode, newContext);
  }, [selectedProject, selectedTicket, selectedTool, lastAction, viewMode]);

  // Listen to browser back/forward for hash changes
  useEffect(() => {
    const handleHashChange = () => {
      let newTab = globalThis.location.hash.replace("#", "") || "home";
      if (newTab === "diagnostics") {
        setTabState("system");
        setSystemSection("diagnostics");
        return;
      }

      const normalizedTab = normalizeDashboardTab(newTab);
      setTabState(normalizedTab);
      setSystemSection("overview");
    };
    globalThis.addEventListener("hashchange", handleHashChange);
    return () => globalThis.removeEventListener("hashchange", handleHashChange);
  }, []);

  useEffect(() => {
    const rawHash = globalThis.location.hash.replace("#", "");
  }, []);

  // 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);
    };
    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,
    systemSection,
    selectedProject, setSelectedProject: setSelectedProjectWithUrl,
    selectedTicket, setSelectedTicket: setSelectedTicketWithUrl,
    selectedTool, setSelectedTool: setSelectedToolWithUrl,
    lastAction, setLastAction,
    viewMode, setViewMode: setViewModeWithUrl,
    context, setContext: setContextWithUrl,
    navigationHistory,
    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,
  };
}
