import { useState, useEffect, useMemo, type ReactNode } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import { Box, Cpu, GitBranch, Settings, FileText, ChevronRight, X } from 'lucide-react'
import { AppShell } from '../design-system/layout/AppShell/AppShell'
import { Sidebar } from '../design-system/layout/Sidebar/Sidebar'
import { SidebarTree } from '../design-system/layout/Sidebar/SidebarTree'
import type { SidebarTreeNode } from '../design-system/layout/Sidebar/SidebarTree'
import { useStarred } from '../design-system/layout/Sidebar/useStarred'
import { StatusDot } from '../design-system/primitives/StatusDot/StatusDot'
import { SIDEBAR_APPS } from '../mocks/sidebar'
import type { SidebarApp } from '../mocks/sidebar'
import camelLogoUrl from '../assets/camel-logo.svg'

// ── Helpers ─────────────────────────────────────────────────────────────────

function formatCount(n: number): string {
  if (n >= 1000) return `${(n / 1000).toFixed(1)}k`
  return String(n)
}

// ── Tree node builders ──────────────────────────────────────────────────────

function buildAppTreeNodes(apps: SidebarApp[]): SidebarTreeNode[] {
  return apps.map((app) => ({
    id: app.id,
    label: app.name,
    icon: <StatusDot status={app.health} />,
    badge: formatCount(app.exchangeCount),
    path: `/apps/${app.id}`,
    starrable: true,
    starKey: `app:${app.id}`,
    children: app.routes.map((route) => ({
      id: `${app.id}/${route.id}`,
      label: route.name,
      icon: <ChevronRight size={12} />,
      badge: formatCount(route.exchangeCount),
      path: `/apps/${app.id}/${route.id}`,
    })),
  }))
}

function buildRouteTreeNodes(apps: SidebarApp[]): SidebarTreeNode[] {
  return apps
    .filter((app) => app.routes.length > 0)
    .map((app) => ({
      id: `routes:${app.id}`,
      label: app.name,
      icon: <StatusDot status={app.health} />,
      badge: `${app.routes.length} route${app.routes.length !== 1 ? 's' : ''}`,
      path: `/routes/${app.id}`,
      starrable: true,
      starKey: `routestat:${app.id}`,
      children: app.routes.map((route) => ({
        id: `routes:${app.id}/${route.id}`,
        label: route.name,
        icon: <ChevronRight size={12} />,
        badge: formatCount(route.exchangeCount),
        path: `/routes/${app.id}/${route.id}`,
      })),
    }))
}

function buildAgentTreeNodes(apps: SidebarApp[]): SidebarTreeNode[] {
  return apps
    .filter((app) => app.agents.length > 0)
    .map((app) => {
      const liveCount = app.agents.filter((a) => a.status === 'live').length
      return {
        id: `agents:${app.id}`,
        label: app.name,
        icon: <StatusDot status={app.health} />,
        badge: `${liveCount}/${app.agents.length} live`,
        path: `/agents/${app.id}`,
        starrable: true,
        starKey: `agent:${app.id}`,
        children: app.agents.map((agent) => ({
          id: `agents:${app.id}/${agent.id}`,
          label: agent.name,
          icon: <StatusDot status={agent.status} />,
          badge: `${agent.tps} tps`,
          path: `/agents/${app.id}/${agent.id}`,
        })),
      }
    })
}

// ── Starred items ───────────────────────────────────────────────────────────

interface StarredItem {
  starKey: string
  label: string
  icon?: ReactNode
  path: string
  type: 'application' | 'route' | 'agent' | 'routestat'
  parentApp?: string
}

function collectStarredItems(
  apps: SidebarApp[],
  starredIds: Set<string>,
): StarredItem[] {
  const items: StarredItem[] = []

  for (const app of apps) {
    if (starredIds.has(`app:${app.id}`)) {
      items.push({
        starKey: `app:${app.id}`,
        label: app.name,
        icon: <Box size={12} />,
        path: `/apps/${app.id}`,
        type: 'application',
      })
    }

    for (const route of app.routes) {
      if (starredIds.has(`route:${app.id}/${route.id}`)) {
        items.push({
          starKey: `route:${app.id}/${route.id}`,
          label: route.name,
          icon: <ChevronRight size={12} />,
          path: `/apps/${app.id}/${route.id}`,
          type: 'route',
          parentApp: app.name,
        })
      }
    }

    if (starredIds.has(`routestat:${app.id}`)) {
      items.push({
        starKey: `routestat:${app.id}`,
        label: app.name,
        icon: <GitBranch size={12} />,
        path: `/routes/${app.id}`,
        type: 'routestat',
      })
    }

    if (starredIds.has(`agent:${app.id}`)) {
      items.push({
        starKey: `agent:${app.id}`,
        label: app.name,
        icon: <Cpu size={12} />,
        path: `/agents/${app.id}`,
        type: 'agent',
      })
    }
  }

  return items
}

// ── Starred group component ─────────────────────────────────────────────────

interface StarredGroupProps {
  label: string
  items: StarredItem[]
  onRemove: (starKey: string) => void
  onNavigate: (path: string) => void
}

function StarredGroup({ label, items, onRemove, onNavigate }: StarredGroupProps) {
  if (items.length === 0) return null

  return (
    <div style={{ marginBottom: 8 }}>
      <div
        style={{
          fontSize: 10,
          fontWeight: 600,
          textTransform: 'uppercase',
          letterSpacing: '0.05em',
          color: 'var(--text-tertiary)',
          padding: '4px 12px',
        }}
      >
        {label}
      </div>
      {items.map((item) => (
        <div
          key={item.starKey}
          style={{
            display: 'flex',
            alignItems: 'center',
            gap: 8,
            padding: '4px 12px',
            cursor: 'pointer',
            fontSize: 12,
            color: 'var(--text-secondary)',
            borderRadius: 4,
          }}
          onClick={() => onNavigate(item.path)}
          role="button"
          tabIndex={0}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') onNavigate(item.path)
          }}
        >
          {item.icon && (
            <span style={{ display: 'flex', alignItems: 'center', color: 'var(--text-tertiary)' }}>
              {item.icon}
            </span>
          )}
          <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {item.label}
            {item.parentApp && (
              <span style={{ color: 'var(--text-tertiary)', marginLeft: 4, fontSize: 10 }}>
                {item.parentApp}
              </span>
            )}
          </span>
          <button
            style={{
              background: 'none',
              border: 'none',
              padding: 2,
              cursor: 'pointer',
              color: 'var(--text-tertiary)',
              display: 'flex',
              alignItems: 'center',
              opacity: 0.6,
            }}
            onClick={(e) => {
              e.stopPropagation()
              onRemove(item.starKey)
            }}
            aria-label={`Remove ${item.label} from starred`}
          >
            <X size={10} />
          </button>
        </div>
      ))}
    </div>
  )
}

// ── localStorage-backed section collapse ────────────────────────────────────

function usePersistedCollapse(key: string, defaultValue: boolean): [boolean, () => void] {
  const [value, setValue] = useState(() => {
    try {
      const raw = localStorage.getItem(key)
      if (raw !== null) return raw === 'true'
    } catch { /* ignore */ }
    return defaultValue
  })

  const toggle = () => {
    setValue((prev) => {
      const next = !prev
      try {
        localStorage.setItem(key, String(next))
      } catch { /* ignore */ }
      return next
    })
  }

  return [value, toggle]
}

// ── LayoutShell ─────────────────────────────────────────────────────────────

export function LayoutShell() {
  const navigate = useNavigate()
  const location = useLocation()
  const { starredIds, isStarred, toggleStar } = useStarred()

  const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
  const [filterQuery, setFilterQuery] = useState('')

  // Section collapse state — persisted to localStorage
  const [appsCollapsed, toggleAppsCollapsed] = usePersistedCollapse('cameleer:sidebar:apps-collapsed', false)
  const [agentsCollapsed, toggleAgentsCollapsed] = usePersistedCollapse('cameleer:sidebar:agents-collapsed', false)
  const [routesCollapsed, toggleRoutesCollapsed] = usePersistedCollapse('cameleer:sidebar:routes-collapsed', false)

  // Tree data — static, so empty deps
  const appNodes = useMemo(() => buildAppTreeNodes(SIDEBAR_APPS), [])
  const agentNodes = useMemo(() => buildAgentTreeNodes(SIDEBAR_APPS), [])
  const routeNodes = useMemo(() => buildRouteTreeNodes(SIDEBAR_APPS), [])

  // Sidebar reveal from Cmd-K navigation
  const sidebarRevealPath = (location.state as { sidebarReveal?: string } | null)?.sidebarReveal ?? null

  // Auto-uncollapse matching sections when sidebarRevealPath changes
  useEffect(() => {
    if (!sidebarRevealPath) return

    if (sidebarRevealPath.startsWith('/apps') && appsCollapsed) {
      toggleAppsCollapsed()
    }
    if (sidebarRevealPath.startsWith('/agents') && agentsCollapsed) {
      toggleAgentsCollapsed()
    }
    if (sidebarRevealPath.startsWith('/routes') && routesCollapsed) {
      toggleRoutesCollapsed()
    }
  }, [sidebarRevealPath]) // eslint-disable-line react-hooks/exhaustive-deps

  const effectiveSelectedPath = sidebarRevealPath ?? location.pathname

  // Starred items — collected and grouped
  const allStarred = useMemo(
    () => collectStarredItems(SIDEBAR_APPS, starredIds),
    [starredIds],
  )

  const starredApps = allStarred.filter((s) => s.type === 'application')
  const starredRoutes = allStarred.filter((s) => s.type === 'route')
  const starredAgents = allStarred.filter((s) => s.type === 'agent')
  const starredRouteStats = allStarred.filter((s) => s.type === 'routestat')
  const hasStarred = allStarred.length > 0

  const camelLogo = (
    <img
      src={camelLogoUrl}
      alt=""
      aria-hidden="true"
      style={{
        width: 28,
        height: 24,
        filter:
          'brightness(0) saturate(100%) invert(76%) sepia(30%) saturate(400%) hue-rotate(5deg) brightness(95%)',
      }}
    />
  )

  return (
    <AppShell
      sidebar={
        <Sidebar
          collapsed={sidebarCollapsed}
          onCollapseToggle={() => setSidebarCollapsed((c) => !c)}
          searchValue={filterQuery}
          onSearchChange={setFilterQuery}
        >
          <Sidebar.Header
            logo={camelLogo}
            title="cameleer"
            version="v3.2.1"
            onClick={() => navigate('/apps')}
          />

          <Sidebar.Section
            label="Applications"
            icon={<Box size={14} />}
            open={!appsCollapsed}
            onToggle={toggleAppsCollapsed}
            active={location.pathname.startsWith('/apps')}
          >
            <SidebarTree
              nodes={appNodes}
              selectedPath={effectiveSelectedPath}
              isStarred={isStarred}
              onToggleStar={toggleStar}
              filterQuery={filterQuery}
              persistKey="cameleer:expanded:apps"
              autoRevealPath={sidebarRevealPath}
            />
          </Sidebar.Section>

          <Sidebar.Section
            label="Agents"
            icon={<Cpu size={14} />}
            open={!agentsCollapsed}
            onToggle={toggleAgentsCollapsed}
            active={location.pathname.startsWith('/agents')}
          >
            <SidebarTree
              nodes={agentNodes}
              selectedPath={effectiveSelectedPath}
              isStarred={isStarred}
              onToggleStar={toggleStar}
              filterQuery={filterQuery}
              persistKey="cameleer:expanded:agents"
              autoRevealPath={sidebarRevealPath}
            />
          </Sidebar.Section>

          <Sidebar.Section
            label="Routes"
            icon={<GitBranch size={14} />}
            open={!routesCollapsed}
            onToggle={toggleRoutesCollapsed}
            active={location.pathname.startsWith('/routes')}
          >
            <SidebarTree
              nodes={routeNodes}
              selectedPath={effectiveSelectedPath}
              isStarred={isStarred}
              onToggleStar={toggleStar}
              filterQuery={filterQuery}
              persistKey="cameleer:expanded:routes"
              autoRevealPath={sidebarRevealPath}
            />
          </Sidebar.Section>

          {hasStarred && (
            <Sidebar.Section
              label="\u2605 Starred"
              icon={<span />}
              open={true}
              onToggle={() => {}}
              active={false}
            >
              <StarredGroup
                label="Applications"
                items={starredApps}
                onRemove={toggleStar}
                onNavigate={navigate}
              />
              <StarredGroup
                label="Routes"
                items={starredRoutes}
                onRemove={toggleStar}
                onNavigate={navigate}
              />
              <StarredGroup
                label="Route Stats"
                items={starredRouteStats}
                onRemove={toggleStar}
                onNavigate={navigate}
              />
              <StarredGroup
                label="Agents"
                items={starredAgents}
                onRemove={toggleStar}
                onNavigate={navigate}
              />
            </Sidebar.Section>
          )}

          <Sidebar.Footer>
            <Sidebar.FooterLink
              icon={<Settings size={14} />}
              label="Admin"
              onClick={() => navigate('/admin')}
              active={location.pathname.startsWith('/admin')}
            />
            <Sidebar.FooterLink
              icon={<FileText size={14} />}
              label="API Docs"
              onClick={() => navigate('/api-docs')}
              active={location.pathname === '/api-docs'}
            />
          </Sidebar.Footer>
        </Sidebar>
      }
    >
      <Outlet />
    </AppShell>
  )
}
