'use client'

import { useState, useMemo, useRef, useEffect, useCallback } from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { adminPortalContainer } from '../../lib/portal-container.js'
import {
  Star,
  Type,
  Image,
  LayoutGrid,
  MousePointer,
  Play,
  Grid,
  HelpCircle,
  FileText,
  Code,
  Box,
  X,
  ArrowLeft,
  Search,
  Check,
} from 'lucide-react'
import type { LucideIcon } from 'lucide-react'
import { BlockCatalog } from '@actuate-media/cms-core/page-builder'
import type { BlockTypeDefinition, VariantDefinition } from '@actuate-media/cms-core'

export interface BlockPickerProps {
  open: boolean
  onClose: () => void
  onSelect: (blockType: string, variant?: string) => void
}

const iconMap: Record<string, LucideIcon> = {
  Star,
  Type,
  Image,
  LayoutGrid,
  MousePointer,
  Play,
  Grid,
  HelpCircle,
  FileText,
  Code,
}

function resolveIcon(name: string): LucideIcon {
  return iconMap[name] ?? Box
}

export function BlockPicker({ open, onClose, onSelect }: BlockPickerProps) {
  const [search, setSearch] = useState('')
  const [selectedBlock, setSelectedBlock] = useState<BlockTypeDefinition | null>(null)
  const searchInputRef = useRef<HTMLInputElement>(null)
  const variantListRef = useRef<HTMLDivElement>(null)

  const catalog = useMemo(() => new BlockCatalog(), [])
  const allBlocks = useMemo(() => catalog.getAll(), [catalog])

  const filteredBlocks = useMemo(() => {
    if (!search.trim()) return allBlocks
    const q = search.toLowerCase()
    return allBlocks.filter(
      (block) =>
        block.label.toLowerCase().includes(q) ||
        (block.description?.toLowerCase().includes(q) ?? false),
    )
  }, [allBlocks, search])

  const resetState = useCallback(() => {
    setSearch('')
    setSelectedBlock(null)
  }, [])

  useEffect(() => {
    if (open) {
      resetState()
    }
  }, [open, resetState])

  useEffect(() => {
    if (open && !selectedBlock) {
      const timer = setTimeout(() => searchInputRef.current?.focus(), 50)
      return () => clearTimeout(timer)
    }
  }, [open, selectedBlock])

  useEffect(() => {
    if (selectedBlock && variantListRef.current) {
      const firstButton =
        variantListRef.current.querySelector<HTMLButtonElement>('button[data-variant]')
      firstButton?.focus()
    }
  }, [selectedBlock])

  function handleBlockClick(block: BlockTypeDefinition) {
    if (block.variants.length === 1) {
      onSelect(block.type, block.variants[0]!.name)
      onClose()
      return
    }
    setSelectedBlock(block)
  }

  function handleVariantClick(variant: VariantDefinition) {
    if (!selectedBlock) return
    onSelect(selectedBlock.type, variant.name)
    onClose()
  }

  function handleBack() {
    setSelectedBlock(null)
  }

  function handleKeyDownOnGrid(e: React.KeyboardEvent) {
    if (e.key === 'Escape') {
      e.stopPropagation()
      onClose()
    }
  }

  function handleKeyDownOnVariants(e: React.KeyboardEvent) {
    if (e.key === 'Escape') {
      e.stopPropagation()
      handleBack()
    }
  }

  return (
    <Dialog.Root open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
      <Dialog.Portal container={adminPortalContainer()}>
        <Dialog.Overlay className="motion-safe:animate-in motion-safe:fade-in-0 fixed inset-0 z-50 bg-black/50" />
        <Dialog.Content
          className="bg-card border-border fixed top-1/2 left-1/2 z-50 flex max-h-[80vh] w-full max-w-2xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border shadow-2xl"
          aria-describedby={undefined}
          onEscapeKeyDown={() => {
            if (selectedBlock) {
              handleBack()
            }
          }}
        >
          {selectedBlock ? (
            <VariantView
              block={selectedBlock}
              variantListRef={variantListRef}
              onBack={handleBack}
              onVariantClick={handleVariantClick}
              onKeyDown={handleKeyDownOnVariants}
            />
          ) : (
            <BlockTypeGrid
              search={search}
              filteredBlocks={filteredBlocks}
              searchInputRef={searchInputRef}
              onSearchChange={setSearch}
              onBlockClick={handleBlockClick}
              onClose={onClose}
              onKeyDown={handleKeyDownOnGrid}
            />
          )}
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
}

interface BlockTypeGridProps {
  search: string
  filteredBlocks: BlockTypeDefinition[]
  searchInputRef: React.RefObject<HTMLInputElement | null>
  onSearchChange: (value: string) => void
  onBlockClick: (block: BlockTypeDefinition) => void
  onClose: () => void
  onKeyDown: (e: React.KeyboardEvent) => void
}

function BlockTypeGrid({
  search,
  filteredBlocks,
  searchInputRef,
  onSearchChange,
  onBlockClick,
  onClose,
  onKeyDown,
}: BlockTypeGridProps) {
  return (
    <div className="flex h-full flex-col" onKeyDown={onKeyDown}>
      <div className="flex items-center justify-between gap-3 px-5 pt-5 pb-3">
        <Dialog.Title className="text-foreground text-lg font-medium">Add Block</Dialog.Title>
        <Dialog.Close asChild>
          <button
            type="button"
            className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
            aria-label="Close"
          >
            <X size={18} />
          </button>
        </Dialog.Close>
      </div>

      <div className="px-5 pb-3">
        <div className="relative">
          <Search
            className="text-muted-foreground pointer-events-none absolute top-1/2 left-3 -translate-y-1/2"
            size={16}
          />
          <input
            ref={searchInputRef}
            type="text"
            placeholder="Search blocks..."
            value={search}
            onChange={(e) => onSearchChange(e.target.value)}
            className="bg-background border-input focus:ring-ring w-full rounded-md border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
            aria-label="Search block types"
          />
        </div>
      </div>

      <div className="flex-1 overflow-y-auto px-5 pb-5">
        {filteredBlocks.length === 0 ? (
          <div className="flex flex-col items-center justify-center py-12 text-center">
            <Search size={24} className="text-muted-foreground mb-2" />
            <p className="text-muted-foreground text-sm">No blocks match &ldquo;{search}&rdquo;</p>
          </div>
        ) : (
          <div className="grid grid-cols-2 gap-3" role="list" aria-label="Available block types">
            {filteredBlocks.map((block) => {
              const Icon = resolveIcon(block.icon)
              return (
                <button
                  key={block.type}
                  type="button"
                  role="listitem"
                  onClick={() => onBlockClick(block)}
                  className="border-border hover:border-primary bg-card group focus:ring-ring flex cursor-pointer items-start gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
                >
                  <div className="bg-accent text-foreground group-hover:bg-primary/10 group-hover:text-primary flex h-9 w-9 shrink-0 items-center justify-center rounded-md transition-colors">
                    <Icon size={18} />
                  </div>
                  <div className="min-w-0">
                    <p className="text-foreground truncate text-sm font-medium">{block.label}</p>
                    {block.description && (
                      <p className="text-muted-foreground mt-0.5 line-clamp-2 text-xs">
                        {block.description}
                      </p>
                    )}
                  </div>
                </button>
              )
            })}
          </div>
        )}
      </div>
    </div>
  )
}

interface VariantViewProps {
  block: BlockTypeDefinition
  variantListRef: React.RefObject<HTMLDivElement | null>
  onBack: () => void
  onVariantClick: (variant: VariantDefinition) => void
  onKeyDown: (e: React.KeyboardEvent) => void
}

function VariantView({
  block,
  variantListRef,
  onBack,
  onVariantClick,
  onKeyDown,
}: VariantViewProps) {
  const Icon = resolveIcon(block.icon)

  return (
    <div className="flex h-full flex-col" onKeyDown={onKeyDown}>
      <div className="flex items-center gap-3 px-5 pt-5 pb-3">
        <button
          type="button"
          onClick={onBack}
          className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
          aria-label="Back to block types"
        >
          <ArrowLeft size={18} />
        </button>
        <div className="flex min-w-0 items-center gap-2">
          <Icon size={18} className="text-foreground shrink-0" />
          <h2 className="text-foreground truncate text-lg font-medium">{block.label}</h2>
        </div>
      </div>

      {block.description && (
        <p className="text-muted-foreground px-5 pb-3 text-sm">{block.description}</p>
      )}

      <div className="flex-1 overflow-y-auto px-5 pb-5" ref={variantListRef}>
        <div className="space-y-2" role="list" aria-label={`${block.label} variants`}>
          {block.variants.map((variant, index) => (
            <button
              key={variant.name}
              type="button"
              role="listitem"
              data-variant={variant.name}
              onClick={() => onVariantClick(variant)}
              className="border-border hover:border-primary bg-card group focus:ring-ring flex w-full cursor-pointer items-center gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
            >
              <div className="min-w-0 flex-1">
                <div className="flex items-center gap-2">
                  <p className="text-foreground text-sm font-medium">{variant.label}</p>
                  {index === 0 && (
                    <span className="text-primary bg-primary/10 inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs">
                      <Check size={10} />
                      Default
                    </span>
                  )}
                </div>
                <p className="text-muted-foreground mt-0.5 text-xs">{variant.description}</p>
              </div>
            </button>
          ))}
        </div>
      </div>
    </div>
  )
}
