import { useEffect, useRef, type ComponentType, type MouseEvent as ReactMouseEvent } from 'react'
import type { SidebarSelection, VaultEntry, WorkspaceIdentity } from '../types'
import { cn } from '@/lib/utils'
import { getTypeColor, getTypeLightColor } from '../utils/typeColors'
import { type IconProps } from '@phosphor-icons/react'
import { SIDEBAR_ITEM_PADDING } from './sidebar/sidebarStyles'
import { useSidebarInlineRenameInput } from './sidebar/sidebarHooks'
import { Button } from './ui/button'
import { Checkbox } from './ui/checkbox'
import { Input } from './ui/input'
import { translate, type AppLocale } from '../lib/i18n'
import { WorkspaceInitialsBadge } from './WorkspaceInitialsBadge'
import {
  collectTypeVisibilityWorkspaces,
  findTypeDefinitionForWorkspace,
} from '../utils/typeVisibility'

const SIDEBAR_COUNT_PILL_STYLE = {
  borderRadius: 9999,
  padding: '0 6px',
  fontSize: 10,
  fontVariantNumeric: 'tabular-nums',
} as const

export interface SectionGroup {
  label: string
  type: string
  Icon: ComponentType<IconProps>
  customColor?: string | null
}

function resolveSectionColors(type: string, customColor?: string | null) {
  return {
    sectionColor: getTypeColor(type, customColor),
    sectionLightColor: getTypeLightColor(type, customColor),
  }
}

// eslint-disable-next-line react-refresh/only-export-components -- utility co-located with component
export function isSelectionActive(current: SidebarSelection, check: SidebarSelection): boolean {
  if (current.kind !== check.kind) return false
  switch (check.kind) {
    case 'filter': return (current as typeof check).filter === check.filter
    case 'sectionGroup': return (current as typeof check).type === check.type
    case 'folder': return (current as typeof check).path === check.path
    case 'entity': return (current as typeof check).entry.path === check.entry.path
    case 'view': {
      const currentView = current as typeof check
      return currentView.filename === check.filename && (currentView.rootPath ?? '') === (check.rootPath ?? '')
    }
    default: return false
  }
}

// --- NavItem ---

function hasSidebarCount(count?: number): count is number {
  return count !== undefined && count > 0
}

function getNavItemPadding(compact: boolean | undefined, hasCount: boolean) {
  if (compact) return hasCount ? SIDEBAR_ITEM_PADDING.compactWithCount : SIDEBAR_ITEM_PADDING.compact
  return hasCount ? SIDEBAR_ITEM_PADDING.withCount : SIDEBAR_ITEM_PADDING.regular
}

function getNavItemIconSize(compact?: boolean) {
  return compact ? 14 : 16
}

function getNavItemTextClass(compact?: boolean) {
  return compact ? 'text-[12px]' : 'text-[13px]'
}

function resolveBadgeClassName(
  isActive: boolean | undefined,
  activeBadgeClassName: string | undefined,
  badgeClassName: string | undefined,
) {
  if (isActive && activeBadgeClassName) return activeBadgeClassName
  return badgeClassName
}

function resolveBadgeStyle(
  isActive: boolean | undefined,
  activeBadgeClassName: string | undefined,
  activeBadgeStyle: React.CSSProperties | undefined,
  badgeStyle: React.CSSProperties | undefined,
) {
  if (isActive && activeBadgeClassName) return activeBadgeStyle
  return badgeStyle
}

function SidebarNavIcon({
  Icon,
  emoji,
  iconSize,
  isActive,
}: {
  Icon: ComponentType<IconProps>
  emoji?: string | null
  iconSize: number
  isActive?: boolean
}) {
  if (emoji) return <span style={{ fontSize: iconSize, lineHeight: 1, width: iconSize, textAlign: 'center' }}>{emoji}</span>
  return <Icon size={iconSize} weight={isActive ? 'fill' : 'regular'} />
}

export function SidebarCountPill({
  count,
  className,
  style,
  compact,
  testId = 'sidebar-count-chip',
}: {
  count: number
  className?: string
  style?: React.CSSProperties
  compact?: boolean
  testId?: string
}) {
  return (
    <span
      data-testid={testId}
      className={cn("flex items-center justify-center", className)}
      style={{ height: compact ? 18 : 20, ...SIDEBAR_COUNT_PILL_STYLE, ...style }}
    >
      {count}
    </span>
  )
}

export function SidebarLoadingCountPill({ compact, testId = 'sidebar-count-skeleton' }: { compact?: boolean; testId?: string }) {
  return (
    <span
      aria-hidden="true"
      data-testid={testId}
      className="inline-flex animate-pulse rounded-full bg-muted"
      style={{ width: compact ? 22 : 28, height: compact ? 18 : 20 }}
    />
  )
}

function NavItemLabel({ label, compact }: { label: string; compact?: boolean }) {
  return <span className={cn("min-w-0 flex-1 truncate text-left font-medium", getNavItemTextClass(compact))}>{label}</span>
}

function NavItemCount({
  count,
  countLoading,
  className,
  style,
  compact,
}: {
  count?: number
  countLoading?: boolean
  className?: string
  style?: React.CSSProperties
  compact?: boolean
}) {
  if (countLoading) return <SidebarLoadingCountPill compact={compact} />
  if (!hasSidebarCount(count)) return null
  return (
    <SidebarCountPill
      count={count}
      className={className}
      style={style}
      compact={compact}
    />
  )
}

function DisabledNavItem({
  Icon,
  emoji,
  label,
  compact,
  disabledTooltip,
  padding,
}: {
  Icon: ComponentType<IconProps>
  emoji?: string | null
  label: string
  compact?: boolean
  disabledTooltip?: string
  padding: ReturnType<typeof getNavItemPadding>
}) {
  return (
    <div className="flex select-none items-center gap-2 rounded text-foreground" style={{ padding, borderRadius: 4, opacity: 0.4, cursor: 'not-allowed' }} title={disabledTooltip ?? "Coming soon"}>
      <SidebarNavIcon Icon={Icon} emoji={emoji} iconSize={getNavItemIconSize(compact)} />
      <NavItemLabel label={label} compact={compact} />
    </div>
  )
}

function ClickableNavItem({
  Icon,
  emoji,
  label,
  count,
  countLoading,
  isActive,
  activeClassName,
  badgeClassName,
  badgeStyle,
  activeBadgeClassName,
  activeBadgeStyle,
  onClick,
  compact,
  padding,
}: {
  Icon: ComponentType<IconProps>
  emoji?: string | null
  label: string
  count?: number
  countLoading?: boolean
  isActive?: boolean
  activeClassName: string
  badgeClassName?: string
  badgeStyle?: React.CSSProperties
  activeBadgeClassName?: string
  activeBadgeStyle?: React.CSSProperties
  onClick?: () => void
  compact?: boolean
  padding: ReturnType<typeof getNavItemPadding>
}) {
  return (
    <Button
      type="button"
      variant="ghost"
      size="sm"
      className={cn("h-auto w-full cursor-pointer select-none justify-start rounded text-left transition-colors", isActive ? activeClassName : "text-foreground hover:bg-accent")}
      style={{ padding, borderRadius: 4 }}
      onClick={onClick}
    >
      <SidebarNavIcon Icon={Icon} emoji={emoji} iconSize={getNavItemIconSize(compact)} isActive={isActive} />
      <NavItemLabel label={label} compact={compact} />
      <NavItemCount
        count={count}
        countLoading={countLoading}
        className={resolveBadgeClassName(isActive, activeBadgeClassName, badgeClassName)}
        style={resolveBadgeStyle(isActive, activeBadgeClassName, activeBadgeStyle, badgeStyle)}
        compact={compact}
      />
    </Button>
  )
}

export function NavItem({ icon: Icon, emoji, label, count, countLoading, isActive, activeClassName = 'bg-primary/10 text-primary', badgeClassName, badgeStyle, activeBadgeClassName, activeBadgeStyle, onClick, disabled, disabledTooltip, compact }: {
  icon: ComponentType<IconProps>
  emoji?: string | null
  label: string
  count?: number
  countLoading?: boolean
  isActive?: boolean
  activeClassName?: string
  badgeClassName?: string
  badgeStyle?: React.CSSProperties
  activeBadgeClassName?: string
  activeBadgeStyle?: React.CSSProperties
  onClick?: () => void
  disabled?: boolean
  disabledTooltip?: string
  compact?: boolean
}) {
  const padding = getNavItemPadding(compact, countLoading || hasSidebarCount(count))
  if (disabled) {
    return (
      <DisabledNavItem
        Icon={Icon}
        emoji={emoji}
        label={label}
        compact={compact}
        disabledTooltip={disabledTooltip}
        padding={padding}
      />
    )
  }

  return (
    <ClickableNavItem
      Icon={Icon}
      emoji={emoji}
      label={label}
      count={count}
      countLoading={countLoading}
      isActive={isActive}
      activeClassName={activeClassName}
      badgeClassName={badgeClassName}
      badgeStyle={badgeStyle}
      activeBadgeClassName={activeBadgeClassName}
      activeBadgeStyle={activeBadgeStyle}
      onClick={onClick}
      compact={compact}
      padding={padding}
    />
  )
}

// --- Section Content ---

export interface SectionContentProps {
  group: SectionGroup
  itemCount: number
  selection: SidebarSelection
  onSelect: (sel: SidebarSelection) => void
  onContextMenu: (e: React.MouseEvent, type: string) => void
  dragHandleProps?: Record<string, unknown>
  isRenaming?: boolean
  renameInitialValue?: string
  onRenameSubmit?: (value: string) => void
  onRenameCancel?: () => void
  onStartRename?: (type: string) => void
  onSelectTypeNote?: (type: string) => void
  locale?: AppLocale
}

export function SectionContent({
  group, itemCount, selection, onSelect,
  onContextMenu, dragHandleProps,
  isRenaming, renameInitialValue, onRenameSubmit, onRenameCancel, locale,
  onStartRename, onSelectTypeNote,
}: SectionContentProps) {
  const { label, type, Icon, customColor } = group
  const { sectionColor, sectionLightColor } = resolveSectionColors(type, customColor)

  return (
    <SectionHeader
      label={label} type={type} Icon={Icon}
      sectionColor={sectionColor}
      sectionLightColor={sectionLightColor}
      itemCount={itemCount}
      isActive={isSelectionActive(selection, { kind: 'sectionGroup', type })}
      onSelect={() => onSelect({ kind: 'sectionGroup', type })}
      onContextMenu={(e) => onContextMenu(e, type)}
      dragHandleProps={dragHandleProps}
      isRenaming={isRenaming}
      renameInitialValue={renameInitialValue}
      onRenameSubmit={onRenameSubmit}
      onRenameCancel={onRenameCancel}
      onStartRename={onStartRename ? () => onStartRename(type) : undefined}
      onSelectTypeNote={onSelectTypeNote ? () => onSelectTypeNote(type) : undefined}
      locale={locale}
    />
  )
}

function InlineRenameInput({ initialValue, onSubmit, onCancel, locale }: {
  initialValue: string
  onSubmit: (value: string) => void
  onCancel: () => void
  locale?: AppLocale
}) {
  const {
    handleKeyDown,
    inputRef,
    setValue,
    submitValue,
    value,
  } = useSidebarInlineRenameInput({
    initialValue,
    onCancel,
    onSubmit: (nextValue) => onSubmit(nextValue.trim()),
  })

  return (
    <Input
      ref={inputRef}
      value={value}
      onChange={(e) => setValue(e.target.value)}
      onKeyDown={handleKeyDown}
      onBlur={() => { void submitValue() }}
      onClick={(e) => e.stopPropagation()}
      aria-label={translate(locale ?? 'en', 'sidebar.section.name')}
      className="h-auto min-h-0 flex-1 rounded border-primary bg-background px-1 py-px text-[13px] font-medium text-foreground"
    />
  )
}

function getSectionHeaderBackground(isActive: boolean, sectionLightColor: string) {
  if (!isActive) return undefined
  return { background: sectionLightColor }
}

function getSectionHeaderIconWeight(isActive: boolean): IconProps['weight'] {
  return isActive ? 'fill' : 'regular'
}

function getSectionHeaderTitleColor(isActive: boolean, sectionColor: string) {
  if (!isActive) return undefined
  return sectionColor
}

function getSectionSelectHandler(isRenaming: boolean | undefined, onSelect: () => void) {
  if (isRenaming) return undefined
  return onSelect
}

function getSectionContextMenuHandler(
  isRenaming: boolean | undefined,
  onContextMenu: (e: React.MouseEvent) => void,
) {
  if (isRenaming) return undefined
  return onContextMenu
}

function resolveInlineRenameHandlers({
  isRenaming,
  onRenameCancel,
  onRenameSubmit,
}: {
  isRenaming?: boolean
  onRenameCancel?: () => void
  onRenameSubmit?: (value: string) => void
}): { onRenameCancel: () => void; onRenameSubmit: (value: string) => void } | null {
  if (!isRenaming || !onRenameSubmit || !onRenameCancel) return null
  return { onRenameCancel, onRenameSubmit }
}

function SectionHeaderLabel({
  type,
  label,
  isActive,
  sectionColor,
  isRenaming,
  renameInitialValue,
  onRenameSubmit,
  onRenameCancel,
  onStartRename,
  locale,
}: {
  type: string
  label: string
  isActive: boolean
  sectionColor: string
  isRenaming?: boolean
  renameInitialValue?: string
  onRenameSubmit?: (value: string) => void
  onRenameCancel?: () => void
  onStartRename?: () => void
  locale?: AppLocale
}) {
  const inlineRenameHandlers = resolveInlineRenameHandlers({
    isRenaming,
    onRenameCancel,
    onRenameSubmit,
  })

  if (inlineRenameHandlers) {
    return (
      <InlineRenameInput
        key={`rename-${type}`}
        initialValue={renameInitialValue ?? label}
        onSubmit={inlineRenameHandlers.onRenameSubmit}
        onCancel={inlineRenameHandlers.onRenameCancel}
        locale={locale}
      />
    )
  }

  return (
    <button
      type="button"
      className="min-w-0 truncate border-0 bg-transparent p-0 text-left text-[13px] font-medium"
      style={{ marginLeft: 4, color: getSectionHeaderTitleColor(isActive, sectionColor) }}
      onDoubleClick={(event) => {
        event.stopPropagation()
        onStartRename?.()
      }}
    >
      {label}
    </button>
  )
}

function SectionHeaderCountPill({
  itemCount,
  isActive,
  sectionColor,
}: {
  itemCount: number
  isActive: boolean
  sectionColor: string
}) {
  if (itemCount <= 0) return null
  return (
    <SidebarCountPill
      count={itemCount}
      className={!isActive ? 'text-muted-foreground' : undefined}
      style={isActive ? { background: sectionColor, color: 'var(--text-inverse)' } : { background: 'var(--muted)' }}
    />
  )
}

function SectionHeader({ label, type, Icon, sectionColor, sectionLightColor, itemCount, isActive, onSelect, onContextMenu, dragHandleProps, isRenaming, renameInitialValue, onRenameSubmit, onRenameCancel, onStartRename, onSelectTypeNote, locale }: {
  label: string; type: string; Icon: ComponentType<IconProps>
  sectionColor: string; sectionLightColor: string; itemCount: number; isActive: boolean
  onSelect: () => void; onContextMenu: (e: React.MouseEvent) => void
  dragHandleProps?: Record<string, unknown>
  isRenaming?: boolean; renameInitialValue?: string
  onRenameSubmit?: (value: string) => void; onRenameCancel?: () => void
  onStartRename?: () => void; onSelectTypeNote?: () => void
  locale?: AppLocale
}) {
  const headerRef = useRef<HTMLDivElement>(null)
  const selectHandler = getSectionSelectHandler(isRenaming, onSelect)
  const contextMenuHandler = getSectionContextMenuHandler(isRenaming, onContextMenu)
  const doubleClickHandler = !isRenaming ? onSelectTypeNote : undefined

  useEffect(() => {
    const header = headerRef.current
    if (!header) return

    const handleClick = () => selectHandler?.()
    const handleContextMenu = (event: MouseEvent) => contextMenuHandler?.(event as unknown as ReactMouseEvent)
    const handleDoubleClick = () => doubleClickHandler?.()

    header.addEventListener('click', handleClick)
    header.addEventListener('contextmenu', handleContextMenu)
    header.addEventListener('dblclick', handleDoubleClick)
    return () => {
      header.removeEventListener('click', handleClick)
      header.removeEventListener('contextmenu', handleContextMenu)
      header.removeEventListener('dblclick', handleDoubleClick)
    }
  }, [contextMenuHandler, doubleClickHandler, selectHandler])

  return (
    <div
      ref={headerRef}
      className={cn("group/section flex cursor-pointer select-none items-center justify-between rounded transition-colors", !isActive && "hover:bg-accent")}
      style={{ padding: SIDEBAR_ITEM_PADDING.withCount, borderRadius: 4, gap: 4, ...getSectionHeaderBackground(isActive, sectionLightColor) }}
      {...dragHandleProps}
    >
      <div className="flex min-w-0 flex-1 items-center" style={{ gap: 4 }}>
        <Icon size={16} weight={getSectionHeaderIconWeight(isActive)} style={{ color: sectionColor, flexShrink: 0 }} />
        <SectionHeaderLabel
          type={type}
          label={label}
          isActive={isActive}
          sectionColor={sectionColor}
          isRenaming={isRenaming}
          renameInitialValue={renameInitialValue}
          onRenameSubmit={onRenameSubmit}
          onRenameCancel={onRenameCancel}
          onStartRename={onStartRename}
          locale={locale}
        />
      </div>
      {!isRenaming && (
        <SectionHeaderCountPill itemCount={itemCount} isActive={isActive} sectionColor={sectionColor} />
      )}
    </div>
  )
}

type VisibilityToggleHandler = (type: string, typeEntryPath?: string) => void

function VisibilityPopoverItem({
  group,
  isVisible,
  onToggle,
  locale = 'en',
}: {
  group: SectionGroup
  isVisible: boolean
  onToggle: VisibilityToggleHandler
  locale?: AppLocale
}) {
  const { label, type, Icon, customColor } = group
  const { sectionColor } = resolveSectionColors(type, customColor)

  return (
    <Button
      type="button"
      variant="ghost"
      size="sm"
      className="h-auto w-full justify-start rounded-none px-3 py-1.5"
      style={{ padding: '6px 12px', gap: 8 }}
      onClick={() => onToggle(type)}
      aria-label={translate(locale, 'sidebar.section.toggle', { label })}
    >
      <Icon size={14} style={{ color: sectionColor }} />
      <span className="flex-1 text-left text-[13px] text-foreground">{label}</span>
      <ToggleSwitch on={isVisible} />
    </Button>
  )
}

function VisibilityMatrixHeader({ workspaces }: { workspaces: WorkspaceIdentity[] }) {
  return (
    <div
      className="grid items-center gap-2 px-3 pb-1"
      style={{ gridTemplateColumns: `minmax(96px, 1fr) repeat(${workspaces.length}, 28px)` }}
    >
      <div />
      {workspaces.map((workspace) => (
        <div key={workspace.path} className="flex justify-center">
          <WorkspaceInitialsBadge workspace={workspace} />
        </div>
      ))}
    </div>
  )
}

function VisibilityMatrixCell({
  group,
  typeEntry,
  workspace,
  onToggle,
  locale,
}: {
  group: SectionGroup
  typeEntry: VaultEntry | null
  workspace: WorkspaceIdentity
  onToggle: VisibilityToggleHandler
  locale: AppLocale
}) {
  if (!typeEntry) {
    return <span aria-hidden="true" className="mx-auto h-px w-3 bg-border" />
  }

  return (
    <Checkbox
      checked={typeEntry.visible !== false}
      onCheckedChange={() => onToggle(group.type, typeEntry.path)}
      aria-label={translate(locale, 'sidebar.section.toggle', { label: `${group.label} ${workspace.shortLabel}` })}
      className="mx-auto"
    />
  )
}

function VisibilityMatrixRow({
  entries,
  group,
  locale,
  onToggle,
  workspaces,
}: {
  entries: VaultEntry[]
  group: SectionGroup
  locale: AppLocale
  onToggle: VisibilityToggleHandler
  workspaces: WorkspaceIdentity[]
}) {
  const { label, type, Icon, customColor } = group
  const { sectionColor } = resolveSectionColors(type, customColor)

  return (
    <div
      className="grid items-center gap-2 px-3 py-1.5"
      style={{ gridTemplateColumns: `minmax(96px, 1fr) repeat(${workspaces.length}, 28px)` }}
    >
      <div className="flex min-w-0 items-center gap-2">
        <Icon size={14} style={{ color: sectionColor }} />
        <span className="min-w-0 truncate text-left text-[13px] text-foreground">{label}</span>
      </div>
      {workspaces.map((workspace) => (
        <VisibilityMatrixCell
          key={workspace.path}
          group={group}
          typeEntry={findTypeDefinitionForWorkspace(entries, type, workspace.path)}
          workspace={workspace}
          onToggle={onToggle}
          locale={locale}
        />
      ))}
    </div>
  )
}

function VisibilityMatrixPopover({
  entries,
  locale,
  onToggle,
  sections,
  workspaces,
}: {
  entries: VaultEntry[]
  locale: AppLocale
  onToggle: VisibilityToggleHandler
  sections: SectionGroup[]
  workspaces: WorkspaceIdentity[]
}) {
  return (
    <>
      <VisibilityMatrixHeader workspaces={workspaces} />
      {sections.map((group) => (
        <VisibilityMatrixRow
          key={group.type}
          entries={entries}
          group={group}
          locale={locale}
          onToggle={onToggle}
          workspaces={workspaces}
        />
      ))}
    </>
  )
}

// --- Visibility Popover ---

export function VisibilityPopover({ entries, sections, isSectionVisible, onToggle, workspaceOrder = [], locale = 'en' }: {
  entries: VaultEntry[]
  sections: SectionGroup[]
  isSectionVisible: (type: string) => boolean
  onToggle: VisibilityToggleHandler
  workspaceOrder?: readonly string[]
  locale?: AppLocale
}) {
  const workspaces = collectTypeVisibilityWorkspaces(entries, workspaceOrder)
  const showMatrix = workspaces.length > 1

  return (
    <div
      className="border border-border bg-popover text-popover-foreground"
      style={{ position: 'absolute', top: '100%', left: 6, right: 6, zIndex: 50, borderRadius: 8, padding: '8px 0', boxShadow: '0 4px 12px var(--shadow-dialog)' }}
    >
      <div className="text-[12px] font-semibold text-muted-foreground" style={{ padding: '0 12px 4px' }}>{translate(locale, 'sidebar.section.showInSidebar')}</div>
      {showMatrix ? (
        <VisibilityMatrixPopover
          entries={entries}
          locale={locale}
          onToggle={onToggle}
          sections={sections}
          workspaces={workspaces}
        />
      ) : (
        sections.map((group) => (
          <VisibilityPopoverItem
            key={group.type}
            group={group}
            isVisible={isSectionVisible(group.type)}
            onToggle={onToggle}
            locale={locale}
          />
        ))
      )}
    </div>
  )
}

function ToggleSwitch({ on }: { on: boolean }) {
  return (
    <div className="flex items-center" style={{ width: 32, height: 18, borderRadius: 9, padding: 2, backgroundColor: on ? 'var(--primary)' : 'var(--muted)', justifyContent: on ? 'flex-end' : 'flex-start', transition: 'background-color 150ms' }}>
      <div style={{ width: 14, height: 14, borderRadius: 7, backgroundColor: 'var(--background)', transition: 'transform 150ms' }} />
    </div>
  )
}
