import { useMemo, useCallback } from 'react'
import { Routes, Route, Navigate, useNavigate } from 'react-router-dom'
import { Dashboard } from './pages/Dashboard/Dashboard'
import { Routes as RoutesPage } from './pages/Routes/Routes'
import { ExchangeDetail } from './pages/ExchangeDetail/ExchangeDetail'
import { AgentHealth } from './pages/AgentHealth/AgentHealth'
import { AgentInstance } from './pages/AgentInstance/AgentInstance'
import { Inventory } from './pages/Inventory/Inventory'
import { AuditLog } from './pages/Admin/AuditLog/AuditLog'
import { OidcConfig } from './pages/Admin/OidcConfig/OidcConfig'
import { UserManagement } from './pages/Admin/UserManagement/UserManagement'
import { ApiDocs } from './pages/ApiDocs/ApiDocs'

import { CommandPalette } from './design-system/composites/CommandPalette/CommandPalette'
import type { SearchResult } from './design-system/composites/CommandPalette/types'
import { useCommandPalette } from './design-system/providers/CommandPaletteProvider'
import { useGlobalFilters } from './design-system/providers/GlobalFilterProvider'
import { buildSearchData } from './mocks/searchData'
import { exchanges } from './mocks/exchanges'
import { routes } from './mocks/routes'
import { agents } from './mocks/agents'
import { buildRouteToAppMap } from './mocks/sidebar'
import { LayoutShell } from './layout/LayoutShell'

const routeToApp = buildRouteToAppMap()

/** Compute which sidebar path to reveal for a given search result */
function computeSidebarRevealPath(result: SearchResult): string | undefined {
  if (!result.path) return undefined

  if (result.category === 'application') {
    return result.path
  }

  if (result.category === 'route') {
    return result.path
  }

  if (result.category === 'agent') {
    return result.path
  }

  if (result.category === 'exchange') {
    const exchange = exchanges.find((e) => e.id === result.id)
    if (exchange) {
      const appId = routeToApp.get(exchange.route)
      if (appId) return `/apps/${appId}/${exchange.route}`
    }
  }

  return result.path
}

export default function App() {
  const navigate = useNavigate()
  const { open: paletteOpen, setOpen } = useCommandPalette()
  const { isInTimeRange, statusFilters } = useGlobalFilters()

  const filteredSearchData = useMemo(() => {
    // Filter exchanges by time range and status
    let filteredExchanges = exchanges.filter((e) => isInTimeRange(e.timestamp))
    if (statusFilters.size > 0) {
      filteredExchanges = filteredExchanges.filter((e) => statusFilters.has(e.status))
    }
    return buildSearchData(filteredExchanges, routes, agents)
  }, [isInTimeRange, statusFilters])

  const handleSelect = useCallback(
    (result: SearchResult) => {
      if (result.path) {
        const sidebarReveal = computeSidebarRevealPath(result)
        navigate(result.path, { state: sidebarReveal ? { sidebarReveal } : undefined })
      }
      setOpen(false)
    },
    [navigate, setOpen],
  )

  return (
    <>
      <Routes>
        <Route element={<LayoutShell />}>
          <Route path="/" element={<Navigate to="/apps" replace />} />
          <Route path="/apps" element={<Dashboard />} />
          <Route path="/apps/:id" element={<Dashboard />} />
          <Route path="/apps/:id/:routeId" element={<Dashboard />} />
          <Route path="/routes" element={<RoutesPage />} />
          <Route path="/routes/:appId" element={<RoutesPage />} />
          <Route path="/routes/:appId/:routeId" element={<RoutesPage />} />
          <Route path="/exchanges/:id" element={<ExchangeDetail />} />
          <Route path="/agents/:appId/:instanceId" element={<AgentInstance />} />
          <Route path="/agents/*" element={<AgentHealth />} />
          <Route path="/admin" element={<Navigate to="/admin/rbac" replace />} />
          <Route path="/admin/audit" element={<AuditLog />} />
          <Route path="/admin/oidc" element={<OidcConfig />} />
          <Route path="/admin/rbac" element={<UserManagement />} />
          <Route path="/api-docs" element={<ApiDocs />} />
        </Route>
        <Route path="/inventory" element={<Inventory />} />
      </Routes>
      <CommandPalette
        open={paletteOpen}
        onClose={() => setOpen(false)}
        onOpen={() => setOpen(true)}
        data={filteredSearchData}
        onSelect={handleSelect}
      />
    </>
  )
}
