import { useState, useEffect, useRef, useMemo } from 'react'
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'
import { Layout, Menu, Spin, Button, Tooltip, message, Modal, Input, Space, Dropdown, Empty, Switch } from 'antd'
import { ShareAltOutlined, FileTextOutlined, FolderOutlined, FolderOpenOutlined, FilePdfOutlined, CopyOutlined, CloudDownloadOutlined, CloudUploadOutlined, ArrowLeftOutlined, ReloadOutlined, VerticalAlignTopOutlined } from '@ant-design/icons'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import rehypeRaw from 'rehype-raw'
import rehypeSlug from 'rehype-slug'
import rehypeHighlight from 'rehype-highlight'
import 'highlight.js/styles/github.css'
import Highlighter from 'react-highlight-words'
import GithubSlugger from 'github-slugger'
import { getProjectTree, getFileContent, getDocumentUrl, getExportPdfUrl } from '@/api/file'
import { gitPull, gitPush, getGitRepos } from '@/api/project'
import { getFileShareInfo, createOrUpdateFileShare, deleteFileShare } from '@/api/share'
import { searchDocuments } from '@/api/search'
import VirtualPDFViewer from '@/components/PDFViewer/VirtualPDFViewer'
import FloatingToc from '@/components/FloatingToc/FloatingToc'
import Toast from '@/components/Toast/Toast'
import ModeSwitch from '@/components/ModeSwitch/ModeSwitch'
import LargeMarkdownViewer, { isLargeMarkdownContent } from '@/components/LargeMarkdownViewer/LargeMarkdownViewer'
import './DocumentPage.css'

const { Sider, Content } = Layout
const MAX_TOC_ITEMS = 500

// 高亮渲染组件
const HighlightText = ({ text, keyword }) => {
  if (!keyword || !text) return text;
  return (
    <Highlighter
      highlightClassName="search-highlight"
      searchWords={[keyword]}
      autoEscape={true}
      textToHighlight={text}
    />
  )
}

function DocumentPage() {
  const { projectId } = useParams()
  const navigate = useNavigate()
  const [searchParams, setSearchParams] = useSearchParams()
  const [fileTree, setFileTree] = useState([])
  const [selectedFile, setSelectedFile] = useState('')
  const [selectedNodeKey, setSelectedNodeKey] = useState('')
  const [markdownContent, setMarkdownContent] = useState('')
  const [loading, setLoading] = useState(false)
  const [openKeys, setOpenKeys] = useState([])
  const [tocItems, setTocItems] = useState([])
  const [shareModalVisible, setShareModalVisible] = useState(false)
  const [shareInfo, setShareInfo] = useState(null)
  const [hasPassword, setHasPassword] = useState(false)
  const [password, setPassword] = useState('')
  const [userRole, setUserRole] = useState('viewer')
  const [pdfUrl, setPdfUrl] = useState('')
  const [pdfFilename, setPdfFilename] = useState('')
  const [viewMode, setViewMode] = useState('markdown')
  const [gitRepos, setGitRepos] = useState([])
  const [projectName, setProjectName] = useState('')
  const [refreshing, setRefreshing] = useState(false)
  
  // 搜索相关状态
  const [searchKeyword, setSearchKeyword] = useState('')
  const [matchedFilePaths, setMatchedFilePaths] = useState(new Set())
  const [isSearching, setIsSearching] = useState(false)
  const [modeSwitchValue, setModeSwitchValue] = useState('view')
  
  const contentRef = useRef(null)
  const largeMarkdownRef = useRef(null)
  const modeSwitchingRef = useRef(false)
  const [pdfToolbarTarget, setPdfToolbarTarget] = useState(null)
  const isLargeMarkdown = isLargeMarkdownContent(markdownContent)

  const getHeaderDisplay = (filePath) => {
    const resolvedPath = selectedNodeKey || filePath || 'README.md'
    const fileName = resolvedPath.split('/').filter(Boolean).pop() || 'README.md'
    const selectedNode = selectedNodeKey ? findNodeByKey(fileTree, selectedNodeKey) : null
    const isFolder = Boolean(selectedNode && !selectedNode.isLeaf)
    const isPdf = fileName.toLowerCase().endsWith('.pdf')
    const FileIcon = isFolder ? FolderOutlined : isPdf ? FilePdfOutlined : FileTextOutlined

    return {
      fileName,
      FileIcon,
      isPdf,
    }
  }

  const navigateWithTransition = (to) => {
    if (document.startViewTransition) {
      document.startViewTransition(() => navigate(to))
      return
    }
    navigate(to)
  }

  const updateSelectedParam = (path, isFile = true) => {
    const nextParams = new URLSearchParams(searchParams)
    nextParams.delete('file')
    nextParams.delete('selected')

    if (path) {
      nextParams.set(isFile ? 'file' : 'selected', path)
    }
    setSearchParams(nextParams, { replace: true })
  }

  const updateFileParam = (filePath) => {
    updateSelectedParam(filePath, true)
  }

  const expandParentFolders = (path) => {
    const parts = path.split('/')
    const allParentPaths = []
    let currentPath = ''

    for (let i = 0; i < parts.length - 1; i++) {
      currentPath = currentPath ? `${currentPath}/${parts[i]}` : parts[i]
      allParentPaths.push(currentPath)
    }

    if (allParentPaths.length > 0) {
      setOpenKeys(prev => [...new Set([...prev, ...allParentPaths])])
    }
  }

  const selectFolder = (folderPath, { syncUrl = false } = {}) => {
    setSelectedFile('')
    setSelectedNodeKey(folderPath)
    setMarkdownContent('')
    setTocItems([])
    setViewMode('folder')
    expandParentFolders(`${folderPath}/placeholder`)

    if (syncUrl) {
      updateSelectedParam(folderPath, false)
    }
  }

  const openDocumentPath = (filePath, { syncUrl = false } = {}) => {
    setSelectedFile(filePath)
    setSelectedNodeKey(filePath)
    expandParentFolders(filePath)

    if (syncUrl) {
      updateFileParam(filePath)
    }

    if (filePath.toLowerCase().endsWith('.pdf')) {
      setPdfUrl(buildDocumentUrl(filePath))
      setPdfFilename(filePath.split('/').pop())
      setViewMode('pdf')
    } else {
      setViewMode('markdown')
      loadMarkdown(filePath)
    }
  }

  const buildDocumentUrl = (filePath, refreshKey = null) => {
    const params = new URLSearchParams()
    const token = localStorage.getItem('access_token')

    if (token) {
      params.set('token', token)
    }
    if (refreshKey) {
      params.set('refresh', String(refreshKey))
    }

    const query = params.toString()
    return `${getDocumentUrl(projectId, filePath)}${query ? `?${query}` : ''}`
  }

  useEffect(() => {
    loadFileTree()
  }, [projectId])

  const handleClose = () => {
    Modal.confirm({
      title: '确认退出',
      content: '确定要退出当前项目页面吗？',
      okText: '退出',
      cancelText: '取消',
      onOk: () => {
        if (userRole === 'owner') {
          navigate('/projects/my')
        } else {
          navigate('/projects/share')
        }
      },
    })
  }

  // 监听 URL 参数变化，处理文件导航和搜索
  useEffect(() => {
    // 只有当文件树加载完成后才处理导航，否则无法正确展开目录
    if (fileTree.length === 0) return

    const fileParam = searchParams.get('file')
    const selectedParam = searchParams.get('selected')
    const keywordParam = searchParams.get('keyword')
    
    // 处理搜索
    if (keywordParam && keywordParam !== searchKeyword) {
      handleSearch(keywordParam)
    }

    // 处理文件加载
    if (selectedParam) {
      const targetNode = findNodeByKey(fileTree, selectedParam)
      if (targetNode && !targetNode.isLeaf && selectedParam !== selectedNodeKey) {
        selectFolder(selectedParam)
      }
    } else if (fileParam) {
      const targetNode = findNodeByKey(fileTree, fileParam)
      if (targetNode && !targetNode.isLeaf) {
        selectFolder(fileParam, { syncUrl: true })
      } else if (fileParam !== selectedFile) {
        openDocumentPath(fileParam)
      }
    } else {
      // 如果没有指定文件，且当前没有选中文件，默认打开 README.md
      if (!selectedFile && !selectedNodeKey) {
        const readmeNode = findReadme(fileTree)
        if (readmeNode) {
          openDocumentPath(readmeNode.key, { syncUrl: true })
        }
      }
    }
  }, [searchParams, fileTree])

  // 处理搜索
  const handleSearch = async (value) => {
    setSearchKeyword(value)
    if (!value.trim()) {
      setMatchedFilePaths(new Set())
      return
    }

    setIsSearching(true)
    try {
      const res = await searchDocuments(value, projectId)
      const paths = new Set(res.data.map(item => item.file_path))
      setMatchedFilePaths(paths)
      
      // 自动展开匹配的节点
      const keysToExpand = new Set(openKeys)
      res.data.forEach(item => {
        const parts = item.file_path.split('/')
        let currentPath = ''
        for (let i = 0; i < parts.length - 1; i++) {
          currentPath = currentPath ? `${currentPath}/${parts[i]}` : parts[i]
          keysToExpand.add(currentPath)
        }
      })
      setOpenKeys(Array.from(keysToExpand))
    } catch (error) {
      console.error('Search error:', error)
    } finally {
      setIsSearching(false)
    }
  }

  // 过滤文件树
  const filteredTreeData = useMemo(() => {
    if (!searchKeyword.trim()) return fileTree

    const loop = (data) => {
      const result = []
      for (const node of data) {
        const titleMatch = node.title.toLowerCase().includes(searchKeyword.toLowerCase())
        const contentMatch = matchedFilePaths.has(node.key)
        
        if (node.children) {
          const children = loop(node.children)
          if (children.length > 0 || titleMatch) {
            result.push({ ...node, children })
          }
        } else {
          if (titleMatch || contentMatch) {
            result.push(node)
          }
        }
      }
      return result
    }
    return loop(fileTree)
  }, [fileTree, searchKeyword, matchedFilePaths])

  const loadGitRepos = async () => {
    try {
      const res = await getGitRepos(projectId)
      setGitRepos(res.data || [])
    } catch (error) {
      console.error('Load git repos error:', error)
    }
  }

  // 加载文件树
  const loadFileTree = async ({ throwOnError = false } = {}) => {
    try {
      const res = await getProjectTree(projectId)
      const data = res.data || {}
      const tree = data.tree || data || []  // 兼容新旧格式
      const role = data.user_role || 'viewer'
      const name = data.project_name

      setFileTree(tree)
      setUserRole(role)
      setProjectName(name)
      return tree
    } catch (error) {
      console.error('Load file tree error:', error)
      if (throwOnError) {
        throw error
      }
      return []
    }
  }

  // 查找根目录的 README.md
  const findReadme = (nodes) => {
    // 只在根目录查找
    for (const node of nodes) {
      if (node.title === 'README.md' && node.isLeaf) {
        return node
      }
    }
    return null
  }

  const findNodeByKey = (nodes, key) => {
    for (const node of nodes) {
      if (node.key === key) {
        return node
      }
      if (node.children?.length) {
        const found = findNodeByKey(node.children, key)
        if (found) {
          return found
        }
      }
    }
    return null
  }

  // 转换文件树为菜单项
  const convertTreeToMenuItems = (nodes) => {
    return nodes.map((node) => {
      const titleText = node.title.endsWith('.md') ? node.title.replace('.md', '') : node.title
      const labelNode = (
        <Tooltip title={node.title} placement="right">
          <span className="docs-menu-label">
            <span className="docs-menu-label-text">{titleText}</span>
            {node.is_shared && <ShareAltOutlined className="docs-menu-share-icon" title="已分享" />}
          </span>
        </Tooltip>
      )

      if (!node.isLeaf) {
        const isOpen = openKeys.includes(node.key)
        // 目录
        return {
          key: node.key,
          label: labelNode,
          icon: isOpen ? <FolderOpenOutlined /> : <FolderOutlined />,
          onTitleClick: () => selectFolder(node.key, { syncUrl: true }),
          children: node.children ? convertTreeToMenuItems(node.children) : [],
        }
      } else if (node.title && node.title.endsWith('.md')) {
        // Markdown 文件
        return {
          key: node.key,
          label: labelNode,
          icon: <FileTextOutlined />,
        }
      } else if (node.title && node.title.endsWith('.pdf')) {
        // PDF 文件
        return {
          key: node.key,
          label: labelNode,
          icon: <FilePdfOutlined style={{ color: '#f5222d' }} />,
        }
      }
      return null
    }).filter(Boolean)
  }

  // 加载 markdown 文件
  const loadMarkdown = async (filePath) => {
    setLoading(true)
    setTocItems([]) // 清空旧的目录数据
    try {
      const res = await getFileContent(projectId, filePath)
      setMarkdownContent(res.data?.content || '')

      // 滚动到顶部
      if (contentRef.current) {
        contentRef.current.scrollTo({ top: 0, behavior: 'auto' })
      }
    } catch (error) {
      console.error('Load markdown error:', error)
      setMarkdownContent('# 文档加载失败\n\n无法加载该文档，请稍后重试。')
    } finally {
      setLoading(false)
    }
  }

  // 提取 markdown 标题生成目录
  useEffect(() => {
    if (markdownContent && !isLargeMarkdown) {
      let canceled = false
      const schedule = window.requestIdleCallback || ((cb) => window.setTimeout(cb, 1))
      const cancel = window.cancelIdleCallback || window.clearTimeout

      const taskId = schedule(() => {
        if (canceled) return

      const slugger = new GithubSlugger()
      const headings = []
      const lines = markdownContent.split('\n')

      for (const line of lines) {
        const match = line.match(/^(#{1,6})\s+(.+)$/)
        if (match) {
          const level = match[1].length
          const title = match[2]
          // 使用标准的 github-slugger 生成 ID，确保与 rehype-slug 一致
          const key = slugger.slug(title)

          headings.push({
            key: `#${key}`,
            href: `#${key}`,
            title,
            level,
          })

          if (headings.length >= MAX_TOC_ITEMS) {
            break
          }
        }
      }

      setTocItems(headings)
      })

      return () => {
        canceled = true
        cancel(taskId)
      }
    } else {
      setTocItems([])
    }
  }, [markdownContent, isLargeMarkdown])

  // 从知识库引用跳转而来时（URL 带 keyword），文档加载完成后滚动到第一个高亮处
  useEffect(() => {
    if (loading || !searchKeyword || !markdownContent) return
    if (viewMode !== 'markdown') return

    let canceled = false
    const timer = window.setTimeout(() => {
      if (canceled) return
      const container = contentRef.current
      const target = container?.querySelector('.search-highlight')
      if (target) {
        target.scrollIntoView({ behavior: 'smooth', block: 'center' })
        // 临时强调被引用的位置，短暂后淡出
        target.classList.add('cited-highlight-flash')
        window.setTimeout(() => target.classList.remove('cited-highlight-flash'), 2400)
      }
    }, 260)

    return () => {
      canceled = true
      window.clearTimeout(timer)
    }
  }, [loading, markdownContent, searchKeyword, viewMode])

  // 处理菜单点击
  const handleMenuClick = ({ key }) => {
    const node = findNodeByKey(fileTree, key)
    if (!node) return

    if (!node.isLeaf) {
      selectFolder(key, { syncUrl: true })
      return
    }

    openDocumentPath(key, { syncUrl: true })
  }

  const scrollContentToTop = () => {
    if (isLargeMarkdown) {
      largeMarkdownRef.current?.scrollToTop()
      return
    }

    if (contentRef.current) {
      contentRef.current.scrollTo({ top: 0, behavior: 'smooth' })
    }
  }

  const handleExportMarkdownPDF = () => {
    if (!selectedFile) return
    let url = getExportPdfUrl(projectId, selectedFile)
    const token = localStorage.getItem('access_token')
    if (token) {
      url += `&token=${encodeURIComponent(token)}`
    }
    window.open(url, '_blank')
  }

  // 解析相对路径
  const resolveRelativePath = (currentPath, relativePath) => {
    // 获取当前文件所在目录
    const currentDir = currentPath.substring(0, currentPath.lastIndexOf('/'))

    // 分割相对路径
    const parts = relativePath.split('/')
    const dirParts = currentDir ? currentDir.split('/') : []

    // 处理 ../ 和 ./
    for (const part of parts) {
      if (part === '..') {
        dirParts.pop()
      } else if (part !== '.' && part !== '') {
        dirParts.push(part)
      }
    }

    return dirParts.join('/')
  }

  const normalizeMarkdownHref = (href) => {
    if (!href) return href

    const [pathPart, hashPart = ''] = href.split('#')
    const [rawPath, searchPart = ''] = pathPart.split('?')

    const decodedPath = rawPath
      .split('/')
      .map((part) => {
        try {
          return decodeURIComponent(part)
        } catch (e) {
          return part
        }
      })
      .join('/')

    const rebuilt = searchPart ? `${decodedPath}?${searchPart}` : decodedPath
    return hashPart ? `${rebuilt}#${hashPart}` : rebuilt
  }

  const isExternalHref = (href) => {
    return Boolean(href && (/^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith('//')))
  }

  // 处理markdown内部链接点击
  const handleMarkdownLink = (e, href) => {
    const normalizedHref = normalizeMarkdownHref(href)

    // 检查是否是外部链接
    if (!normalizedHref || isExternalHref(normalizedHref)) {
      return // 外部链接，允许默认行为
    }

    // 检查是否是锚点链接
    if (normalizedHref.startsWith('#')) {
      return // 锚点链接，允许默认行为
    }

    // 检查是否是文档文件（.md 或 .pdf）
    const pathOnly = normalizedHref.split(/[?#]/)[0]
    const isMd = pathOnly.endsWith('.md')
    const isPdf = pathOnly.toLowerCase().endsWith('.pdf')

    if (!isMd && !isPdf) {
      return // 不是文档文件，允许默认行为
    }

    // 阻止默认跳转
    e.preventDefault()

    // 解析路径
    let targetPath
    if (pathOnly.startsWith('.') || pathOnly.startsWith('..')) {
      // 真正的相对路径，相对于当前文件
      targetPath = resolveRelativePath(selectedFile, pathOnly)
    } else {
      // 项目内绝对路径（由编辑器生成），相对于项目根目录
      targetPath = pathOnly.startsWith('/') ? pathOnly.substring(1) : pathOnly
    }

    // 自动展开父目录
    const lastSlashIndex = targetPath.lastIndexOf('/')
    if (lastSlashIndex !== -1) {
      const parentPath = targetPath.substring(0, lastSlashIndex)
      if (parentPath && !openKeys.includes(parentPath)) {
        // 收集所有父路径
        const pathParts = parentPath.split('/')
        const allParentPaths = []
        let currentPath = ''
        for (const part of pathParts) {
          currentPath = currentPath ? `${currentPath}/${part}` : part
          allParentPaths.push(currentPath)
        }
        setOpenKeys([...new Set([...openKeys, ...allParentPaths])])
      }
    }

    // 选中文件并加载
    setSelectedFile(targetPath)
    setSelectedNodeKey(targetPath)
    updateFileParam(targetPath)

    if (isPdf) {
      // PDF文件：切换到PDF模式
      setPdfUrl(buildDocumentUrl(targetPath))
      setPdfFilename(targetPath.split('/').pop())
      setViewMode('pdf')
    } else {
      // Markdown文件：加载内容
      setViewMode('markdown')
      loadMarkdown(targetPath)
    }
  }

  const handleGitPull = async (repoId = null, force = false) => {
    if (gitRepos.length === 0) {
      message.warning('未配置Git仓库')
      return
    }
    try {
      const res = await gitPull(projectId, repoId, force)
      message.success(res.message || 'Git Pull 成功')
      // Refresh tree
      loadFileTree()
      // Reload current file if open
      if (selectedFile) {
        loadMarkdown(selectedFile)
      }
    } catch (error) {
       console.error('Git Pull error:', error)
       const errorMsg = error.response?.data?.detail || 'Git Pull 失败'
       
       if (!force) {
         Modal.confirm({
           title: 'Git Pull 失败',
           content: (
             <div>
               <p>{errorMsg}</p>
               <p style={{ color: 'red', fontWeight: 'bold', marginTop: 8 }}>
                 是否强制重置到远程版本？
               </p>
               <p style={{ color: '#666', fontSize: 12 }}>
                 警告：这将丢失所有本地未提交的修改！
               </p>
             </div>
           ),
           okText: '强制重置',
           okType: 'danger',
           cancelText: '取消',
           onOk: () => handleGitPull(repoId, true)
         })
         return
       }
       
       message.error(errorMsg)
    }
  }

  const handleGitPush = async (repoId = null, force = false) => {
    if (gitRepos.length === 0) {
      message.warning('未配置Git仓库')
      return
    }
    try {
      const res = await gitPush(projectId, repoId, force)
      message.success(res.message || 'Git Push 成功')
    } catch (error) {
       console.error('Git Push error:', error)
       const errorMsg = error.response?.data?.detail || 'Git Push 失败'
       
       if (!force) {
         Modal.confirm({
           title: 'Git Push 失败',
           content: (
             <div>
               <p>{errorMsg}</p>
               <p style={{ color: 'red', fontWeight: 'bold', marginTop: 8 }}>
                 是否强制推送到远程？
               </p>
               <p style={{ color: '#666', fontSize: 12 }}>
                 警告：这将覆盖远程仓库的修改！
               </p>
             </div>
           ),
           okText: '强制推送',
           okType: 'danger',
           cancelText: '取消',
           onOk: () => handleGitPush(repoId, true)
         })
         return
       }
       
       message.error(errorMsg)
    }
  }

  const renderGitActions = () => {
    if (gitRepos.length <= 1) {
      // 0 或 1 个仓库，显示普通按钮
      return (
        <>
          <Tooltip title="Git Pull">
            <Button
              size="middle"
              icon={<CloudDownloadOutlined />}
              onClick={() => handleGitPull()}
            />
          </Tooltip>
          <Tooltip title="Git Push">
            <Button
              size="middle"
              icon={<CloudUploadOutlined />}
              onClick={() => handleGitPush()}
            />
          </Tooltip>
        </>
      )
    }

    // 多个仓库，显示下拉菜单
    const pullItems = gitRepos.map(repo => ({
      key: repo.id,
      label: repo.name + (repo.is_default ? ' (默认)' : ''),
      onClick: () => handleGitPull(repo.id),
    }))

    const pushItems = gitRepos.map(repo => ({
      key: repo.id,
      label: repo.name + (repo.is_default ? ' (默认)' : ''),
      onClick: () => handleGitPush(repo.id),
    }))

    if (gitRepos.length <= 1) {
      return (
        <>
          <Tooltip title="Git Pull">
            <Button
              size="middle"
              icon={<CloudDownloadOutlined />}
              onClick={() => handleGitPull()}
            />
          </Tooltip>
          <Tooltip title="Git Push">
            <Button
              size="middle"
              icon={<CloudUploadOutlined />}
              onClick={() => handleGitPush()}
            />
          </Tooltip>
        </>
      )
    }

    return (
      <>
        <Dropdown menu={{ items: pullItems }}>
          <Tooltip title="Git Pull">
            <Button
              size="middle"
              icon={<CloudDownloadOutlined />}
            />
          </Tooltip>
        </Dropdown>
        <Dropdown menu={{ items: pushItems }}>
          <Tooltip title="Git Push">
            <Button
              size="middle"
              icon={<CloudUploadOutlined />}
            />
          </Tooltip>
        </Dropdown>
      </>
    )
  }

  // 进入编辑模式
  const handleEdit = () => {
    const params = new URLSearchParams()
    if (selectedFile) {
      params.set('file', selectedFile)
    } else if (selectedNodeKey) {
      params.set('selected', selectedNodeKey)
    }
    const query = params.toString()
    navigateWithTransition(`/projects/${projectId}/editor${query ? `?${query}` : ''}`)
  }

  const handleRefresh = async () => {
    setRefreshing(true)
    try {
      await loadFileTree({ throwOnError: true })
      message.success('已刷新')
    } catch (error) {
      console.error('Refresh documents error:', error)
      message.error('刷新失败')
    } finally {
      setRefreshing(false)
    }
  }

  // 打开分享设置
  const handleShare = async () => {
    const selectedNode = selectedNodeKey ? findNodeByKey(fileTree, selectedNodeKey) : null
    if (!selectedNode || !selectedNode.isLeaf) {
      Toast.warning('提示', '请先选择一个文件再分享')
      return
    }

    try {
      const res = await getFileShareInfo(projectId, selectedNode.key)
      const nextShareInfo = res.data
      setShareInfo(nextShareInfo)
      setHasPassword(Boolean(nextShareInfo?.has_password))
      setPassword(nextShareInfo?.access_pass || '')
      setShareModalVisible(true)
    } catch (error) {
      console.error('Get share info error:', error)
      message.error('获取分享信息失败')
    }
  }

  // 复制分享链接
  const handleCopyLink = async () => {
    if (!shareInfo) return
    const fullUrl = `${window.location.origin}${shareInfo.share_url}`
    
    try {
      if (navigator.clipboard && window.isSecureContext) {
        await navigator.clipboard.writeText(fullUrl)
        Toast.success('复制成功', '分享链接已复制到剪贴板')
      } else {
        // Fallback for non-secure contexts or older browsers
        const textArea = document.createElement("textarea")
        textArea.value = fullUrl
        textArea.style.position = "fixed"
        textArea.style.left = "-9999px"
        textArea.style.top = "0"
        document.body.appendChild(textArea)
        textArea.focus()
        textArea.select()
        const successful = document.execCommand('copy')
        document.body.removeChild(textArea)
        if (successful) {
           Toast.success('复制成功', '分享链接已复制到剪贴板')
        } else {
           Toast.error('复制失败', '请手动复制链接')
        }
      }
    } catch (err) {
      console.error('Failed to copy:', err)
      Toast.error('复制失败', '无法访问剪贴板')
    }
  }

  // 切换密码保护
  const handlePasswordToggle = async (checked) => {
    if (!selectedNodeKey) return

    if (!checked) {
      try {
        if (shareInfo?.share_url) {
          await createOrUpdateFileShare(projectId, { file_path: selectedNodeKey, access_pass: null })
        } else {
          await deleteFileShare(projectId, selectedNodeKey)
        }
        setHasPassword(false)
        setPassword('')
        message.success('已取消文件访问密码')
        await loadFileTree()
        const res = await getFileShareInfo(projectId, selectedNodeKey)
        setShareInfo(res.data)
      } catch (error) {
        console.error('Update settings error:', error)
        message.error('操作失败')
      }
    } else {
      setHasPassword(true)
    }
  }

  // 保存密码
  const handleSavePassword = async () => {
    if (!selectedNodeKey) {
      message.warning('请先选择文件')
      return
    }

    if (!password.trim()) {
      message.warning('请输入访问密码')
      return
    }
    try {
      const res = await createOrUpdateFileShare(projectId, {
        file_path: selectedNodeKey,
        access_pass: hasPassword ? password : null,
      })
      message.success('文件分享已更新')
      setShareInfo(res.data)
      await loadFileTree()
      const nextInfo = await getFileShareInfo(projectId, selectedNodeKey)
      setShareInfo(nextInfo.data)
      setHasPassword(Boolean(nextInfo.data?.has_password))
    } catch (error) {
      console.error('Save password error:', error)
      message.error('设置文件分享失败')
    }
  }

  const handleCreateShare = async () => {
    if (!selectedNodeKey) {
      message.warning('请先选择文件')
      return
    }

    try {
      const res = await createOrUpdateFileShare(projectId, {
        file_path: selectedNodeKey,
        access_pass: hasPassword ? password : null,
      })
      setShareInfo(res.data)
      setHasPassword(Boolean(res.data?.has_password))
      await loadFileTree()
      message.success('文件分享已创建')
    } catch (error) {
      console.error('Create file share error:', error)
      message.error('创建文件分享失败')
    }
  }

  const handleDisableShare = async () => {
    if (!selectedNodeKey) return

    try {
      await deleteFileShare(projectId, selectedNodeKey)
      setShareInfo(null)
      setHasPassword(false)
      setPassword('')
      await loadFileTree()
      message.success('文件分享已关闭')
    } catch (error) {
      console.error('Delete file share error:', error)
      message.error('关闭文件分享失败')
    }
  }

  const menuItems = convertTreeToMenuItems(filteredTreeData)

  // Markdown 内容高亮处理
  // 使用 components 替换文本节点，但这只对直接文本子节点有效
  // 对于深层嵌套，我们需要递归或使用 rehype 插件
  // 这里使用简单组件替换
  const markdownComponents = useMemo(() => {
    if (!searchKeyword) {
      return {
        a: ({ node, href, children, ...props }) => {
          const isExternal = isExternalHref(href);
          return (
            <a
              href={href}
              onClick={(e) => handleMarkdownLink(e, href)}
              target={isExternal ? '_blank' : undefined}
              rel={isExternal ? 'noopener noreferrer' : undefined}
              {...props}
            >
              {children}
            </a>
          );
        },
      }
    }

    // 搜索模式下，尝试高亮
    // 注意：这可能不完美，但比没有好
    const highlightRenderer = (Tag) => ({ node, children, ...props }) => {
      // 如果 children 是字符串，高亮
      if (typeof children === 'string') {
        return <Tag {...props}><HighlightText text={children} keyword={searchKeyword} /></Tag>
      }
      // 如果是数组，遍历
      if (Array.isArray(children)) {
        const newChildren = children.map((child, idx) => {
          if (typeof child === 'string') {
            return <HighlightText key={idx} text={child} keyword={searchKeyword} />
          }
          return child
        })
        return <Tag {...props}>{newChildren}</Tag>
      }
      return <Tag {...props}>{children}</Tag>
    }

    return {
      a: ({ node, href, children, ...props }) => {
        const isExternal = isExternalHref(href);
        return (
          <a
            href={href}
            onClick={(e) => handleMarkdownLink(e, href)}
            target={isExternal ? '_blank' : undefined}
            rel={isExternal ? 'noopener noreferrer' : undefined}
            {...props}
          >
            {typeof children === 'string' ? <HighlightText text={children} keyword={searchKeyword} /> : children}
          </a>
        );
      },
      p: highlightRenderer('p'),
      li: highlightRenderer('li'),
      h1: highlightRenderer('h1'),
      h2: highlightRenderer('h2'),
      h3: highlightRenderer('h3'),
      h4: highlightRenderer('h4'),
      h5: highlightRenderer('h5'),
      h6: highlightRenderer('h6'),
      span: highlightRenderer('span'),
      td: highlightRenderer('td'),
      th: highlightRenderer('th'),
      div: highlightRenderer('div'),
    }
  }, [searchKeyword])

  return (
    <div className="project-docs-page">
      <Layout className="docs-layout">
        {/* 左侧目录 */}
        <Sider width={280} className="docs-sider" theme="light">
          <div className="docs-sider-header">
            <div className="docs-sider-title-row">
              <button
                type="button"
                className="project-back-button"
                onClick={handleClose}
                aria-label="返回项目列表"
              >
                <ArrowLeftOutlined />
              </button>
              <h2 title={projectName}>{projectName}</h2>
            </div>
            <div className="docs-sider-actions">
              <div className="mode-actions-row">
                {/* 只有 owner/admin/editor 可以编辑和Git操作 */}
                {userRole !== 'viewer' ? (
                  <ModeSwitch
                    size="small"
                    value={modeSwitchValue}
                    onChange={(mode) => {
                      if (mode === 'edit' && !modeSwitchingRef.current) {
                        modeSwitchingRef.current = true
                        setModeSwitchValue('edit')
                        setTimeout(() => {
                          handleEdit()
                        }, 160)
                      }
                    }}
                  />
                ) : (
                  <div />
                )}
                <Space.Compact className="mode-actions-group">
                  {userRole !== 'viewer' && renderGitActions()}
                  <Tooltip title="分享">
                    <Button
                      size="middle"
                      icon={<ShareAltOutlined />}
                      onClick={handleShare}
                    />
                  </Tooltip>
                  <Tooltip title="刷新">
                    <Button
                      size="middle"
                      icon={<ReloadOutlined spin={refreshing} />}
                      onClick={handleRefresh}
                      disabled={refreshing}
                    />
                  </Tooltip>
                </Space.Compact>
              </div>
            </div>
          </div>

          {/* 搜索框 */}
          <div style={{ padding: '12px 16px 4px' }}>
            <Input.Search
              placeholder="搜索文档内容..."
              allowClear
              value={searchKeyword}
              onChange={(e) => setSearchKeyword(e.target.value)}
              onSearch={handleSearch}
              loading={isSearching}
              enterButton
            />
          </div>

          {filteredTreeData.length > 0 ? (
            <Menu
              mode="inline"
              selectedKeys={selectedNodeKey ? [selectedNodeKey] : []}
              openKeys={openKeys}
              onOpenChange={setOpenKeys}
              items={menuItems}
              onClick={handleMenuClick}
              className="docs-menu"
            />
          ) : (
            <div style={{ padding: '20px', textAlign: 'center', color: '#999' }}>
              <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="未找到匹配文档" />
            </div>
          )}
        </Sider>

        {/* 右侧内容区 */}
        <Layout className="docs-content-layout">
          <Content className="docs-content" ref={contentRef}>
            <div className="docs-content-header" title={selectedFile || 'README.md'}>
              {(() => {
                const { fileName, FileIcon, isPdf } = getHeaderDisplay(selectedFile)
                return (
                  <>
                    <div className="docs-header-title">
                      <span className="docs-header-item">
                        <FileIcon className="docs-header-icon" style={isPdf ? { color: '#f5222d' } : undefined} />
                        <span className="docs-header-text">{fileName}</span>
                      </span>
                    </div>
                    {viewMode === 'pdf' && <div className="docs-header-actions pdf-header-toolbar" ref={setPdfToolbarTarget} />}
                    {viewMode === 'markdown' && (
                      <Space className="docs-header-actions">
                        <Button
                          icon={<VerticalAlignTopOutlined />}
                          onClick={scrollContentToTop}
                          size="small"
                        >
                          回到顶部
                        </Button>
                        <Button
                          icon={<CloudDownloadOutlined />}
                          onClick={handleExportMarkdownPDF}
                          size="small"
                        >
                          下载PDF
                        </Button>
                      </Space>
                    )}
                  </>
                )
              })()}
            </div>
            <div className={`docs-content-wrapper ${viewMode === 'pdf' ? 'pdf-mode' : ''} ${isLargeMarkdown ? 'large-markdown-mode' : ''}`}>
              {loading ? (
                <div className="docs-loading">
                  <Spin size="large">
                    <div style={{ marginTop: 16 }}>加载中...</div>
                  </Spin>
                </div>
              ) : viewMode === 'pdf' ? (
                <VirtualPDFViewer
                  url={pdfUrl}
                  filename={pdfFilename}
                  toolbarTarget={pdfToolbarTarget}
                />
              ) : viewMode === 'folder' ? (
                <div className="docs-folder-placeholder">
                  <FolderOpenOutlined />
                  <span>已选择文件夹，请从左侧选择 Markdown 或 PDF 文件查看。</span>
                </div>
              ) : isLargeMarkdown ? (
                <LargeMarkdownViewer
                  ref={largeMarkdownRef}
                  content={markdownContent}
                  components={markdownComponents}
                  searchKeyword={searchKeyword}
                  renderTitle={(item, keyword) => <HighlightText text={item.title} keyword={keyword} />}
                />
              ) : (
                <div className="markdown-body">
                  <ReactMarkdown
                    remarkPlugins={[remarkGfm]}
                    rehypePlugins={[rehypeRaw, rehypeSlug, rehypeHighlight]}
                    components={markdownComponents}
                  >
                    {markdownContent}
                  </ReactMarkdown>
                </div>
              )}
            </div>

          </Content>

          {viewMode === 'markdown' && !isLargeMarkdown && (
            <FloatingToc
              items={tocItems}
              searchKeyword={searchKeyword}
              getContainer={() => contentRef.current}
              renderTitle={(item, keyword) => <HighlightText text={item.title} keyword={keyword} />}
            />
          )}
        </Layout>
      </Layout>

      {/* 分享模态框 */}
      {/* ... keeping the modal ... */}
      <Modal
        title="文件分享"
        open={shareModalVisible}
        onCancel={() => setShareModalVisible(false)}
        footer={null}
        width={500}
      >
        <Space direction="vertical" style={{ width: '100%' }} size="large">
          <div>
            <label style={{ marginBottom: 8, display: 'block', fontWeight: 500 }}>
              当前文件
            </label>
            <Input value={selectedNodeKey || ''} readOnly />
          </div>

          {shareInfo?.share_url ? (
            <>
              <div>
                <label style={{ marginBottom: 8, display: 'block', fontWeight: 500 }}>
                  分享链接
                </label>
                <Input
                  value={`${window.location.origin}${shareInfo.share_url}`}
                  readOnly
                  addonAfter={
                    <CopyOutlined onClick={handleCopyLink} style={{ cursor: 'pointer' }} />
                  }
                />
              </div>

              <div>
                <Space>
                  <span style={{ fontWeight: 500 }}>访问密码保护</span>
                  <Switch checked={hasPassword} onChange={handlePasswordToggle} />
                </Space>
              </div>

              {hasPassword && (
                <Space.Compact style={{ width: '100%' }}>
                  <Input.Password
                    placeholder="请输入访问密码"
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                  />
                  <Button type="primary" onClick={handleSavePassword}>
                    保存密码
                  </Button>
                </Space.Compact>
              )}
            </>
          ) : (
            <>
              <div style={{ color: '#8c8c8c', lineHeight: 1.7 }}>
                当前文件尚未创建独立分享。
              </div>

              <Button type="primary" onClick={handleCreateShare}>
                创建文件分享
              </Button>
            </>
          )}
          {shareInfo?.share_url && (
            <Button danger onClick={handleDisableShare}>
              关闭文件分享
            </Button>
          )}
        </Space>
      </Modal>
    </div>
  )
}

export default DocumentPage
