import { useState, useRef, useEffect, useCallback, type DragEvent } from 'react'
import type { CalcDocument, CalcFolder } from '../hooks/useDocumentStore.ts'
import { TEMPLATES } from '../data/templates.ts'
import '../styles/sidebar.css'

interface SidebarProps {
  visible: boolean
  width: number
  documents: CalcDocument[]
  folders: CalcFolder[]
  activeTabId: string
  openTabIds: string[]
  onFileClick: (id: string) => void
  onNewDocument: (title?: string, content?: string) => void
  onNewFolder: () => void
  onRenameDocument: (id: string, title: string) => void
  onDeleteDocument: (id: string) => void
  onToggleFavorite: (id: string) => void
  onMoveToFolder: (docId: string, folderId: string | null) => void
  onRenameFolder: (id: string, name: string) => void
  onDeleteFolder: (id: string) => void
  onWidthChange: (width: number) => void
}

export function Sidebar({
  visible,
  width,
  documents,
  folders,
  activeTabId,
  openTabIds,
  onFileClick,
  onNewDocument,
  onNewFolder,
  onRenameDocument,
  onDeleteDocument,
  onToggleFavorite,
  onMoveToFolder,
  onRenameFolder,
  onDeleteFolder,
  onWidthChange,
}: SidebarProps) {
  const [search, setSearch] = useState('')
  const [expandedSections, setExpandedSections] = useState<Set<string>>(
    () => new Set(['files', 'recent'])
  )
  const [expandedFolders, setExpandedFolders] = useState<Set<string>>(() => new Set())
  const [editingId, setEditingId] = useState<string | null>(null)
  const [editValue, setEditValue] = useState('')
  const [editType, setEditType] = useState<'file' | 'folder'>('file')
  const [contextMenu, setContextMenu] = useState<{
    x: number; y: number; type: 'file' | 'folder'; id: string
  } | null>(null)
  const inputRef = useRef<HTMLInputElement>(null)
  const resizeRef = useRef<{ startX: number; startWidth: number } | null>(null)

  // Focus rename input
  useEffect(() => {
    if (editingId && inputRef.current) {
      inputRef.current.focus()
      inputRef.current.select()
    }
  }, [editingId])

  // Close context menu on click outside
  useEffect(() => {
    if (!contextMenu) return
    const handler = () => setContextMenu(null)
    document.addEventListener('click', handler)
    return () => document.removeEventListener('click', handler)
  }, [contextMenu])

  // Resize handle
  useEffect(() => {
    function onMouseMove(e: MouseEvent) {
      if (!resizeRef.current) return
      const newWidth = Math.min(400, Math.max(180, resizeRef.current.startWidth + e.clientX - resizeRef.current.startX))
      onWidthChange(newWidth)
    }
    function onMouseUp() {
      if (!resizeRef.current) return
      resizeRef.current = null
      document.body.style.cursor = ''
      document.body.style.userSelect = ''
    }
    document.addEventListener('mousemove', onMouseMove)
    document.addEventListener('mouseup', onMouseUp)
    return () => {
      document.removeEventListener('mousemove', onMouseMove)
      document.removeEventListener('mouseup', onMouseUp)
    }
  }, [onWidthChange])

  const toggleSection = useCallback((section: string) => {
    setExpandedSections(prev => {
      const next = new Set(prev)
      if (next.has(section)) next.delete(section)
      else next.add(section)
      return next
    })
  }, [])

  const toggleFolder = useCallback((folderId: string) => {
    setExpandedFolders(prev => {
      const next = new Set(prev)
      if (next.has(folderId)) next.delete(folderId)
      else next.add(folderId)
      return next
    })
  }, [])

  // Rename — use refs to avoid stale closures in blur/keydown handlers
  const editRef = useRef<{ id: string; value: string; type: 'file' | 'folder' } | null>(null)

  const startRename = useCallback((id: string, currentName: string, type: 'file' | 'folder') => {
    editRef.current = { id, value: currentName, type }
    setEditingId(id)
    setEditValue(currentName)
    setEditType(type)
    setContextMenu(null)
  }, [])

  const commitRename = useCallback(() => {
    const edit = editRef.current
    if (!edit) return
    if (edit.type === 'file') onRenameDocument(edit.id, edit.value)
    else onRenameFolder(edit.id, edit.value)
    editRef.current = null
    setEditingId(null)
  }, [onRenameDocument, onRenameFolder])

  // Keep ref in sync when editValue changes
  const handleEditChange = useCallback((val: string) => {
    setEditValue(val)
    if (editRef.current) editRef.current.value = val
  }, [])

  // Derived data
  const recentDocs = [...documents]
    .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
    .slice(0, 5)

  const favoriteDocs = documents.filter(d => d.isFavorite)

  const rootDocs = documents.filter(d => !d.folderId)
    .sort((a, b) => a.title.localeCompare(b.title))

  const rootFolders = folders.filter(f => !f.parentId)
    .sort((a, b) => a.name.localeCompare(b.name))

  const getDocsInFolder = (folderId: string) =>
    documents.filter(d => d.folderId === folderId).sort((a, b) => a.title.localeCompare(b.title))

  // Drag and drop — use ref to avoid stale closure
  const [dragId, setDragId] = useState<string | null>(null)
  const dragIdRef = useRef<string | null>(null)
  const [dropTarget, setDropTarget] = useState<string | null>(null)

  const handleDragStart = useCallback((e: DragEvent, docId: string) => {
    dragIdRef.current = docId
    setDragId(docId)
    e.dataTransfer.effectAllowed = 'move'
    e.dataTransfer.setData('text/plain', docId)
  }, [])

  const handleDragOver = useCallback((e: DragEvent, targetId: string) => {
    e.preventDefault()
    e.dataTransfer.dropEffect = 'move'
    setDropTarget(targetId)
  }, [])

  const handleDragLeave = useCallback(() => {
    setDropTarget(null)
  }, [])

  const handleDrop = useCallback((e: DragEvent, folderId: string | null) => {
    e.preventDefault()
    e.stopPropagation()
    const docId = dragIdRef.current ?? e.dataTransfer.getData('text/plain')
    if (docId) {
      onMoveToFolder(docId, folderId)
      if (folderId) {
        setExpandedFolders(prev => {
          const next = new Set(prev)
          next.add(folderId)
          return next
        })
      }
    }
    dragIdRef.current = null
    setDragId(null)
    setDropTarget(null)
  }, [onMoveToFolder])

  const handleDragEnd = useCallback(() => {
    dragIdRef.current = null
    setDragId(null)
    setDropTarget(null)
  }, [])

  // Search filter
  const searchResults = search.trim()
    ? documents.filter(d => d.title.toLowerCase().includes(search.toLowerCase()))
        .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
    : null

  if (!visible) return null

  const renderFileItem = (doc: CalcDocument, depth = 0) => {
    const isActive = doc.id === activeTabId
    const isOpen = openTabIds.includes(doc.id)
    const isDragged = dragId === doc.id

    return (
      <div
        key={doc.id}
        className={`sidebar-file ${isActive ? 'active' : ''} ${isOpen ? 'open' : ''} ${isDragged ? 'dragging' : ''}`}
        style={{ paddingLeft: 12 + depth * 16 }}
        draggable
        onDragStart={e => handleDragStart(e, doc.id)}
        onDragEnd={handleDragEnd}
        onClick={() => onFileClick(doc.id)}
        onContextMenu={e => {
          e.preventDefault()
          setContextMenu({ x: e.clientX, y: e.clientY, type: 'file', id: doc.id })
        }}
      >
        <span className="sidebar-file-icon">📄</span>
        {editingId === doc.id ? (
          <input
            ref={inputRef}
            className="sidebar-rename-input"
            value={editValue}
            onChange={e => handleEditChange(e.target.value)}
            onBlur={commitRename}
            onKeyDown={e => {
              if (e.key === 'Enter') commitRename()
              if (e.key === 'Escape') setEditingId(null)
            }}
            onClick={e => e.stopPropagation()}
          />
        ) : (
          <span className="sidebar-file-label">{doc.title}</span>
        )}
        {isOpen && !isActive && <span className="sidebar-open-dot" />}
      </div>
    )
  }

  const renderFolderItem = (folder: CalcFolder, depth = 0) => {
    const isExpanded = expandedFolders.has(folder.id)
    const docsInFolder = getDocsInFolder(folder.id)
    const subFolders = folders.filter(f => f.parentId === folder.id)
    const isDropTarget = dropTarget === folder.id

    return (
      <div key={folder.id}>
        <div
          className={`sidebar-folder ${isDropTarget ? 'drop-target' : ''}`}
          style={{ paddingLeft: 12 + depth * 16 }}
          onClick={() => { if (!editingId) toggleFolder(folder.id) }}
          onDragOver={e => handleDragOver(e, folder.id)}
          onDragLeave={handleDragLeave}
          onDrop={e => handleDrop(e, folder.id)}
          onContextMenu={e => {
            e.preventDefault()
            setContextMenu({ x: e.clientX, y: e.clientY, type: 'folder', id: folder.id })
          }}
        >
          <span className="sidebar-folder-chevron">{isExpanded ? '▾' : '▸'}</span>
          {editingId === folder.id ? (
            <input
              ref={inputRef}
              className="sidebar-rename-input"
              value={editValue}
              onChange={e => handleEditChange(e.target.value)}
              onBlur={commitRename}
              onKeyDown={e => {
                if (e.key === 'Enter') commitRename()
                if (e.key === 'Escape') setEditingId(null)
              }}
              onClick={e => e.stopPropagation()}
            />
          ) : (
            <>
              <span className="sidebar-folder-icon">{isExpanded ? '📂' : '📁'}</span>
              <span className="sidebar-folder-label">{folder.name}</span>
              <span className="sidebar-folder-count">({docsInFolder.length})</span>
            </>
          )}
        </div>
        {isExpanded && (
          <>
            {subFolders.map(sf => renderFolderItem(sf, depth + 1))}
            {docsInFolder.map(d => renderFileItem(d, depth + 1))}
            {docsInFolder.length === 0 && subFolders.length === 0 && (
              <div className="sidebar-empty" style={{ paddingLeft: 28 + depth * 16 }}>
                Empty folder
              </div>
            )}
          </>
        )}
      </div>
    )
  }

  return (
    <>
      <div className="sidebar" style={{ width }}>
        {/* Search */}
        <div className="sidebar-search">
          <span className="sidebar-search-icon">🔍</span>
          <input
            type="text"
            placeholder="Search documents..."
            value={search}
            onChange={e => setSearch(e.target.value)}
            className="sidebar-search-input"
          />
          {search && (
            <button className="sidebar-search-clear" onClick={() => setSearch('')}>×</button>
          )}
        </div>

        <div className="sidebar-content">
          {searchResults ? (
            /* Search results */
            <div className="sidebar-section">
              <div className="sidebar-section-header">
                Results ({searchResults.length})
              </div>
              {searchResults.map(d => renderFileItem(d))}
              {searchResults.length === 0 && (
                <div className="sidebar-empty">No documents match &apos;{search}&apos;</div>
              )}
            </div>
          ) : (
            <>
              {/* Recent */}
              <div className="sidebar-section">
                <div
                  className="sidebar-section-header"
                  onClick={() => toggleSection('recent')}
                >
                  <span className="sidebar-section-chevron">
                    {expandedSections.has('recent') ? '▾' : '▸'}
                  </span>
                  🕐 Recent
                </div>
                {expandedSections.has('recent') && (
                  recentDocs.length > 0
                    ? recentDocs.map(d => renderFileItem(d))
                    : <div className="sidebar-empty">No recent documents</div>
                )}
              </div>

              {/* Favorites */}
              {favoriteDocs.length > 0 && (
                <div className="sidebar-section">
                  <div
                    className="sidebar-section-header"
                    onClick={() => toggleSection('favorites')}
                  >
                    <span className="sidebar-section-chevron">
                      {expandedSections.has('favorites') ? '▾' : '▸'}
                    </span>
                    ⭐ Favorites
                  </div>
                  {expandedSections.has('favorites') && favoriteDocs.map(d => renderFileItem(d))}
                </div>
              )}

              {/* Templates */}
              <div className="sidebar-section">
                <div
                  className="sidebar-section-header"
                  onClick={() => toggleSection('templates')}
                >
                  <span className="sidebar-section-chevron">
                    {expandedSections.has('templates') ? '▾' : '▸'}
                  </span>
                  📋 Templates
                </div>
                {expandedSections.has('templates') && (
                  <div className="sidebar-templates">
                    {TEMPLATES.map(t => (
                      <div
                        key={t.id}
                        className="sidebar-template"
                        onClick={() => onNewDocument(t.name, t.content)}
                        title={t.description}
                      >
                        <span className="sidebar-template-dot" style={{ backgroundColor: t.color }} />
                        <div className="sidebar-template-text">
                          <span className="sidebar-template-name">{t.name}</span>
                          <span className="sidebar-template-desc">{t.description}</span>
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </div>

              {/* Files */}
              <div className="sidebar-section">
                <div
                  className={`sidebar-section-header ${dropTarget === 'root' ? 'drop-target' : ''}`}
                  onClick={() => toggleSection('files')}
                  onDragOver={e => handleDragOver(e, 'root')}
                  onDragLeave={handleDragLeave}
                  onDrop={e => handleDrop(e, null)}
                >
                  <span className="sidebar-section-chevron">
                    {expandedSections.has('files') ? '▾' : '▸'}
                  </span>
                  📁 Files
                </div>
                {expandedSections.has('files') && (
                  <div
                    className={`sidebar-files-area ${dropTarget === 'root' ? 'drop-target-area' : ''}`}
                    onDragOver={e => { e.preventDefault(); e.dataTransfer.dropEffect = 'move' }}
                    onDrop={e => handleDrop(e, null)}
                  >
                    {rootFolders.map(f => renderFolderItem(f))}
                    {rootDocs.map(d => renderFileItem(d))}
                  </div>
                )}
              </div>
            </>
          )}
        </div>

        {/* Footer */}
        <div className="sidebar-footer">
          <button className="sidebar-footer-btn" onClick={() => onNewDocument()}>+ Document</button>
          <button className="sidebar-footer-btn" onClick={onNewFolder}>+ Folder</button>
        </div>

        {/* Resize handle */}
        <div
          className="sidebar-resize"
          onMouseDown={e => {
            e.preventDefault()
            resizeRef.current = { startX: e.clientX, startWidth: width }
            document.body.style.cursor = 'col-resize'
            document.body.style.userSelect = 'none'
          }}
          onDoubleClick={() => onWidthChange(240)}
        />
      </div>

      {/* Context Menu */}
      {contextMenu && (
        <div
          className="sidebar-context-menu"
          style={{ left: contextMenu.x, top: contextMenu.y }}
        >
          {contextMenu.type === 'file' && (
            <>
              <button onClick={() => { onFileClick(contextMenu.id); setContextMenu(null) }}>
                Open
              </button>
              <button onClick={() => {
                const doc = documents.find(d => d.id === contextMenu.id)
                if (doc) startRename(doc.id, doc.title, 'file')
              }}>
                Rename
              </button>
              <button onClick={() => {
                onToggleFavorite(contextMenu.id)
                setContextMenu(null)
              }}>
                {documents.find(d => d.id === contextMenu.id)?.isFavorite ? 'Remove from Favorites' : 'Add to Favorites'}
              </button>
              {folders.length > 0 && (
                <>
                  <div className="sidebar-context-separator" />
                  <div className="sidebar-context-label">Move to...</div>
                  <button onClick={() => { onMoveToFolder(contextMenu.id, null); setContextMenu(null) }}>
                    Root
                  </button>
                  {folders.map(f => (
                    <button key={f.id} onClick={() => { onMoveToFolder(contextMenu.id, f.id); setContextMenu(null) }}>
                      📁 {f.name}
                    </button>
                  ))}
                </>
              )}
              <div className="sidebar-context-separator" />
              <button className="sidebar-context-danger" onClick={() => {
                onDeleteDocument(contextMenu.id)
                setContextMenu(null)
              }}>
                Delete
              </button>
            </>
          )}
          {contextMenu.type === 'folder' && (
            <>
              <button onClick={() => {
                const folder = folders.find(f => f.id === contextMenu.id)
                if (folder) startRename(folder.id, folder.name, 'folder')
              }}>
                Rename
              </button>
              <div className="sidebar-context-separator" />
              <button className="sidebar-context-danger" onClick={() => {
                onDeleteFolder(contextMenu.id)
                setContextMenu(null)
              }}>
                Delete Folder
              </button>
            </>
          )}
        </div>
      )}
    </>
  )
}
