'use client'

import React, { useState, useMemo } from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { cn } from '@/lib/utils'
import { MagnifyingGlass, CaretRight, CaretDown, ArrowSquareOut, X } from '@phosphor-icons/react'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import * as PhosphorIcons from '@phosphor-icons/react'
import type { Navigation, NavGroup, NavItem } from '@/lib/docs/navigation'

/**
 * Docs Sidebar Navigation Component
 * 
 * Matches the API docs sidebar styling for visual consistency
 */

// Dynamic icon resolver
function getIcon(iconName: string): React.ComponentType<{ className?: string; weight?: string }> | null {
  if (!iconName) return null
  
  const pascalCase = iconName
    .split(/[-_]/)
    .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join('')
  
  const Icon = (PhosphorIcons as Record<string, unknown>)[pascalCase] as React.ComponentType<{ className?: string; weight?: string }> | undefined
  return Icon || null
}

// Helper to check if item is a NavItem (has href)
function isNavItem(item: NavItem | NavGroup): item is NavItem {
  return 'href' in item && typeof item.href === 'string'
}

// Recursively check if any item matches the path
function hasMatchingItem(items: (NavItem | NavGroup)[], path: string): boolean {
  for (const item of items) {
    if (isNavItem(item)) {
      if (item.href === path || path.startsWith(item.href + '/')) {
        return true
      }
    }
    if ('items' in item && Array.isArray(item.items)) {
      if (hasMatchingItem(item.items, path)) {
        return true
      }
    }
  }
  return false
}

// Filter navigation based on search query
function filterNavigation(navigation: Navigation, query: string): Navigation {
  if (!query.trim()) return navigation
  
  const lowerQuery = query.toLowerCase()
  
  const filterItems = (items: (NavItem | NavGroup)[]): (NavItem | NavGroup)[] => {
    return items.reduce<(NavItem | NavGroup)[]>((acc, item) => {
      if (isNavItem(item)) {
        if (item.title.toLowerCase().includes(lowerQuery)) {
          acc.push(item)
        }
      } else {
        // It's a NavGroup
        const filteredNestedItems = filterItems(item.items)
        if (filteredNestedItems.length > 0 || item.title.toLowerCase().includes(lowerQuery)) {
          acc.push({
            ...item,
            items: filteredNestedItems.length > 0 ? filteredNestedItems : item.items,
          })
        }
      }
      return acc
    }, [])
  }
  
  const filterGroups = (groups: NavGroup[]): NavGroup[] => {
    return groups.reduce<NavGroup[]>((acc, group) => {
      const filteredItems = filterItems(group.items)
      
      if (filteredItems.length > 0 || group.title.toLowerCase().includes(lowerQuery)) {
        acc.push({
          ...group,
          items: filteredItems.length > 0 ? filteredItems : group.items,
        })
      }
      
      return acc
    }, [])
  }
  
  return {
    tabs: navigation.tabs?.map(tab => ({
      ...tab,
      groups: filterGroups(tab.groups),
    })).filter(tab => tab.groups.length > 0),
    groups: navigation.groups ? filterGroups(navigation.groups) : undefined,
    anchors: navigation.anchors,
  }
}

interface DocsSidebarProps {
  navigation: Navigation
  siteName?: string
  className?: string
  isMobile?: boolean
  isOpen?: boolean
  onClose?: () => void
}

export function DocsSidebar({ 
  navigation, 
  siteName = 'Documentation',
  className,
  isMobile = false,
  isOpen = true,
  onClose,
}: DocsSidebarProps) {
  const pathname = usePathname()
  const [searchQuery, setSearchQuery] = useState('')
  const [activeTab, setActiveTab] = useState<string>(
    navigation.tabs?.[0]?.slug || ''
  )
  
  // Filter navigation based on search
  const filteredNav = useMemo(() => 
    filterNavigation(navigation, searchQuery),
    [navigation, searchQuery]
  )
  
  // Find active tab from current path
  React.useEffect(() => {
    if (navigation.tabs) {
      for (const tab of navigation.tabs) {
        for (const group of tab.groups) {
          if (hasMatchingItem(group.items, pathname)) {
            setActiveTab(tab.slug)
            return
          }
        }
      }
    }
  }, [pathname, navigation.tabs])
  
  const currentTabData = filteredNav.tabs?.find(t => t.slug === activeTab)
  const groups = currentTabData?.groups || filteredNav.groups || []
  
  return (
    <>
      {/* Mobile overlay backdrop - z-[55] to cover header (z-50) but below sidebar (z-60) */}
      {isMobile && isOpen && (
        <div 
          className="fixed inset-0 bg-black/50 z-[55] lg:hidden"
          onClick={onClose}
        />
      )}
      
      <aside 
        className={cn(
          "flex flex-col border-r bg-sidebar border-sidebar-border overflow-hidden",
          // Desktop: always visible, fixed width
          "lg:relative lg:w-72 lg:h-full lg:z-auto",
          // Mobile: drawer behavior - z-[60] to appear above header (z-50)
          "fixed inset-y-0 left-0 z-[60] w-[280px] h-full",
          "transform transition-transform duration-300 ease-in-out",
          "lg:transform-none lg:translate-x-0",
          isMobile && !isOpen && "-translate-x-full",
          isMobile && isOpen && "translate-x-0",
          className
        )}
      >
        {/* Header */}
        <div className="px-4 h-[41px] flex items-center justify-between border-b border-sidebar-border shrink-0">
          <h2 className="text-sm font-semibold text-sidebar-foreground truncate">
            {siteName}
          </h2>
          
          {/* Mobile close button */}
          {isMobile && (
            <Button
              variant="ghost"
              size="icon"
              onClick={onClose}
              className="h-7 w-7 lg:hidden"
            >
              <X className="h-4 w-4" weight="bold" />
            </Button>
          )}
        </div>

        {/* Search */}
        <div className="px-3 py-2 border-b border-sidebar-border shrink-0">
          <div className="relative">
            <MagnifyingGlass 
              className="absolute left-2.5 top-1/2 transform -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/60" 
            />
            <Input
              type="text"
              placeholder="Search..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className="w-full pl-8 h-8 text-sm bg-muted/40 border-0 focus-visible:ring-1 focus-visible:ring-border placeholder:text-muted-foreground/50"
            />
            {searchQuery && (
              <button
                onClick={() => setSearchQuery('')}
                className="absolute right-2 top-1/2 transform -translate-y-1/2 text-muted-foreground/60 hover:text-muted-foreground"
              >
                <span className="text-xs">✕</span>
              </button>
            )}
          </div>
        </div>

        {/* Tab selector (if multiple tabs) */}
        {filteredNav.tabs && filteredNav.tabs.length > 1 && (
          <div className="flex border-b border-sidebar-border px-2 py-1 gap-1 shrink-0">
            {filteredNav.tabs.map((tab) => (
              <button
                key={tab.slug}
                onClick={() => setActiveTab(tab.slug)}
                className={cn(
                  'px-3 py-1.5 text-xs font-medium rounded-md transition-colors',
                  activeTab === tab.slug
                    ? 'bg-sidebar-primary text-sidebar-primary-foreground'
                    : 'text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent/50'
                )}
              >
                {tab.title}
              </button>
            ))}
          </div>
        )}

        {/* Scrollable content */}
        <div className="flex-1 overflow-y-auto overflow-x-hidden">
          {groups.map((group, index) => (
            <DocsSidebarSection 
              key={`${group.title}-${index}`}
              title={group.title}
              className={index > 0 ? 'border-t border-sidebar-border' : ''}
            >
              {group.items.map((item, itemIndex) => {
                // Handle nested NavGroup
                if (!isNavItem(item)) {
                  return (
                    <DocsSidebarNestedGroup
                      key={`group-${item.title}-${itemIndex}`}
                      group={item}
                      pathname={pathname}
                      onItemSelect={() => isMobile && onClose?.()}
                    />
                  )
                }
                
                return (
                  <DocsSidebarItem
                    key={`${item.href}-${itemIndex}`}
                    item={item}
                    selected={item.href === pathname}
                    onSelect={() => isMobile && onClose?.()}
                  />
                )
              })}
            </DocsSidebarSection>
          ))}
        </div>
        
        {/* Global anchors */}
        {filteredNav.anchors && filteredNav.anchors.length > 0 && (
          <div className="border-t border-sidebar-border px-2 py-2 shrink-0">
            {filteredNav.anchors.map((anchor, index) => (
              <DocsSidebarItem
                key={`anchor-${index}`}
                item={anchor}
                selected={false}
              />
            ))}
          </div>
        )}
      </aside>
    </>
  )
}

// Section component (matches API docs SidebarSection)
interface DocsSidebarSectionProps {
  title: string
  children: React.ReactNode
  className?: string
}

function DocsSidebarSection({ title, children, className }: DocsSidebarSectionProps) {
  return (
    <div className={cn('flex flex-col', className)}>
      <div className="px-4 py-2.5">
        <span className="text-[11px] font-semibold text-sidebar-foreground/60 uppercase tracking-wider">
          {title}
        </span>
      </div>
      <ul className="flex flex-col gap-px px-2 pb-2">
        {children}
      </ul>
    </div>
  )
}

// Nested group component for recursive groups
interface DocsSidebarNestedGroupProps {
  group: NavGroup
  pathname: string
  onItemSelect?: () => void
}

function DocsSidebarNestedGroup({ group, pathname, onItemSelect }: DocsSidebarNestedGroupProps) {
  const hasActiveChild = hasMatchingItem(group.items, pathname)
  const [isOpen, setIsOpen] = React.useState(hasActiveChild)
  
  return (
    <li className="mb-1">
      <button
        type="button"
        onClick={() => setIsOpen(!isOpen)}
        className={cn(
          "flex items-center justify-between w-full py-1.5 px-2 text-sm rounded-md transition-colors",
          hasActiveChild 
            ? "text-sidebar-foreground font-medium"
            : "text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent/50"
        )}
      >
        <span className="flex items-center gap-2">
          {group.icon && (() => {
            const Icon = getIcon(group.icon)
            return Icon ? <Icon className="w-4 h-4" /> : null
          })()}
          {group.title}
        </span>
        <CaretRight className={cn("w-4 h-4 transition-transform", isOpen && "rotate-90")} />
      </button>
      
      {isOpen && (
        <ul className="ml-4 pl-2 border-l border-sidebar-border space-y-0.5 mt-1">
          {group.items.map((item, idx) => {
            if (!isNavItem(item)) {
              return (
                <DocsSidebarNestedGroup
                  key={`nested-group-${item.title}-${idx}`}
                  group={item}
                  pathname={pathname}
                  onItemSelect={onItemSelect}
                />
              )
            }
            
            return (
              <DocsSidebarItem
                key={`${item.href}-${idx}`}
                item={item}
                selected={item.href === pathname}
                onSelect={onItemSelect}
              />
            )
          })}
        </ul>
      )}
    </li>
  )
}

// Item component (matches API docs SidebarItem)
interface DocsSidebarItemProps {
  item: NavItem
  selected: boolean
  indent?: number
  onSelect?: () => void
}

function DocsSidebarItem({ item, selected, indent = 0, onSelect }: DocsSidebarItemProps) {
  const Icon = item.icon ? getIcon(item.icon) : null
  
  const content = (
    <>
      {Icon && (
        <Icon 
          className={cn(
            'h-4 w-4 shrink-0 mr-2',
            selected ? 'text-sidebar-primary-foreground' : 'text-sidebar-foreground/60'
          )} 
          weight={selected ? 'fill' : 'regular'}
        />
      )}
      <span className="flex-1 truncate">{item.title}</span>
      {item.external && (
        <ArrowSquareOut className="h-3 w-3 shrink-0 ml-1 text-sidebar-foreground/40" />
      )}
      {item.badge && (
        <span className="ml-2 px-1.5 py-0.5 text-[10px] font-medium rounded bg-sidebar-primary/10 text-sidebar-primary">
          {item.badge}
        </span>
      )}
      {item.deprecated && (
        <span className="ml-2 px-1.5 py-0.5 text-[10px] font-medium rounded bg-amber-500/10 text-amber-600 dark:text-amber-400">
          deprecated
        </span>
      )}
    </>
  )
  
  const className = cn(
    'group/button flex items-center rounded-sm px-3 py-1.5 w-full text-left',
    'text-sm leading-5 transition-colors duration-150',
    selected
      ? 'bg-sidebar-primary text-sidebar-primary-foreground font-medium'
      : 'text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground'
  )
  
  const style = indent > 0 ? { paddingLeft: `${indent * 12 + 12}px` } : undefined
  
  if (item.external) {
    return (
      <li className="flex flex-col">
        <a
          href={item.href}
          target="_blank"
          rel="noopener noreferrer"
          className={className}
          style={style}
        >
          {content}
        </a>
      </li>
    )
  }
  
  return (
    <li className="flex flex-col">
      <Link 
        href={item.href} 
        className={className}
        style={style}
        onClick={onSelect}
      >
        {content}
      </Link>
    </li>
  )
}

// Group component with collapsible (matches API docs SidebarGroup)
interface DocsSidebarGroupProps {
  title: string
  items: NavItem[]
  icon?: string
  defaultOpen?: boolean
  currentPath: string
  onItemSelect?: () => void
}

export function DocsSidebarGroup({ 
  title, 
  items, 
  icon,
  defaultOpen = false,
  currentPath,
  onItemSelect,
}: DocsSidebarGroupProps) {
  const hasActiveItem = items.some(item => item.href === currentPath)
  const [isOpen, setIsOpen] = useState(defaultOpen || hasActiveItem)
  
  const Icon = icon ? getIcon(icon) : null
  
  return (
    <li className="flex flex-col gap-px">
      <button
        type="button"
        aria-expanded={isOpen}
        onClick={() => setIsOpen(!isOpen)}
        className={cn(
          'group/button flex items-center rounded-sm px-3 py-1.5 w-full text-left',
          'text-sm leading-5 transition-colors duration-150',
          'text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground'
        )}
      >
        <span className="mr-1.5 text-sidebar-foreground/60 group-hover/button:text-sidebar-foreground">
          {isOpen ? (
            <CaretDown weight="bold" className="h-3.5 w-3.5" />
          ) : (
            <CaretRight weight="bold" className="h-3.5 w-3.5" />
          )}
        </span>
        {Icon && <Icon className="h-4 w-4 mr-2 text-sidebar-foreground/60" weight="regular" />}
        <span className="flex-1 truncate">{title}</span>
      </button>
      
      {isOpen && (
        <ul className="flex flex-col gap-px">
          {items.map((item, index) => (
            <DocsSidebarItem
              key={`${item.href}-${index}`}
              item={item}
              selected={item.href === currentPath}
              indent={1}
              onSelect={onItemSelect}
            />
          ))}
        </ul>
      )}
    </li>
  )
}

export { DocsSidebarSection, DocsSidebarItem }
