'use client'

import {
  ChevronRight,
  ChevronDown,
  FolderOpen,
  Folder as FolderIcon,
  Plus,
  MoreHorizontal,
  Pencil,
  Trash2,
  FolderPlus,
  Clock,
  Inbox,
  LayoutGrid,
  Loader2,
} from 'lucide-react'
import { useState, useEffect, useCallback, useRef } from 'react'
import { toast } from 'sonner'
import { cmsApi } from '../lib/api.js'

export interface FolderNode {
  id: string
  name: string
  scope: string
  parentId: string | null
  position: number
  children: FolderNode[]
}

export type SmartFolder = 'all' | 'recent' | 'uncategorized'

export type FolderSelection =
  | { type: 'smart'; smart: SmartFolder }
  | { type: 'folder'; folderId: string }

export interface FolderTreeProps {
  scope: string
  selected: FolderSelection
  onSelect: (selection: FolderSelection) => void
  itemCounts?: Record<string, number>
  totalCount?: number
  recentCount?: number
  uncategorizedCount?: number
  onDropItem?: (itemId: string, folderId: string | null) => void
}

export function FolderTree({
  scope,
  selected,
  onSelect,
  itemCounts,
  totalCount,
  recentCount,
  uncategorizedCount,
  onDropItem,
}: FolderTreeProps) {
  const [folders, setFolders] = useState<FolderNode[]>([])
  const [loading, setLoading] = useState(true)
  const [expanded, setExpanded] = useState<Set<string>>(new Set())
  const [editingId, setEditingId] = useState<string | null>(null)
  const [editName, setEditName] = useState('')
  const [contextMenu, setContextMenu] = useState<{ id: string; x: number; y: number } | null>(null)
  const [creatingIn, setCreatingIn] = useState<string | null | false>(false)
  const [newFolderName, setNewFolderName] = useState('')
  const newFolderInputRef = useRef<HTMLInputElement>(null)
  const editInputRef = useRef<HTMLInputElement>(null)
  const [dragOverId, setDragOverId] = useState<string | null>(null)

  const fetchFolders = useCallback(async () => {
    const res = await cmsApi<FolderNode[]>(`/folders?scope=${scope}`)
    if (res.data) setFolders(res.data)
    setLoading(false)
  }, [scope])

  useEffect(() => {
    fetchFolders()
  }, [fetchFolders])

  useEffect(() => {
    if (creatingIn !== false && newFolderInputRef.current) {
      newFolderInputRef.current.focus()
    }
  }, [creatingIn])

  useEffect(() => {
    if (editingId && editInputRef.current) {
      editInputRef.current.focus()
      editInputRef.current.select()
    }
  }, [editingId])

  useEffect(() => {
    const handleClick = () => setContextMenu(null)
    document.addEventListener('click', handleClick)
    return () => document.removeEventListener('click', handleClick)
  }, [])

  const toggleExpand = (id: string) => {
    setExpanded((prev) => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      return next
    })
  }

  const handleCreate = async (parentId: string | null) => {
    if (!newFolderName.trim()) {
      setCreatingIn(false)
      return
    }
    const res = await cmsApi('/folders', {
      method: 'POST',
      body: JSON.stringify({ name: newFolderName.trim(), scope, parentId }),
    })
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Folder created')
      if (parentId) setExpanded((prev) => new Set(prev).add(parentId))
      fetchFolders()
    }
    setNewFolderName('')
    setCreatingIn(false)
  }

  const handleRename = async (id: string) => {
    if (!editName.trim()) {
      setEditingId(null)
      return
    }
    const res = await cmsApi(`/folders/${id}`, {
      method: 'PUT',
      body: JSON.stringify({ name: editName.trim() }),
    })
    if (res.error) toast.error(res.error)
    else fetchFolders()
    setEditingId(null)
  }

  const handleDelete = async (id: string) => {
    const res = await cmsApi(`/folders/${id}`, { method: 'DELETE' })
    if (res.error) toast.error(res.error)
    else {
      toast.success('Folder deleted')
      if (selected.type === 'folder' && selected.folderId === id) {
        onSelect({ type: 'smart', smart: 'all' })
      }
      fetchFolders()
    }
  }

  const isSelected = (sel: FolderSelection) => {
    if (selected.type !== sel.type) return false
    if (sel.type === 'smart') return (selected as any).smart === sel.smart
    return (selected as any).folderId === (sel as any).folderId
  }

  const handleDragOver = (e: React.DragEvent, folderId: string | null) => {
    e.preventDefault()
    e.stopPropagation()
    setDragOverId(folderId)
  }

  const handleDragLeave = () => {
    setDragOverId(null)
  }

  const handleDrop = (e: React.DragEvent, folderId: string | null) => {
    e.preventDefault()
    e.stopPropagation()
    setDragOverId(null)
    const itemId = e.dataTransfer.getData('text/actuate-item-id')
    if (itemId && onDropItem) {
      onDropItem(itemId, folderId)
    }
  }

  const countForFolder = (id: string): number | undefined => itemCounts?.[id]

  const renderFolder = (folder: FolderNode, depth: number) => {
    const isExpanded = expanded.has(folder.id)
    const hasChildren = folder.children.length > 0
    const isActive = isSelected({ type: 'folder', folderId: folder.id })
    const isDragOver = dragOverId === folder.id
    const count = countForFolder(folder.id)

    return (
      <div key={folder.id}>
        <div
          className={`group flex cursor-pointer items-center gap-1 rounded-md px-2 py-1.5 text-sm transition-colors ${
            isActive
              ? 'bg-primary/10 text-primary font-medium'
              : isDragOver
                ? 'bg-primary/15 ring-primary/40 ring-2'
                : 'text-foreground hover:bg-muted'
          }`}
          style={{ paddingLeft: `${8 + depth * 16}px` }}
          onClick={() => onSelect({ type: 'folder', folderId: folder.id })}
          onContextMenu={(e) => {
            e.preventDefault()
            setContextMenu({ id: folder.id, x: e.clientX, y: e.clientY })
          }}
          onDragOver={(e) => handleDragOver(e, folder.id)}
          onDragLeave={handleDragLeave}
          onDrop={(e) => handleDrop(e, folder.id)}
        >
          <button
            type="button"
            className={`hover:bg-muted rounded p-0.5 transition-colors ${hasChildren ? '' : 'invisible'}`}
            onClick={(e) => {
              e.stopPropagation()
              toggleExpand(folder.id)
            }}
          >
            {isExpanded ? (
              <ChevronDown className="h-3.5 w-3.5" />
            ) : (
              <ChevronRight className="h-3.5 w-3.5" />
            )}
          </button>

          {isExpanded ? (
            <FolderOpen className="text-primary h-4 w-4 shrink-0" />
          ) : (
            <FolderIcon className="text-muted-foreground h-4 w-4 shrink-0" />
          )}

          {editingId === folder.id ? (
            <input
              ref={editInputRef}
              type="text"
              value={editName}
              onChange={(e) => setEditName(e.target.value)}
              onBlur={() => handleRename(folder.id)}
              onKeyDown={(e) => {
                if (e.key === 'Enter') handleRename(folder.id)
                if (e.key === 'Escape') setEditingId(null)
              }}
              className="border-primary/50 focus:ring-ring min-w-0 flex-1 rounded border px-1 py-0 text-sm focus:ring-1 focus:outline-none"
              onClick={(e) => e.stopPropagation()}
            />
          ) : (
            <span className="min-w-0 flex-1 truncate">{folder.name}</span>
          )}

          {count !== undefined && !editingId && (
            <span className="text-muted-foreground text-xs tabular-nums">{count}</span>
          )}

          <button
            type="button"
            className="hover:bg-muted rounded p-0.5 opacity-0 transition-all group-hover:opacity-100"
            onClick={(e) => {
              e.stopPropagation()
              setContextMenu({ id: folder.id, x: e.clientX, y: e.clientY })
            }}
          >
            <MoreHorizontal className="text-muted-foreground h-3.5 w-3.5" />
          </button>
        </div>

        {isExpanded && (
          <div>
            {folder.children.map((child) => renderFolder(child, depth + 1))}
            {creatingIn === folder.id && (
              <div
                className="flex items-center gap-1 px-2 py-1"
                style={{ paddingLeft: `${24 + (depth + 1) * 16}px` }}
              >
                <FolderIcon className="text-muted-foreground h-4 w-4 shrink-0" />
                <input
                  ref={newFolderInputRef}
                  type="text"
                  value={newFolderName}
                  onChange={(e) => setNewFolderName(e.target.value)}
                  onBlur={() => handleCreate(folder.id)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') handleCreate(folder.id)
                    if (e.key === 'Escape') {
                      setCreatingIn(false)
                      setNewFolderName('')
                    }
                  }}
                  placeholder="Folder name..."
                  className="border-primary/50 focus:ring-ring min-w-0 flex-1 rounded border px-1 py-0 text-sm focus:ring-1 focus:outline-none"
                />
              </div>
            )}
          </div>
        )}
      </div>
    )
  }

  if (loading) {
    return (
      <div className="flex items-center justify-center py-8">
        <Loader2 className="text-muted-foreground h-5 w-5 animate-spin" />
      </div>
    )
  }

  return (
    <div className="flex h-full flex-col">
      <div className="space-y-0.5 px-1 py-2">
        <button
          type="button"
          className={`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors ${
            isSelected({ type: 'smart', smart: 'all' })
              ? 'bg-primary/10 text-primary font-medium'
              : 'text-foreground hover:bg-muted'
          }`}
          onClick={() => onSelect({ type: 'smart', smart: 'all' })}
          onDragOver={(e) => handleDragOver(e, null)}
          onDragLeave={handleDragLeave}
          onDrop={(e) => handleDrop(e, null)}
        >
          <LayoutGrid className="h-4 w-4 shrink-0" />
          <span className="flex-1 text-left">All</span>
          {totalCount !== undefined && (
            <span className="text-muted-foreground text-xs tabular-nums">{totalCount}</span>
          )}
        </button>

        <button
          type="button"
          className={`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors ${
            isSelected({ type: 'smart', smart: 'recent' })
              ? 'bg-primary/10 text-primary font-medium'
              : 'text-foreground hover:bg-muted'
          }`}
          onClick={() => onSelect({ type: 'smart', smart: 'recent' })}
        >
          <Clock className="h-4 w-4 shrink-0" />
          <span className="flex-1 text-left">Recent</span>
          {recentCount !== undefined && (
            <span className="text-muted-foreground text-xs tabular-nums">{recentCount}</span>
          )}
        </button>

        <button
          type="button"
          className={`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors ${
            isSelected({ type: 'smart', smart: 'uncategorized' })
              ? 'bg-primary/10 text-primary font-medium'
              : 'text-foreground hover:bg-muted'
          }`}
          onClick={() => onSelect({ type: 'smart', smart: 'uncategorized' })}
        >
          <Inbox className="h-4 w-4 shrink-0" />
          <span className="flex-1 text-left">Uncategorized</span>
          {uncategorizedCount !== undefined && (
            <span className="text-muted-foreground text-xs tabular-nums">{uncategorizedCount}</span>
          )}
        </button>
      </div>

      <div className="border-border my-1 border-t" />

      <div className="flex-1 space-y-0.5 overflow-y-auto px-1 py-1">
        {folders.map((folder) => renderFolder(folder, 0))}

        {creatingIn === null && (
          <div className="flex items-center gap-1 px-2 py-1">
            <FolderIcon className="text-muted-foreground ml-5 h-4 w-4 shrink-0" />
            <input
              ref={newFolderInputRef}
              type="text"
              value={newFolderName}
              onChange={(e) => setNewFolderName(e.target.value)}
              onBlur={() => handleCreate(null)}
              onKeyDown={(e) => {
                if (e.key === 'Enter') handleCreate(null)
                if (e.key === 'Escape') {
                  setCreatingIn(false)
                  setNewFolderName('')
                }
              }}
              placeholder="Folder name..."
              className="border-primary/50 focus:ring-ring min-w-0 flex-1 rounded border px-1 py-0 text-sm focus:ring-1 focus:outline-none"
            />
          </div>
        )}
      </div>

      <div className="border-border border-t p-2">
        <button
          type="button"
          onClick={() => {
            setCreatingIn(null)
            setNewFolderName('')
          }}
          className="text-muted-foreground hover:bg-muted flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors"
        >
          <Plus className="h-4 w-4" />
          New Folder
        </button>
      </div>

      {contextMenu && (
        <div
          className="border-border bg-card fixed z-50 min-w-[160px] rounded-lg border py-1 shadow-lg"
          style={{ left: contextMenu.x, top: contextMenu.y }}
        >
          <button
            type="button"
            className="text-foreground hover:bg-muted flex w-full items-center gap-2 px-3 py-1.5 text-sm transition-colors"
            onClick={() => {
              const folder = findFolder(folders, contextMenu.id)
              if (folder) {
                setEditingId(folder.id)
                setEditName(folder.name)
              }
              setContextMenu(null)
            }}
          >
            <Pencil className="h-3.5 w-3.5" />
            Rename
          </button>
          <button
            type="button"
            className="text-foreground hover:bg-muted flex w-full items-center gap-2 px-3 py-1.5 text-sm transition-colors"
            onClick={() => {
              setCreatingIn(contextMenu.id)
              setNewFolderName('')
              setExpanded((prev) => new Set(prev).add(contextMenu.id))
              setContextMenu(null)
            }}
          >
            <FolderPlus className="h-3.5 w-3.5" />
            New Subfolder
          </button>
          <div className="border-border my-1 border-t" />
          <button
            type="button"
            className="text-destructive hover:bg-destructive/10 flex w-full items-center gap-2 px-3 py-1.5 text-sm transition-colors"
            onClick={() => {
              handleDelete(contextMenu.id)
              setContextMenu(null)
            }}
          >
            <Trash2 className="h-3.5 w-3.5" />
            Delete
          </button>
        </div>
      )}
    </div>
  )
}

function findFolder(nodes: FolderNode[], id: string): FolderNode | null {
  for (const n of nodes) {
    if (n.id === id) return n
    const found = findFolder(n.children, id)
    if (found) return found
  }
  return null
}
