/*
 * Copyright 2025 Daytona Platforms Inc.
 * SPDX-License-Identifier: AGPL-3.0
 */

import { useCommandPaletteAnalytics } from '@/hooks/useCommandPaletteAnalytics'
import { Logo, LogoText } from '@/assets/Logo'
import { OrganizationPicker } from '@/components/Organizations/OrganizationPicker'
import {
  Sidebar as SidebarComponent,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupContent,
  SidebarHeader,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarSeparator,
  SidebarTrigger,
  useSidebar,
} from '@/components/ui/sidebar'
import { DAYTONA_DOCS_URL, DAYTONA_SLACK_URL } from '@/constants/ExternalLinks'
import { useTheme } from '@/contexts/ThemeContext'
import { FeatureFlags } from '@/enums/FeatureFlags'
import { RoutePath } from '@/enums/RoutePath'
import { useSelectedOrganization } from '@/hooks/useSelectedOrganization'
import { useUserOrganizationInvitations } from '@/hooks/useUserOrganizationInvitations'
import { useWebhooks } from '@/hooks/useWebhooks'
import { cn, getMetaKey } from '@/lib/utils'
import { usePylon, usePylonCommands } from '@/vendor/pylon'
import { OrganizationRolePermissionsEnum, OrganizationUserRoleEnum } from '@daytona/api-client'
import {
  ArrowRightIcon,
  BookOpen,
  Box,
  ChartColumn,
  ChevronsUpDown,
  Container,
  CreditCard,
  HardDrive,
  Joystick,
  KeyRound,
  LifeBuoyIcon,
  ListChecks,
  LockKeyhole,
  LogOut,
  Mail,
  MapPinned,
  MoonIcon,
  PackageOpen,
  SearchIcon,
  Server,
  Settings,
  Slack,
  SquareUserRound,
  SunIcon,
  TextSearch,
  Users,
} from 'lucide-react'
import { useFeatureFlagEnabled, usePostHog } from 'posthog-js/react'
import React, { useMemo } from 'react'
import { useAuth } from 'react-oidc-context'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { CommandConfig, useCommandPaletteActions, useRegisterCommands } from './CommandPalette'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from './ui/dropdown-menu'
import { Kbd } from './ui/kbd'
import { ScrollArea } from './ui/scroll-area'

interface SidebarProps {
  isBannerVisible: boolean
  billingEnabled: boolean
  version: string
}

interface SidebarItem {
  icon: React.ReactElement
  label: string
  path: RoutePath | string
  onClick?: () => void
}

const useNavCommands = (items: { label: string; path: RoutePath | string; onClick?: () => void }[]) => {
  const { pathname } = useLocation()
  const navigate = useNavigate()

  const navCommands: CommandConfig[] = useMemo(
    () =>
      items
        .filter((item) => item.path !== pathname)
        .map((item) => ({
          id: `nav-${item.path}`,
          label: `Go to ${item.label}`,
          icon: <ArrowRightIcon className="w-4 h-4" />,
          onSelect: () => navigate(item.path),
        })),
    [pathname, navigate, items],
  )

  useRegisterCommands(navCommands, { groupId: 'navigation', groupLabel: 'Navigation', groupOrder: 1 })
}

export function Sidebar({ isBannerVisible, billingEnabled, version }: SidebarProps) {
  const posthog = usePostHog()
  const { theme, setTheme } = useTheme()
  const { user, signoutRedirect } = useAuth()
  const { pathname } = useLocation()
  const sidebar = useSidebar()
  const { selectedOrganization, authenticatedUserOrganizationMember, authenticatedUserHasPermission } =
    useSelectedOrganization()
  const { count: organizationInvitationsCount } = useUserOrganizationInvitations()
  const { isInitialized: webhooksInitialized } = useWebhooks()
  const orgInfraEnabled = useFeatureFlagEnabled(FeatureFlags.ORGANIZATION_INFRASTRUCTURE)

  const sidebarItems = useMemo(() => {
    const arr: SidebarItem[] = [
      {
        icon: <Container size={16} strokeWidth={1.5} />,
        label: 'Sandboxes',
        path: RoutePath.SANDBOXES,
      },
      {
        icon: <Box size={16} strokeWidth={1.5} />,
        label: 'Snapshots',
        path: RoutePath.SNAPSHOTS,
      },
      {
        icon: <PackageOpen size={16} strokeWidth={1.5} />,
        label: 'Registries',
        path: RoutePath.REGISTRIES,
      },
    ]
    if (authenticatedUserHasPermission(OrganizationRolePermissionsEnum.READ_VOLUMES)) {
      arr.push({
        icon: <HardDrive size={16} strokeWidth={1.5} />,
        label: 'Volumes',
        path: RoutePath.VOLUMES,
      })
    }

    if (authenticatedUserHasPermission(OrganizationRolePermissionsEnum.READ_AUDIT_LOGS)) {
      arr.push({
        icon: <TextSearch size={16} strokeWidth={1.5} />,
        label: 'Audit Logs',
        path: RoutePath.AUDIT_LOGS,
      })
    }

    return arr
  }, [authenticatedUserHasPermission])

  const settingsItems = useMemo(() => {
    const arr: SidebarItem[] = [
      {
        icon: <Settings size={16} strokeWidth={1.5} />,
        label: 'Settings',
        path: RoutePath.SETTINGS,
      },
      { icon: <KeyRound size={16} strokeWidth={1.5} />, label: 'API Keys', path: RoutePath.KEYS },
    ]

    if (webhooksInitialized) {
      arr.push({
        icon: <Mail size={16} strokeWidth={1.5} />,
        label: 'Webhooks',
        path: RoutePath.WEBHOOKS,
      })
    }

    if (authenticatedUserOrganizationMember?.role === OrganizationUserRoleEnum.OWNER) {
      arr.push({
        icon: <LockKeyhole size={16} strokeWidth={1.5} />,
        label: 'Limits',
        path: RoutePath.LIMITS,
      })
    }
    if (!selectedOrganization?.personal) {
      arr.push({
        icon: <Users size={16} strokeWidth={1.5} />,
        label: 'Members',
        path: RoutePath.MEMBERS,
      })
      // TODO: uncomment when we allow creating custom roles
      // if (authenticatedUserOrganizationMember?.role === OrganizationUserRoleEnum.OWNER) {
      //   arr.push({ icon: <UserCog className="w-5 h-5" />, label: 'Roles', path: RoutePath.ROLES })
      // }
    }

    return arr
  }, [authenticatedUserOrganizationMember?.role, selectedOrganization?.personal, webhooksInitialized])

  const billingItems = useMemo(() => {
    if (!billingEnabled || authenticatedUserOrganizationMember?.role !== OrganizationUserRoleEnum.OWNER) {
      return []
    }

    return [
      {
        icon: <ChartColumn size={16} strokeWidth={1.5} />,
        label: 'Spending',
        path: RoutePath.BILLING_SPENDING,
      },
      {
        icon: <CreditCard size={16} strokeWidth={1.5} />,
        label: 'Wallet',
        path: RoutePath.BILLING_WALLET,
      },
    ]
  }, [billingEnabled, authenticatedUserOrganizationMember?.role])

  const infrastructureItems = useMemo(() => {
    if (!orgInfraEnabled) {
      return []
    }

    const arr = [
      {
        icon: <MapPinned size={16} strokeWidth={1.5} />,
        label: 'Regions',
        path: RoutePath.REGIONS,
      },
    ]

    if (authenticatedUserHasPermission(OrganizationRolePermissionsEnum.READ_RUNNERS)) {
      arr.push({
        icon: <Server size={16} strokeWidth={1.5} />,
        label: 'Runners',
        path: RoutePath.RUNNERS,
      })
    }

    return arr
  }, [authenticatedUserHasPermission, orgInfraEnabled])

  const handleSignOut = () => {
    posthog?.reset()
    signoutRedirect()
  }

  const miscItems = useMemo(() => {
    return [
      {
        icon: <Joystick size={16} strokeWidth={1.5} />,
        label: 'Playground',
        path: RoutePath.PLAYGROUND,
      },
    ]
  }, [])

  const sidebarGroups: { label: string; items: SidebarItem[] }[] = useMemo(() => {
    return [
      { label: 'Sandboxes', items: sidebarItems },
      {
        label: 'Misc',
        items: miscItems,
      },
      { label: 'Settings', items: settingsItems },
      { label: 'Billing', items: billingItems },
      { label: 'Infrastructure', items: infrastructureItems },
    ].filter((group) => group.items.length > 0)
  }, [sidebarItems, settingsItems, billingItems, infrastructureItems, miscItems])

  const commandItems = useMemo(() => {
    return sidebarGroups
      .flatMap((group) => group.items)
      .concat(
        {
          path: RoutePath.ACCOUNT_SETTINGS,
          label: 'Account Settings',
          icon: <Settings size={16} strokeWidth={1.5} />,
        },
        {
          path: RoutePath.USER_INVITATIONS,
          label: 'Invitations',
          icon: <Mail size={16} strokeWidth={1.5} />,
        },
        {
          path: RoutePath.ONBOARDING,
          label: 'Onboarding',
          icon: <ListChecks size={16} strokeWidth={1.5} />,
        },
      )
  }, [sidebarGroups])

  const { unreadCount: pylonUnreadCount, toggle: togglePylon, isEnabled: pylonEnabled } = usePylon()
  usePylonCommands()

  const commandPaletteActions = useCommandPaletteActions()
  const { trackOpened } = useCommandPaletteAnalytics()

  useNavCommands(commandItems)

  const metaKey = getMetaKey()

  return (
    <SidebarComponent isBannerVisible={isBannerVisible} collapsible="icon">
      <SidebarHeader>
        <div
          className={cn('flex justify-between items-center gap-2 px-2 mb-2 h-12', {
            'justify-center px-0': !sidebar.open,
          })}
        >
          <div className="flex items-center gap-2 group-data-[state=collapsed]:hidden text-primary">
            <Logo />
            <LogoText />
          </div>
          <SidebarTrigger className="p-2 [&_svg]:size-5" />
        </div>
        <SidebarMenu>
          <OrganizationPicker />
          <SidebarMenuItem className="mb-1">
            <SidebarMenuButton
              tooltip={`Search ${metaKey}+K`}
              variant="outline"
              className="flex items-center gap-2 justify-between dark:bg-input/30 dark:hover:bg-sidebar-accent hover:shadow-[0_0_0_1px_hsl(var(--sidebar-border))]"
              onClick={() => {
                trackOpened('sidebar_search')
                commandPaletteActions.setIsOpen(true)
              }}
            >
              <span className="flex items-center gap-2">
                <SearchIcon className="w-4 h-4" /> Search
              </span>
              <Kbd className="whitespace-nowrap">{metaKey} K</Kbd>
            </SidebarMenuButton>
          </SidebarMenuItem>
        </SidebarMenu>
      </SidebarHeader>
      <SidebarContent>
        <ScrollArea fade="shadow" className="overflow-auto flex-1">
          {sidebarGroups.map((group, i) => (
            <React.Fragment key={group.label}>
              {i > 0 && <SidebarSeparator />}
              <SidebarGroup>
                <SidebarGroupContent>
                  <SidebarMenu>
                    {group.items.map((item) => (
                      <SidebarMenuItem key={item.label}>
                        <SidebarMenuButton
                          asChild
                          isActive={pathname.startsWith(item.path)}
                          className="text-sm"
                          tooltip={item.label}
                        >
                          {item.onClick ? (
                            <button onClick={() => item.onClick?.()}>
                              {item.icon}
                              <span>{item.label}</span>
                            </button>
                          ) : (
                            <Link to={item.path}>
                              {item.icon}
                              <span>{item.label}</span>
                            </Link>
                          )}
                        </SidebarMenuButton>
                      </SidebarMenuItem>
                    ))}
                  </SidebarMenu>
                </SidebarGroupContent>
              </SidebarGroup>
            </React.Fragment>
          ))}
        </ScrollArea>
      </SidebarContent>
      <SidebarFooter className="pb-4">
        <SidebarMenu>
          {pylonEnabled && (
            <SidebarMenuItem>
              <SidebarMenuButton
                tooltip="Support"
                onClick={() => {
                  togglePylon()
                }}
              >
                <LifeBuoyIcon className="size-4" strokeWidth={1.5} />
                Support
                {pylonUnreadCount > 0 && (
                  <div className={cn('w-2 h-2 bg-green-500 rounded-full transition-all')}>
                    <div className={cn('w-full h-full bg-green-500 rounded-full animate-ping')} />
                  </div>
                )}
              </SidebarMenuButton>
            </SidebarMenuItem>
          )}
          <SidebarMenuItem>
            <SidebarMenuButton asChild tooltip="Slack">
              <a href={DAYTONA_SLACK_URL} className=" h-8 py-0" target="_blank" rel="noopener noreferrer">
                <Slack size={16} strokeWidth={1.5} />
                <span>Slack</span>
              </a>
            </SidebarMenuButton>
          </SidebarMenuItem>
          <SidebarMenuItem>
            <SidebarMenuButton asChild tooltip="Docs">
              <a href={DAYTONA_DOCS_URL} className=" h-8 py-0" target="_blank" rel="noopener noreferrer">
                <BookOpen size={16} strokeWidth={1.5} />
                <span>Docs</span>
              </a>
            </SidebarMenuButton>
          </SidebarMenuItem>
          <SidebarMenuItem>
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <SidebarMenuButton
                  className={cn(
                    'flex flex-shrink-0 items-center outline outline-1 outline-border outline-offset-0 bg-muted font-medium mt-2',
                    {
                      'h-12': sidebar.open,
                    },
                  )}
                  tooltip="Profile"
                >
                  {user?.profile.picture ? (
                    <img
                      src={user.profile.picture}
                      alt={user.profile.name || 'Profile picture'}
                      className="h-4 w-4 rounded-sm flex-shrink-0"
                    />
                  ) : (
                    <SquareUserRound className="!w-4 !h-4  flex-shrink-0" />
                  )}
                  <div className="flex-1 min-w-0">
                    <span className="truncate block">{user?.profile.name || ''}</span>
                    <span className="truncate block text-muted-foreground text-xs">{user?.profile.email || ''}</span>
                  </div>
                  <ChevronsUpDown className="w-4 h-4 opacity-50 flex-shrink-0" />
                </SidebarMenuButton>
              </DropdownMenuTrigger>
              <DropdownMenuContent side="top" align="start" className="w-[--radix-popper-anchor-width] min-w-[12rem]">
                <DropdownMenuItem asChild>
                  <Link to={RoutePath.ACCOUNT_SETTINGS}>
                    <Settings className="size-4" />
                    Account Settings
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
                  {theme === 'dark' ? <SunIcon className="size-4" /> : <MoonIcon className="size-4" />}
                  {theme === 'dark' ? 'Light mode' : 'Dark mode'}
                </DropdownMenuItem>
                <DropdownMenuSeparator />
                <DropdownMenuItem asChild>
                  <Link to={RoutePath.USER_INVITATIONS}>
                    <Mail className="size-4" />
                    Invitations
                    {organizationInvitationsCount > 0 && (
                      <span className="ml-auto px-2 py-0.5 text-xs font-medium bg-secondary rounded-full">
                        {organizationInvitationsCount}
                      </span>
                    )}
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link to={RoutePath.ONBOARDING}>
                    <ListChecks className="size-4" />
                    Onboarding
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuSeparator />
                <DropdownMenuItem onClick={handleSignOut}>
                  <LogOut className="size-4" />
                  Sign out
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          </SidebarMenuItem>
          <SidebarMenuItem key="version">
            <div
              className={cn(
                'flex items-center w-full justify-center gap-2 mt-2 overflow-auto min-h-4 whitespace-nowrap',
              )}
            >
              {sidebar.open && <span className="text-xs text-muted-foreground">Version {version}</span>}
            </div>
          </SidebarMenuItem>
        </SidebarMenu>
      </SidebarFooter>
    </SidebarComponent>
  )
}
