import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { useConfirm } from '@/components/use-confirm-dialog'
import { cn } from '@/lib/utils'
import { useGraphControls } from '@/stores/graph-controls-store'
import { useGraphStore } from '@/stores/graph-store'
import {
  FunnelPlus,
  GitFork,
  GitPullRequestArrow,
  Maximize,
  Merge,
  Minus,
  RotateCw,
  ZoomIn,
  Focus,
  Download,
  LassoSelect,
  ChevronDown,
  SquareDashed
} from 'lucide-react'
import { memo, useCallback } from 'react'
import { toast } from 'sonner'
import Filters from './filters/filters'
import { SaveStatusIndicator } from './save-status-indicator'
import { Separator } from '../ui/separator'
import { ViewToggle } from './view-toggle'
import { NetworkIcon } from '../icons/network'
import { useKeyboard } from '@/hooks/use-keyboard'
import { usePermissions } from '@/hooks/use-can'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { sketchService } from '@/api/sketch-service'
import { useParams } from '@tanstack/react-router'
import { exportToPNG } from './graph/utils/export-to-png'
import { PathFinder } from './graph/actions/path-finder'

// Tooltip wrapper component to avoid repetition
export const ToolbarButton = memo(function ToolbarButton({
  icon,
  tooltip,
  onClick,
  disabled = false,
  badge = null,
  toggled = false,
  showLabel = false
}: {
  icon: React.ReactNode
  tooltip: string | React.ReactNode
  onClick?: () => void
  disabled?: boolean
  badge?: number | null
  toggled?: boolean | null
  showLabel?: boolean
}) {
  return (
    <Tooltip>
      <TooltipTrigger asChild>
        <div>
          <Button
            onClick={onClick}
            disabled={disabled}
            variant="ghost"
            size={showLabel ? 'sm' : 'icon'}
            className={cn(
              'h-7 relative items-center shadow-none',
              !showLabel && 'w-7',
              toggled &&
                'bg-primary/30 border-primary/40 text-primary hover:bg-primary/40 hover:text-primary'
            )}
          >
            {icon} {showLabel && <span className="hidden md:block">{tooltip}</span>}
            {badge && (
              <span className="absolute -top-1 -right-2 !z-[500] bg-primary text-white text-[10px] rounded-full w-auto min-w-4.5 h-4.5 p-1 flex items-center justify-center">
                {badge}
              </span>
            )}
          </Button>
        </div>
      </TooltipTrigger>
      <TooltipContent>{tooltip}</TooltipContent>
    </Tooltip>
  )
})

const FloatingBar = ({
  children,
  className
}: {
  children: React.ReactNode
  className?: string
}) => (
  <div
    className={cn(
      'absolute z-50 flex items-center gap-0.5 rounded-lg border bg-card p-1',
      className
    )}
  >
    {children}
  </div>
)

export const Toolbar = memo(function Toolbar({ isLoading }: { isLoading: boolean }) {
  const { confirm } = useConfirm()
  const { canEdit } = usePermissions()
  const { id: sketchId } = useParams({ strict: false })
  const view = useGraphControls((s) => s.view)
  const setView = useGraphControls((s) => s.setView)
  const zoomToFit = useGraphControls((s) => s.zoomToFit)
  const zoomToSelection = useGraphControls((s) => s.zoomToSelection)
  const zoomIn = useGraphControls((s) => s.zoomIn)
  const zoomOut = useGraphControls((s) => s.zoomOut)
  const regenerateLayout = useGraphControls((s) => s.regenerateLayout)
  const refetchGraph = useGraphControls((s) => s.refetchGraph)
  const isSelectorModeActive = useGraphControls((s) => s.isSelectorModeActive)
  const setIsSelectorModeActive = useGraphControls((s) => s.setIsSelectorModeActive)
  const selectionMode = useGraphControls((s) => s.selectionMode)
  const setSelectionMode = useGraphControls((s) => s.setSelectionMode)
  const selectedNodes = useGraphStore((s) => s.selectedNodes)
  const setOpenAddRelationDialog = useGraphStore((state) => state.setOpenAddRelationDialog)
  const setOpenMergeDialog = useGraphStore((state) => state.setOpenMergeDialog)
  const filters = useGraphStore((s) => s.filters)

  useKeyboard(
    's',
    () => setIsSelectorModeActive(true),
    () => setIsSelectorModeActive(false)
  )

  const handleRefresh = useCallback(() => {
    try {
      refetchGraph()
    } catch (error) {
      toast.error('Failed to refresh graph data')
    }
  }, [refetchGraph])

  const handleApplyForceLayout = useCallback(async () => {
    const confirmed = await confirm({
      title: 'Apply force layout?',
      message:
        'This will reset all node positions and regenerate them using the force-directed layout algorithm. Current positions will be lost.'
    })

    if (!confirmed) {
      return
    }
    try {
      regenerateLayout('force')
      toast.success('Force layout applied successfully')
    } catch (error) {
      toast.error(
        `Failed to apply layout: ${error instanceof Error ? error.message : 'Unknown error'}`
      )
    }
  }, [confirm, regenerateLayout])

  const handleApplyHierarchyLayout = useCallback(async () => {
    const confirmed = await confirm({
      title: 'Apply hierarchy layout?',
      message:
        'This will reset all node positions and regenerate them using the hierarchical layout algorithm. Current positions will be lost.'
    })

    if (!confirmed) {
      return
    }
    try {
      regenerateLayout('hierarchy')
      toast.success('Hierarchy layout applied successfully')
    } catch (error) {
      toast.error(
        `Failed to apply layout: ${error instanceof Error ? error.message : 'Unknown error'}`
      )
    }
  }, [confirm, regenerateLayout])

  const handleOpenAddRelationDialog = useCallback(() => {
    setOpenAddRelationDialog(true)
  }, [setOpenAddRelationDialog])

  const handleOpenMergeDialog = useCallback(() => {
    setOpenMergeDialog(true)
  }, [setOpenMergeDialog])

  const handleToggleSelector = useCallback(() => {
    setIsSelectorModeActive(!isSelectorModeActive)
  }, [setIsSelectorModeActive, isSelectorModeActive])

  const handleSelectMode = useCallback(
    (mode: 'lasso' | 'rectangle') => {
      setSelectionMode(mode)
      if (!isSelectorModeActive) {
        setIsSelectorModeActive(true)
      }
    },
    [setSelectionMode, isSelectorModeActive, setIsSelectorModeActive]
  )

  const handleExport = useCallback(
    async (format: 'json' | 'png') => {
      if (!sketchId) return
      try {
        if (format === 'png') {
          await exportToPNG('null', 'null')
        } else {
          await sketchService.exportSketch(sketchId, format)
        }
        toast.success(`Sketch exported as ${format.toUpperCase()}`)
      } catch (error) {
        toast.error(
          `Failed to export sketch: ${error instanceof Error ? error.message : 'Unknown error'}`
        )
      }
    },
    [sketchId, exportToPNG]
  )

  const areExactlyTwoSelected = selectedNodes.length === 2
  const areMergeable =
    selectedNodes.length > 1 && selectedNodes.every((n) => n.nodeType === selectedNodes[0].nodeType)
  const hasFilters = !(
    filters.types.every((t) => t.checked) || filters.types.every((t) => !t.checked)
  )

  return (
    <>
      {/* Bottom-left: Zoom controls */}
      {(view === 'graph' || view === 'map') && (
        <FloatingBar className="bottom-3 left-3">
          <ToolbarButton
            icon={<ZoomIn className="h-4 w-4 opacity-70" />}
            tooltip="Zoom In"
            onClick={zoomIn}
            disabled={(view !== 'graph' && view !== 'map') || isSelectorModeActive || !zoomIn}
          />
          <ToolbarButton
            icon={<Minus className="h-4 w-4 opacity-70" />}
            tooltip="Zoom Out"
            onClick={zoomOut}
            disabled={(view !== 'graph' && view !== 'map') || isSelectorModeActive}
          />
          <ToolbarButton
            icon={<Maximize className="h-4 w-4 opacity-70" />}
            tooltip="Fit to View"
            onClick={zoomToFit}
            disabled={(view !== 'graph' && view !== 'map') || isSelectorModeActive}
          />
          <ToolbarButton
            icon={<Focus className="h-4 w-4 opacity-70" />}
            tooltip="Zoom to Selection"
            onClick={zoomToSelection}
            disabled={view !== 'graph' || isSelectorModeActive || selectedNodes.length < 2}
          />
        </FloatingBar>
      )}

      {/* Left middle: Selection, Actions & Layout */}
      {view === 'graph' && (
        <FloatingBar className="left-3 top-1/2 -translate-y-1/2 flex-col">
          <div className="flex flex-col items-center">
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  variant="ghost"
                  size="icon"
                  onClick={handleToggleSelector}
                  disabled={view !== 'graph'}
                  className={cn(
                    'h-7 w-7 rounded relative items-center shadow-none',
                    isSelectorModeActive &&
                      'bg-primary/30 border-primary/40 text-primary hover:bg-primary/40 hover:text-primary'
                  )}
                >
                  {selectionMode === 'lasso' ? (
                    <LassoSelect className="h-4 w-4 opacity-70" />
                  ) : (
                    <SquareDashed className="h-4 w-4 opacity-70" />
                  )}
                </Button>
              </TooltipTrigger>
              <TooltipContent>Select (hold S)</TooltipContent>
            </Tooltip>
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <div>
                  <Tooltip>
                    <TooltipTrigger asChild>
                      <Button
                        variant="ghost"
                        size="icon"
                        disabled={view !== 'graph'}
                        className={cn(
                          'h-3! w-5 px-0 rounded relative items-center shadow-none',
                          isSelectorModeActive &&
                            'bg-primary/30 border-primary/40 text-primary hover:bg-primary/40 hover:text-primary'
                        )}
                      >
                        <ChevronDown className="h-3 w-3 opacity-50" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent>Selection mode</TooltipContent>
                  </Tooltip>
                </div>
              </DropdownMenuTrigger>
              <DropdownMenuContent align="start" className="min-w-[140px]">
                <DropdownMenuItem
                  onClick={() => handleSelectMode('lasso')}
                  className={cn(selectionMode === 'lasso' && 'bg-accent')}
                >
                  <LassoSelect className="h-4 w-4 mr-2" />
                  Lasso
                </DropdownMenuItem>
                <DropdownMenuItem
                  onClick={() => handleSelectMode('rectangle')}
                  className={cn(selectionMode === 'rectangle' && 'bg-accent')}
                >
                  <SquareDashed className="h-4 w-4 mr-2" />
                  Rectangle
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          </div>
          <Separator className="w-full" />
          <ToolbarButton
            icon={<GitPullRequestArrow className="h-4 w-4 opacity-70" />}
            tooltip="Connect"
            onClick={handleOpenAddRelationDialog}
            disabled={!canEdit || !areExactlyTwoSelected}
            badge={areExactlyTwoSelected ? 2 : null}
          />
          <ToolbarButton
            icon={<Merge className="h-4 w-4 opacity-70" />}
            tooltip="Merge"
            onClick={handleOpenMergeDialog}
            disabled={!canEdit || !areMergeable}
            badge={areMergeable ? selectedNodes.length : null}
          />
          <PathFinder />
          <Separator className="w-full" />
          <ToolbarButton
            icon={<NetworkIcon className="h-4 w-4 opacity-70" />}
            tooltip="Force layout"
            onClick={handleApplyForceLayout}
            disabled={!canEdit || isLoading || view !== 'graph'}
          />
          <ToolbarButton
            icon={<GitFork strokeWidth={1.4} className="h-4 w-4 opacity-70 rotate-180" />}
            tooltip="Hierarchy layout"
            onClick={handleApplyHierarchyLayout}
            disabled={!canEdit || isLoading || view !== 'graph'}
          />
        </FloatingBar>
      )}

      <FloatingBar className="top-3 left-1/2 -translate-x-1/2">
        <ViewToggle view={view} setView={setView} />
        <Separator orientation="vertical" className="h-5" />
        <Filters>
          <ToolbarButton
            disabled={isLoading}
            icon={<FunnelPlus className={cn('h-4 w-4 opacity-70')} />}
            tooltip="Filters"
            toggled={hasFilters}
          />
        </Filters>
      </FloatingBar>

      {/* Top right: Status, Export, Reload */}
      <FloatingBar className="top-3 right-3">
        <SaveStatusIndicator />
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <div>
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant="ghost"
                    size="icon"
                    disabled={isLoading}
                    className="h-7 w-7 relative items-center shadow-none"
                  >
                    <Download className="h-4 w-4 opacity-70" />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Export</TooltipContent>
              </Tooltip>
            </div>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="min-w-[140px]">
            <DropdownMenuItem onClick={() => handleExport('json')}>Export as JSON</DropdownMenuItem>
            <DropdownMenuItem onClick={() => handleExport('png')}>Export as PNG</DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
        <ToolbarButton
          onClick={handleRefresh}
          disabled={isLoading}
          icon={<RotateCw className={cn('h-4 w-4 opacity-70', isLoading && 'animate-spin')} />}
          tooltip="Refresh"
        />
      </FloatingBar>
    </>
  )
})
