import React, { useCallback, useMemo, useEffect, useRef } from 'react'
import { useTabStore } from '../../stores/tabStore'
import { useSidebarStore } from '../../stores/sidebarStore'
import { getFileName } from '../../lib/fileUtils'
import { recentFilesRepository } from '../../db/recentFilesRepository'
import { FolderPlus, File } from '../Icons'
import { FileTree } from '../FileTree'
import { useSidebarResize } from '../../hooks/useSidebarResize'
import { useFolderOperations } from '../../hooks/useFolderOperations'
import { useAutoExpandDir } from '../../hooks/useAutoExpandDir'
import { useActiveHeading } from '../../hooks/useActiveHeading'
import { OutlinePanel, parseHeadings } from '../OutlinePanel'
import type { Heading } from '../OutlinePanel'
import { getEditorView, useEditorStore } from '../../stores/editorStore'
import { TextSelection } from '@milkdown/prose/state'

const norm = (p: string) => p.replace(/[/\\]+$/, '').replace(/\\/g, '/')

export const Sidebar = React.memo(function Sidebar() {
  const tabs = useTabStore(s => s.tabs)
  const activeTabId = useTabStore(s => s.activeTabId)
  // B-03: 用 activeTabId + tabs 推导 activeTab 而非 s.getActiveTab()，
  // 后者每次返回新对象引用导致 Zustand 无条件重渲染
  const activeTab = useMemo(() => tabs.find(t => t.id === activeTabId) ?? null, [tabs, activeTabId])
  const switchToTab = useTabStore(s => s.switchToTab)
  const createTab = useTabStore(s => s.createTab)
  const rootPath = useSidebarStore(s => s.rootPath)
  const tree = useSidebarStore(s => s.tree)
  const expandedDirs = useSidebarStore(s => s.expandedDirs)
  const toggleDir = useSidebarStore(s => s.toggleDir)
  const isVisible = useSidebarStore(s => s.isVisible)

  const activeFilePath = activeTab?.filePath ?? null
  const { sidebarRef, startResize } = useSidebarResize()
  const { handleOpenFolder } = useFolderOperations()
  const setLoading = useEditorStore(s => s.setLoading)
  const viewMode = useEditorStore(s => s.viewMode)
  useAutoExpandDir(activeFilePath)

  // Parse headings from active tab content
  const headings = useMemo(() => {
    if (!activeTab?.content) return []
    return parseHeadings(activeTab.content)
  }, [activeTab?.content])

  // D4: 追踪预览面板中的活跃标题
  const previewRef = useRef<HTMLElement | null>(null)
  useEffect(() => {
    // 仅在预览模式时获取 preview DOM 节点
    if (viewMode === 'preview') {
      previewRef.current = document.getElementById('preview')
    } else {
      previewRef.current = null
    }
  }, [viewMode])

  const activeHeadingIndex = useActiveHeading(
    viewMode === 'preview' ? previewRef : { current: null },
    headings
  )

  // Navigate to heading in ProseMirror document tree
  const handleHeadingNavigate = useCallback((heading: Heading, index: number) => {
    const view = getEditorView()
    if (!view) return
    try {
      let foundPos: number | null = null
      let currentIndex = 0

      view.state.doc.descendants((node, pos) => {
        if (foundPos !== null) return false
        if (node.type.name === 'heading' && node.attrs.level === heading.level) {
          if (node.textContent.trim() === heading.text) {
            if (currentIndex === index) {
              foundPos = pos
              return false
            }
            currentIndex++
          }
        }
        return true
      })

      if (foundPos === null) return

      const tr = view.state.tr
        .setSelection(TextSelection.create(view.state.doc, foundPos, foundPos))
        .scrollIntoView()
      view.dispatch(tr)
      view.focus()
    } catch {
      // Position may be invalid if content has changed
    }
  }, [])

  const handleFileClick = useCallback(async (path: string) => {
    const existing = tabs.find(t => t.filePath === path)
    if (existing) { switchToTab(existing.id); return }
    if (!window.electronAPI) return
    setLoading('file-open', true)
    try {
      const result = await window.electronAPI.readFile(path)
      if (result.success && result.content !== undefined) {
        createTab(path, result.content)
        recentFilesRepository.add(path)
      }
    } finally {
      setLoading('file-open', false)
    }
  }, [tabs, switchToTab, createTab, setLoading])

  const independentFiles = tabs.filter(t => {
    if (!t.filePath) return false
    if (!rootPath) return true
    return !norm(t.filePath).startsWith(norm(rootPath))
  })

  if (!isVisible) return null

  return (
    <aside id="sidebar" ref={sidebarRef} aria-label="文件资源管理器">
      <div id="sidebar-header">
        <span id="sidebar-title">资源管理器</span>
        <button
          className="sidebar-header-btn"
          onClick={handleOpenFolder}
          title="打开文件夹"
          aria-label="打开文件夹"
        >
          <FolderPlus size={14} />
        </button>
      </div>
      <nav id="sidebar-tree" role="tree" aria-label="文件树">
        {independentFiles.length > 0 && (
          <div className="independent-files-section" role="group" aria-label="已打开的文件">
            <div className="independent-files-header" id="independent-files-label">已打开的文件</div>
            {independentFiles.map(tab => (
              <div key={tab.id}
                className={`tree-item independent-file-item ${tab.id === activeTabId ? 'active' : ''}`}
                style={{ paddingLeft: '8px' }}
                role="treeitem"
                tabIndex={0}
                aria-selected={tab.id === activeTabId}
                aria-label={getFileName(tab.filePath!)}
                onClick={() => switchToTab(tab.id)}
                onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); switchToTab(tab.id) } }}
              >
                <span className="tree-icon"><File size={14} /></span>
                <span className="tree-name">{getFileName(tab.filePath!)}</span>
                {tab.isModified && <span className="independent-modified-dot" aria-label="已修改"> •</span>}
              </div>
            ))}
          </div>
        )}
        {rootPath && (
          <>
            <div className="sidebar-section-header" id="folder-tree-label">文件夹目录树</div>
            <FileTree
              nodes={[{ name: rootPath.split(/[/\\]/).pop() || rootPath, path: rootPath, type: 'dir' as const, children: tree }]}
              depth={0} expandedDirs={expandedDirs} toggleDir={toggleDir}
              activeFilePath={activeFilePath} onFileClick={handleFileClick}
            />
          </>
        )}
      </nav>
      <div className="sidebar-outline-section">
        <OutlinePanel
          headings={headings}
          onNavigate={handleHeadingNavigate}
          activeHeadingIndex={activeHeadingIndex}
        />
      </div>
      <div
        className="sidebar-resize-handle"
        onMouseDown={startResize}
        role="separator"
        aria-orientation="vertical"
        aria-label="调整侧边栏宽度"
        tabIndex={0}
      />
    </aside>
  )
})

Sidebar.displayName = 'Sidebar'
