'use client'

import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import * as VisuallyHidden from '@radix-ui/react-visually-hidden'
import { BookOpen, Layout, RepeatIcon, ScrollText, Search, SplitIcon } from 'lucide-react'
import { useParams, useRouter } from 'next/navigation'
import { Dialog, DialogPortal, DialogTitle } from '@/components/ui/dialog'
import { useBrandConfig } from '@/lib/branding/branding'
import { cn } from '@/lib/core/utils/cn'
import { getToolOperationsIndex } from '@/lib/search/tool-operations'
import { getTriggersForSidebar, hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
import { searchItems } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-utils'
import { SIDEBAR_SCROLL_EVENT } from '@/app/workspace/[workspaceId]/w/components/sidebar/sidebar'
import { getAllBlocks } from '@/blocks'
import { usePermissionConfig } from '@/hooks/use-permission-config'

interface SearchModalProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  workflows?: WorkflowItem[]
  workspaces?: WorkspaceItem[]
  isOnWorkflowPage?: boolean
}

interface WorkflowItem {
  id: string
  name: string
  href: string
  color: string
  isCurrent?: boolean
}

interface WorkspaceItem {
  id: string
  name: string
  href: string
  isCurrent?: boolean
}

interface BlockItem {
  id: string
  name: string
  description: string
  icon: React.ComponentType<any>
  bgColor: string
  type: string
  config?: any
}

interface ToolItem {
  id: string
  name: string
  description: string
  icon: React.ComponentType<any>
  bgColor: string
  type: string
}

interface PageItem {
  id: string
  name: string
  icon: React.ComponentType<any>
  href: string
  shortcut?: string
}

interface DocItem {
  id: string
  name: string
  icon: React.ComponentType<any>
  href: string
  type: 'main' | 'block' | 'tool'
}

type SearchItem = {
  id: string
  name: string
  description?: string
  icon?: React.ComponentType<any>
  bgColor?: string
  color?: string
  href?: string
  shortcut?: string
  type: 'block' | 'trigger' | 'tool' | 'tool-operation' | 'workflow' | 'workspace' | 'page' | 'doc'
  isCurrent?: boolean
  blockType?: string
  config?: any
  operationId?: string
  aliases?: string[]
}

interface SearchResultItemProps {
  item: SearchItem
  visualIndex: number
  isSelected: boolean
  onItemClick: (item: SearchItem) => void
}

const SearchResultItem = memo(function SearchResultItem({
  item,
  visualIndex,
  isSelected,
  onItemClick,
}: SearchResultItemProps) {
  const Icon = item.icon
  const showColoredIcon =
    item.type === 'block' ||
    item.type === 'trigger' ||
    item.type === 'tool' ||
    item.type === 'tool-operation'
  const isWorkflow = item.type === 'workflow'
  const isWorkspace = item.type === 'workspace'

  const handleClick = useCallback(() => {
    onItemClick(item)
  }, [onItemClick, item])

  return (
    <button
      data-search-item-index={visualIndex}
      onClick={handleClick}
      onMouseDown={(e) => e.preventDefault()}
      className={cn(
        'group flex h-[28px] w-full items-center gap-[8px] rounded-[6px] bg-[var(--surface-4)]/60 px-[10px] text-left text-[15px] transition-all focus:outline-none',
        isSelected ? 'bg-[var(--border)] shadow-sm' : 'hover:bg-[var(--border)]'
      )}
    >
      {/* Icon - different rendering for workflows vs others */}
      {!isWorkspace && (
        <>
          {isWorkflow ? (
            <div
              className='h-[14px] w-[14px] flex-shrink-0 rounded-[3px]'
              style={{ backgroundColor: item.color }}
            />
          ) : (
            Icon && (
              <div
                className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center overflow-hidden rounded-[4px]'
                style={{ background: showColoredIcon ? item.bgColor : 'transparent' }}
              >
                <Icon
                  className={cn(
                    'transition-transform duration-100 group-hover:scale-110',
                    showColoredIcon
                      ? '!h-[10px] !w-[10px] text-white'
                      : 'h-[14px] w-[14px] text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'
                  )}
                />
              </div>
            )
          )}
        </>
      )}

      {/* Content */}
      <span
        className={cn(
          'truncate font-medium',
          isSelected
            ? 'text-[var(--text-primary)]'
            : 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]'
        )}
      >
        {item.name}
        {item.isCurrent && ' (current)'}
      </span>

      {/* Shortcut */}
      {item.shortcut && (
        <span className='ml-auto flex-shrink-0 font-medium text-[13px] text-[var(--text-subtle)]'>
          {item.shortcut}
        </span>
      )}
    </button>
  )
})

export const SearchModal = memo(function SearchModal({
  open,
  onOpenChange,
  workflows = [],
  workspaces = [],
  isOnWorkflowPage = false,
}: SearchModalProps) {
  const [searchQuery, setSearchQuery] = useState('')
  const [selectedIndex, setSelectedIndex] = useState(0)
  const params = useParams()
  const router = useRouter()
  const workspaceId = params.workspaceId as string
  const brand = useBrandConfig()
  const { filterBlocks } = usePermissionConfig()

  const blocks = useMemo(() => {
    if (!open || !isOnWorkflowPage) return []

    const allBlocks = getAllBlocks()
    const filteredAllBlocks = filterBlocks(allBlocks)
    const regularBlocks = filteredAllBlocks
      .filter(
        (block) => block.type !== 'starter' && !block.hideFromToolbar && block.category === 'blocks'
      )
      .map(
        (block): BlockItem => ({
          id: block.type,
          name: block.name,
          description: block.description || '',
          icon: block.icon,
          bgColor: block.bgColor || '#6B7280',
          type: block.type,
        })
      )

    const specialBlocks: BlockItem[] = [
      {
        id: 'loop',
        name: 'Loop',
        description: 'Create a Loop',
        icon: RepeatIcon,
        bgColor: '#2FB3FF',
        type: 'loop',
      },
      {
        id: 'parallel',
        name: 'Parallel',
        description: 'Parallel Execution',
        icon: SplitIcon,
        bgColor: '#FEE12B',
        type: 'parallel',
      },
    ]

    return [...regularBlocks, ...filterBlocks(specialBlocks)]
  }, [open, isOnWorkflowPage, filterBlocks])

  const triggers = useMemo(() => {
    if (!open || !isOnWorkflowPage) return []

    const allTriggers = getTriggersForSidebar()
    const filteredTriggers = filterBlocks(allTriggers)
    const priorityOrder = ['Start', 'Schedule', 'Webhook']

    const sortedTriggers = filteredTriggers.sort((a, b) => {
      const aIndex = priorityOrder.indexOf(a.name)
      const bIndex = priorityOrder.indexOf(b.name)
      const aHasPriority = aIndex !== -1
      const bHasPriority = bIndex !== -1

      if (aHasPriority && bHasPriority) return aIndex - bIndex
      if (aHasPriority) return -1
      if (bHasPriority) return 1
      return a.name.localeCompare(b.name)
    })

    return sortedTriggers.map(
      (block): BlockItem => ({
        id: block.type,
        name: block.name,
        description: block.description || '',
        icon: block.icon,
        bgColor: block.bgColor || '#6B7280',
        type: block.type,
        config: block,
      })
    )
  }, [open, isOnWorkflowPage, filterBlocks])

  const tools = useMemo(() => {
    if (!open || !isOnWorkflowPage) return []

    const allBlocks = getAllBlocks()
    const filteredAllBlocks = filterBlocks(allBlocks)
    return filteredAllBlocks
      .filter((block) => !block.hideFromToolbar && block.category === 'tools')
      .map(
        (block): ToolItem => ({
          id: block.type,
          name: block.name,
          description: block.description || '',
          icon: block.icon,
          bgColor: block.bgColor || '#6B7280',
          type: block.type,
        })
      )
  }, [open, isOnWorkflowPage, filterBlocks])

  const toolOperations = useMemo(() => {
    if (!open || !isOnWorkflowPage) return []

    const allowedBlockTypes = new Set(tools.map((t) => t.type))

    return getToolOperationsIndex()
      .filter((op) => allowedBlockTypes.has(op.blockType))
      .map((op) => ({
        id: op.id,
        name: `${op.serviceName}: ${op.operationName}`,
        icon: op.icon,
        bgColor: op.bgColor,
        blockType: op.blockType,
        operationId: op.operationId,
        aliases: op.aliases,
      }))
  }, [open, isOnWorkflowPage, tools])

  const pages = useMemo(
    (): PageItem[] => [
      {
        id: 'logs',
        name: 'Logs',
        icon: ScrollText,
        href: `/workspace/${workspaceId}/logs`,
        shortcut: '⌘⇧L',
      },
      {
        id: 'templates',
        name: 'Templates',
        icon: Layout,
        href: `/workspace/${workspaceId}/templates`,
      },
      {
        id: 'docs',
        name: 'Docs',
        icon: BookOpen,
        href: brand.documentationUrl || 'https://docs.sim.ai/',
      },
    ],
    [workspaceId, brand.documentationUrl]
  )

  const docs = useMemo((): DocItem[] => {
    if (!open) return []

    const allBlocks = getAllBlocks()
    const docsItems: DocItem[] = []

    allBlocks.forEach((block) => {
      if (block.docsLink && !block.hideFromToolbar) {
        docsItems.push({
          id: `docs-${block.type}`,
          name: block.name,
          icon: block.icon,
          href: block.docsLink,
          type: block.category === 'blocks' || block.category === 'triggers' ? 'block' : 'tool',
        })
      }
    })

    return docsItems
  }, [open])

  const allItems = useMemo((): SearchItem[] => {
    const items: SearchItem[] = []

    workspaces.forEach((workspace) => {
      items.push({
        id: workspace.id,
        name: workspace.name,
        href: workspace.href,
        type: 'workspace',
        isCurrent: workspace.isCurrent,
      })
    })

    workflows.forEach((workflow) => {
      items.push({
        id: workflow.id,
        name: workflow.name,
        href: workflow.href,
        type: 'workflow',
        color: workflow.color,
        isCurrent: workflow.isCurrent,
      })
    })

    pages.forEach((page) => {
      items.push({
        id: page.id,
        name: page.name,
        icon: page.icon,
        href: page.href,
        shortcut: page.shortcut,
        type: 'page',
      })
    })

    blocks.forEach((block) => {
      items.push({
        id: block.id,
        name: block.name,
        description: block.description,
        icon: block.icon,
        bgColor: block.bgColor,
        type: 'block',
        blockType: block.type,
      })
    })

    triggers.forEach((trigger) => {
      items.push({
        id: trigger.id,
        name: trigger.name,
        description: trigger.description,
        icon: trigger.icon,
        bgColor: trigger.bgColor,
        type: 'trigger',
        blockType: trigger.type,
        config: trigger.config,
      })
    })

    tools.forEach((tool) => {
      items.push({
        id: tool.id,
        name: tool.name,
        description: tool.description,
        icon: tool.icon,
        bgColor: tool.bgColor,
        type: 'tool',
        blockType: tool.type,
      })
    })

    toolOperations.forEach((op) => {
      items.push({
        id: op.id,
        name: op.name,
        icon: op.icon,
        bgColor: op.bgColor,
        type: 'tool-operation',
        blockType: op.blockType,
        operationId: op.operationId,
        aliases: op.aliases,
      })
    })

    docs.forEach((doc) => {
      items.push({
        id: doc.id,
        name: doc.name,
        icon: doc.icon,
        href: doc.href,
        type: 'doc',
      })
    })

    return items
  }, [workspaces, workflows, pages, blocks, triggers, tools, toolOperations, docs])

  const sectionOrder = useMemo<SearchItem['type'][]>(
    () => ['block', 'tool', 'trigger', 'doc', 'tool-operation', 'workflow', 'workspace', 'page'],
    []
  )

  const filteredItems = useMemo(() => {
    const orderMap = sectionOrder.reduce<Record<SearchItem['type'], number>>(
      (acc, type, index) => {
        acc[type] = index
        return acc
      },
      {} as Record<SearchItem['type'], number>
    )

    if (!searchQuery.trim()) {
      return [...allItems].sort((a, b) => {
        const aOrder = orderMap[a.type] ?? Number.MAX_SAFE_INTEGER
        const bOrder = orderMap[b.type] ?? Number.MAX_SAFE_INTEGER
        return aOrder - bOrder
      })
    }

    const searchResults = searchItems(searchQuery, allItems)

    return searchResults
      .sort((a, b) => {
        if (a.score !== b.score) {
          return b.score - a.score
        }

        const aOrder = orderMap[a.item.type] ?? Number.MAX_SAFE_INTEGER
        const bOrder = orderMap[b.item.type] ?? Number.MAX_SAFE_INTEGER
        if (aOrder !== bOrder) {
          return aOrder - bOrder
        }

        return a.item.name.localeCompare(b.item.name)
      })
      .map((result) => result.item)
  }, [allItems, searchQuery, sectionOrder])

  const groupedItems = useMemo(() => {
    const groups: Record<string, SearchItem[]> = {
      workspace: [],
      workflow: [],
      page: [],
      trigger: [],
      block: [],
      'tool-operation': [],
      tool: [],
      doc: [],
    }

    filteredItems.forEach((item) => {
      if (groups[item.type]) {
        groups[item.type].push(item)
      }
    })

    return groups
  }, [filteredItems])

  const displayedItemsInVisualOrder = useMemo(() => {
    const visualOrder: SearchItem[] = []

    sectionOrder.forEach((type) => {
      const items = groupedItems[type] || []
      items.forEach((item) => {
        visualOrder.push(item)
      })
    })

    return visualOrder
  }, [groupedItems, sectionOrder])

  useEffect(() => {
    setSelectedIndex(0)
  }, [displayedItemsInVisualOrder])

  useEffect(() => {
    if (!open) {
      setSearchQuery('')
      setSelectedIndex(0)
    }
  }, [open])

  const handleItemClick = useCallback(
    (item: SearchItem) => {
      switch (item.type) {
        case 'block':
        case 'trigger':
        case 'tool':
          if (item.blockType) {
            const enableTriggerMode =
              item.type === 'trigger' && item.config ? hasTriggerCapability(item.config) : false
            const event = new CustomEvent('add-block-from-toolbar', {
              detail: {
                type: item.blockType,
                enableTriggerMode,
              },
            })
            window.dispatchEvent(event)
          }
          break
        case 'tool-operation':
          if (item.blockType && item.operationId) {
            const event = new CustomEvent('add-block-from-toolbar', {
              detail: {
                type: item.blockType,
                presetOperation: item.operationId,
              },
            })
            window.dispatchEvent(event)
          }
          break
        case 'workspace':
          if (item.isCurrent) {
            break
          }
          if (item.href) {
            router.push(item.href)
          }
          break
        case 'workflow':
          if (!item.isCurrent && item.href) {
            router.push(item.href)
            window.dispatchEvent(
              new CustomEvent(SIDEBAR_SCROLL_EVENT, { detail: { itemId: item.id } })
            )
          }
          break
        case 'page':
        case 'doc':
          if (item.href) {
            if (item.href.startsWith('http')) {
              window.open(item.href, '_blank', 'noopener,noreferrer')
            } else {
              router.push(item.href)
            }
          }
          break
      }
      onOpenChange(false)
    },
    [router, onOpenChange]
  )

  useEffect(() => {
    if (!open) return

    const handleKeyDown = (e: KeyboardEvent) => {
      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault()
          setSelectedIndex((prev) => Math.min(prev + 1, displayedItemsInVisualOrder.length - 1))
          break
        case 'ArrowUp':
          e.preventDefault()
          setSelectedIndex((prev) => Math.max(prev - 1, 0))
          break
        case 'Enter':
          e.preventDefault()
          if (displayedItemsInVisualOrder[selectedIndex]) {
            handleItemClick(displayedItemsInVisualOrder[selectedIndex])
          }
          break
        case 'Escape':
          e.preventDefault()
          onOpenChange(false)
          break
      }
    }

    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [open, selectedIndex, displayedItemsInVisualOrder, handleItemClick, onOpenChange])

  useEffect(() => {
    if (open && selectedIndex >= 0) {
      const element = document.querySelector(`[data-search-item-index="${selectedIndex}"]`)
      if (element) {
        element.scrollIntoView({
          block: 'nearest',
          behavior: 'auto',
        })
      }
    }
  }, [selectedIndex, open])

  const sectionTitles: Record<string, string> = {
    workspace: 'Workspaces',
    workflow: 'Workflows',
    page: 'Pages',
    trigger: 'Triggers',
    block: 'Blocks',
    'tool-operation': 'Tool Operations',
    tool: 'Tools',
    doc: 'Docs',
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogPortal>
        <DialogPrimitive.Overlay className='fixed inset-0 z-40 backdrop-blur-md' />
        <DialogPrimitive.Content className='fixed top-[15%] left-[50%] z-50 flex w-[500px] translate-x-[-50%] flex-col gap-[12px] p-0 focus:outline-none focus-visible:outline-none'>
          <VisuallyHidden.Root>
            <DialogTitle>Search</DialogTitle>
          </VisuallyHidden.Root>

          {/* Search input container */}
          <div className='flex items-center gap-[8px] rounded-[10px] border border-[var(--border)] bg-[var(--surface-4)] px-[12px] py-[8px] shadow-sm'>
            <Search className='h-[15px] w-[15px] flex-shrink-0 text-[var(--text-subtle)]' />
            <input
              type='text'
              placeholder='Search anything...'
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              className='w-full border-0 bg-transparent font-base text-[15px] text-[var(--text-primary)] placeholder:text-[var(--text-secondary)] focus:outline-none'
              autoFocus
            />
          </div>

          {/* Floating results container */}
          {displayedItemsInVisualOrder.length > 0 ? (
            <div className='scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent max-h-[400px] overflow-y-auto rounded-[10px] py-[10px] shadow-sm'>
              {sectionOrder.map((type) => {
                const items = groupedItems[type] || []
                if (items.length === 0) return null

                return (
                  <div key={type} className='mb-[10px] last:mb-0'>
                    {/* Section header */}
                    <div className='pt-[2px] pb-[4px] font-medium text-[13px] text-[var(--text-subtle)] uppercase tracking-wide'>
                      {sectionTitles[type]}
                    </div>

                    {/* Section items */}
                    <div className='space-y-[2px]'>
                      {items.map((item) => {
                        const visualIndex = displayedItemsInVisualOrder.indexOf(item)
                        return (
                          <SearchResultItem
                            key={`${item.type}-${item.id}`}
                            item={item}
                            visualIndex={visualIndex}
                            isSelected={visualIndex === selectedIndex}
                            onItemClick={handleItemClick}
                          />
                        )
                      })}
                    </div>
                  </div>
                )
              })}
            </div>
          ) : searchQuery ? (
            <div className='flex items-center justify-center rounded-[10px] bg-[var(--surface-4)] px-[16px] py-[24px] shadow-sm'>
              <p className='text-[15px] text-[var(--text-subtle)]'>
                No results found for "{searchQuery}"
              </p>
            </div>
          ) : null}
        </DialogPrimitive.Content>
      </DialogPortal>
    </Dialog>
  )
})
