import { useState, useEffect, useCallback, useMemo } from 'react'
import {
  Folder,
  Plus,
  FileCode,
  FileText,
  MoreHorizontal,
  ChevronRight,
  ChevronDown,
  Copy,
  Home,
  ArrowLeft,
  Filter,
  ArrowDownToLine,
  GitCommitHorizontal,
  User,
  Calendar,
  GitBranch,
  ChevronsUpDown,
  Check
} from 'lucide-react'



import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'
import { giteaApi } from '@/api/gitea'
import { GiteaRepository, GiteaFile, GiteaTreeNode, RepoTreeCache, TreeDiffResult, GiteaCommit } from '@/api/types'
import { useCache, cacheUtils } from '@/hooks/useCache'
import { useToast } from '@/hooks/use-toast'
import { useDownloadManager } from '@/components/DownloadManager'

// 格式化字节大小的辅助函数
function formatBytes(bytes: number, decimals = 2) {
  if (!+bytes) return '0 B'
  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}

// 解码 Base64 的辅助函数（处理 UTF-8）
function decodeBase64(str: string) {
  try {
    return decodeURIComponent(escape(window.atob(str)));
  } catch (e) {
    return window.atob(str);
  }
}

const BINARY_EXTENSIONS = new Set([
  'dll', 'exe', 'lib', 'so', 'dylib', 'bin', 'obj', 'pdb',
  'zip', 'tar', 'gz', '7z', 'rar',
  'png', 'jpg', 'jpeg', 'gif', 'bmp', 'ico', 'webp', 'svg',
  'mp4', 'mp3', 'wav', 'mov', 'avi',
  'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
  'ttf', 'otf', 'woff', 'woff2',
  'unitypackage', 'apk', 'ipa'
])

const MAX_PREVIEW_SIZE = 1024 * 512; // 512KB Limit

// 树形数据类型
interface TreeItem {
  id: string
  label: string
  type: 'folder' | 'project'
  children?: TreeItem[]
  repoId?: number // Link to real repo if applicable
  tag?: 'Git' | 'Public' | 'Private'
  expanded?: boolean
}

export default function ProjectLibrary() {
  const { toast, success, error: showError } = useToast()
  const { startDownload } = useDownloadManager()

  // 使用缓存Hook获取仓库列表
  const fetchRepos = useCallback(() => giteaApi.getRepositories(), [])
  const cacheConfig = useMemo(() => ({ namespace: 'projects' }), [])

  const {
    data: repos
  } = useCache<GiteaRepository[]>(
    'project-library-repos', // 缓存键
    fetchRepos, // 数据获取函数
    cacheConfig // 缓存配置：使用projects命名空间
  )

  const [selectedRepo, setSelectedRepo] = useState<GiteaRepository | null>(null)
  const [currentPath, setCurrentPath] = useState<string[]>([])
  const [files, setFiles] = useState<GiteaFile[]>([])
  const [selectedFile, setSelectedFile] = useState<GiteaFile | null>(null)
  const [fileContent, setFileContent] = useState<string>('')
  const [isEditorVisible, setIsEditorVisible] = useState(false)
  const [loading, setLoading] = useState(false)

  // 树形状态
  const [treeData, setTreeData] = useState<TreeItem[]>([])
  const [selectedTreeId, setSelectedTreeId] = useState<string>('')

  // 缓存优化相关状态
  const [repoTreeCache, setRepoTreeCache] = useState<RepoTreeCache | null>(null)  // 当前仓库的目录树缓存
  const [cacheProgress, setCacheProgress] = useState<{ current: number; total: number; status: string }>({ current: 0, total: 0, status: '' })
  const [isCaching, setIsCaching] = useState(false)  // 是否正在预缓存
  const [syncResult, setSyncResult] = useState<TreeDiffResult | null>(null)  // 同步结果
  const [commits, setCommits] = useState<GiteaCommit[]>([]) // Git Commits
  const [commitsLoading, setCommitsLoading] = useState(false) // Commits loading state

  // Branch Management
  const [branches, setBranches] = useState<any[]>([])
  const [selectedBranch, setSelectedBranch] = useState<string>('')
  const [isBranchDropdownOpen, setIsBranchDropdownOpen] = useState(false)

  // 当repos数据变化时，构建树形结构
  useEffect(() => {
    if (!repos || repos.length === 0) return

    // 从仓库构建树形数据
    const newTreeData: TreeItem[] = []

    // 按所有者分组
    const ownerGroups: Record<string, GiteaRepository[]> = {}
    repos.forEach(repo => {
      const ownerName = repo.owner.username
      if (!ownerGroups[ownerName]) {
        ownerGroups[ownerName] = []
      }
      ownerGroups[ownerName].push(repo)
    })

    // 为每个所有者创建文件夹
    Object.keys(ownerGroups).forEach((owner) => {
      const ownerRepos = ownerGroups[owner]
      newTreeData.push({
        id: `owner-${owner}`,
        label: owner,
        type: 'folder',
        expanded: true,
        children: ownerRepos.map(repo => ({
          id: `repo-${repo.id}`,
          label: repo.name,
          type: 'project',
          repoId: repo.id,
          tag: repo.private ? 'Private' : 'Public'
        }))
      })
    })

    setTreeData(newTreeData)

    // 如果有可用仓库，选择第一个
    if (!selectedRepo && repos.length > 0) {
      const firstRepo = repos[0]
      setSelectedRepo(firstRepo)
      setSelectedTreeId(`repo-${firstRepo.id}`)
    }
  }, [repos])

  /**
   * 对比两个目录树，找出差异
   */
  const compareTree = (oldTree: GiteaTreeNode[], newTree: GiteaTreeNode[]): TreeDiffResult => {
    const oldMap = new Map(oldTree.map(n => [n.path, n]))
    const newMap = new Map(newTree.map(n => [n.path, n]))

    const added: GiteaTreeNode[] = []
    const deleted: GiteaTreeNode[] = []
    const modified: GiteaTreeNode[] = []
    let unchanged = 0

    // 找新增和修改
    for (const [path, node] of newMap) {
      const oldNode = oldMap.get(path)
      if (!oldNode) {
        added.push(node)
      } else if (oldNode.sha !== node.sha) {
        modified.push(node)
      } else {
        unchanged++
      }
    }

    // 找删除
    for (const [path, node] of oldMap) {
      if (!newMap.has(path)) {
        deleted.push(node)
      }
    }

    return { added, deleted, modified, unchanged }
  }

  // 当仓库变化时获取提交记录
  useEffect(() => {
    if (!selectedRepo) {
      setCommits([])
      return
    }

    const fetchCommits = async () => {
      try {
        setCommitsLoading(true)
        const cacheKey = `commits-${selectedRepo.owner.username}-${selectedRepo.name}`

        console.log(`尝试读取提交记录缓存: ${cacheKey}`)
        const cachedCommits = await cacheUtils.getJSON<GiteaCommit[]>(cacheKey, { namespace: 'projects' })

        if (cachedCommits) {
          console.log('从缓存加载提交记录')
          setCommits(cachedCommits)
          // 即使有缓存，也可以在后台静默更新（可选，暂不实现以保证速度）
          setCommitsLoading(false)
          return
        }

        console.log('调用API获取提交记录')
        // 1. 首先尝试获取分支信息以快速填充 Banner（通常比获取完整提交列表快得多）
        try {
          const branchData = await giteaApi.getRepoBranch(selectedRepo.owner.username, selectedRepo.name, selectedRepo.default_branch)
          if (branchData && branchData.commit) {
            // 构造一个简单的 GiteaCommit 对象用于 Banner 显示
            const latestCommit: any = {
              sha: branchData.commit.id,
              commit: {
                message: branchData.commit.message,
                author: {
                  name: branchData.commit.author.name,
                  date: branchData.commit.timestamp
                }
              }
            }
            setCommits([latestCommit])
            // 这里不设置 Loading 结束，因为还要拉取列表
          }
        } catch (branchError) {
          console.error("Failed to fetch branch info:", branchError)
        }

        // 2. 拉取完整的提交列表用于下方的记录显示
        const data = await giteaApi.getRepoCommits(selectedRepo.owner.username, selectedRepo.name, 1, 20)
        setCommits(data)

        // 缓存提交记录
        await cacheUtils.setJSON(cacheKey, data, { namespace: 'projects', maxAge: 1000 * 60 * 5 }) // 5分钟缓存
      } catch (error: any) {
        console.error("Failed to fetch commits:", error)
        setCommits([])

        // 如果是超时错误，给用户明确提示
        if (error.code === 'ECONNABORTED' || error.message?.includes('timeout')) {
          toast(`获取提交记录超时 (60s)，请检查网络或稍后重试`, { type: 'error' })
        }
      } finally {
        setCommitsLoading(false)
      }
    }

    fetchCommits()
    fetchCommits()
  }, [selectedRepo])

  // Fetch Branches when Repo changes
  useEffect(() => {
    if (!selectedRepo) {
      setBranches([])
      setSelectedBranch('')
      return
    }

    const fetchBranches = async () => {
      try {
        const data = await giteaApi.getRepoBranches(selectedRepo.owner.username, selectedRepo.name)
        setBranches(data)
        // Set default branch initially
        if (!selectedBranch || selectedBranch !== selectedRepo.default_branch) {
          setSelectedBranch(selectedRepo.default_branch)
        }
      } catch (error) {
        console.error("Failed to fetch branches:", error)
      }
    }
    fetchBranches()
  }, [selectedRepo])

  /**
   * 预加载仓库目录树缓存
   */
  const prefetchRepoTree = async (repo: GiteaRepository) => {
    const treeCacheKey = `repo-tree-${repo.owner.username}-${repo.name}`

    try {
      setIsCaching(true)
      setCacheProgress({ current: 0, total: 1, status: '检查缓存...' })

      // 尝试从缓存读取
      const cachedTree = await cacheUtils.getJSON<RepoTreeCache>(treeCacheKey, { namespace: 'projects' })

      if (cachedTree) {
        console.log(`从缓存加载目录树: ${treeCacheKey}`)
        setRepoTreeCache(cachedTree)
        setCacheProgress({ current: 1, total: 1, status: '缓存已加载' })
        setIsCaching(false)
        return cachedTree
      }

      // 缓存不存在，调用 API 获取
      setCacheProgress({ current: 0, total: 1, status: '获取目录树...' })
      console.log(`调用 API 获取目录树: ${repo.owner.username}/${repo.name}`)

      const result = await giteaApi.getRepoTree(repo.owner.username, repo.name, repo.default_branch)

      const newTreeCache: RepoTreeCache = {
        owner: repo.owner.username,
        repo: repo.name,
        sha: result.sha,
        fetchedAt: Date.now(),
        tree: result.tree
      }

      // 写入缓存
      await cacheUtils.setJSON(treeCacheKey, newTreeCache, { namespace: 'projects' })
      console.log(`目录树缓存完成: ${result.tree.length} 个节点`)

      setRepoTreeCache(newTreeCache)
      setCacheProgress({ current: 1, total: 1, status: `已缓存 ${result.tree.length} 个文件/目录` })
      setIsCaching(false)

      return newTreeCache
    } catch (error) {
      console.error('预加载目录树失败:', error)
      setCacheProgress({ current: 0, total: 0, status: '缓存失败' })
      setIsCaching(false)
      return null
    }
  }

  /**
   * 增量同步 - 只更新变化的部分
   */
  const incrementalSync = async (repo: GiteaRepository) => {
    const treeCacheKey = `repo-tree-${repo.owner.username}-${repo.name}`

    try {
      setIsCaching(true)
      setCacheProgress({ current: 0, total: 3, status: '获取最新目录树...' })

      // 1. 获取最新的目录树
      const result = await giteaApi.getRepoTree(repo.owner.username, repo.name, repo.default_branch)
      setCacheProgress({ current: 1, total: 3, status: '对比差异...' })

      // 2. 获取旧缓存
      const oldCache = await cacheUtils.getJSON<RepoTreeCache>(treeCacheKey, { namespace: 'projects' })
      const oldTree = oldCache?.tree || []

      // 3. 对比差异
      const diff = compareTree(oldTree, result.tree)
      console.log('同步差异:', {
        added: diff.added.length,
        deleted: diff.deleted.length,
        modified: diff.modified.length,
        unchanged: diff.unchanged
      })

      setCacheProgress({ current: 2, total: 3, status: '更新缓存...' })

      // 4. 删除被移除文件的内容缓存
      for (const node of diff.deleted) {
        if (node.type === 'blob') {
          const contentKey = `content-${repo.owner.username}-${repo.name}-${node.path}`
          await cacheUtils.delete(contentKey, 'projects')
        }
      }

      // 5. 删除被修改文件的内容缓存（下次点击时重新加载）
      for (const node of diff.modified) {
        if (node.type === 'blob') {
          const contentKey = `content-${repo.owner.username}-${repo.name}-${node.path}`
          await cacheUtils.delete(contentKey, 'projects')
        }
      }

      // 6. 更新目录树缓存
      const newTreeCache: RepoTreeCache = {
        owner: repo.owner.username,
        repo: repo.name,
        sha: result.sha,
        fetchedAt: Date.now(),
        tree: result.tree
      }
      await cacheUtils.setJSON(treeCacheKey, newTreeCache, { namespace: 'projects' })

      setRepoTreeCache(newTreeCache)
      setSyncResult(diff)
      setCacheProgress({ current: 3, total: 3, status: '同步完成' })
      setIsCaching(false)

      // 3秒后清除同步结果提示
      setTimeout(() => setSyncResult(null), 5000)

      return diff
    } catch (error) {
      console.error('增量同步失败:', error)
      setCacheProgress({ current: 0, total: 0, status: '同步失败' })
      setIsCaching(false)
      throw error
    }
  }

  /**
   * Git同步功能 - 增量同步
   */
  const handleGitSync = async () => {
    if (!selectedRepo) return

    try {
      console.log('Git同步: 开始增量同步')
      await incrementalSync(selectedRepo)
      console.log('Git同步完成')
    } catch (error) {
      console.error('Git同步失败:', error)
    }
  }


  // Fetch Files when Repo or Path changes (优先使用树缓存)
  useEffect(() => {
    if (!selectedRepo) return

    const fetchFiles = async () => {
      try {
        setLoading(true)
        const pathStr = currentPath.join("/")

        // 首先尝试从树缓存中提取当前路径的文件列表
        if (repoTreeCache && repoTreeCache.owner === selectedRepo.owner.username && repoTreeCache.repo === selectedRepo.name) {
          console.log(`从树缓存提取文件列表: ${pathStr || 'root'}`)

          // 从树缓存中筛选当前路径下的直接子节点
          const currentPathPrefix = pathStr ? `${pathStr}/` : ''
          const filesFromCache: GiteaFile[] = []

          for (const node of repoTreeCache.tree) {
            // 检查是否为当前路径的直接子节点
            if (pathStr === '') {
              // 根目录：只取第一级（不包含 /）
              if (!node.path.includes('/')) {
                filesFromCache.push({
                  name: node.path,
                  path: node.path,
                  sha: node.sha,
                  type: node.type === 'tree' ? 'dir' : 'file',
                  size: node.size || 0,
                  url: node.url || ''
                })
              }
            } else {
              // 子目录：取以 currentPathPrefix 开头但后面不再包含 / 的节点
              if (node.path.startsWith(currentPathPrefix)) {
                const relativePath = node.path.slice(currentPathPrefix.length)
                if (!relativePath.includes('/')) {
                  filesFromCache.push({
                    name: relativePath,
                    path: node.path,
                    sha: node.sha,
                    type: node.type === 'tree' ? 'dir' : 'file',
                    size: node.size || 0,
                    url: node.url || ''
                  })
                }
              }
            }
          }

          // 排序：文件夹优先，然后按名称排序
          const sortedFiles = filesFromCache.sort((a, b) => {
            if (a.type === 'dir' && b.type !== 'dir') return -1
            if (a.type !== 'dir' && b.type === 'dir') return 1
            return a.name.localeCompare(b.name)
          })

          setFiles(sortedFiles)
          setLoading(false)
          return
        }

        // 树缓存不可用，回退到旧的缓存/API方式
        const cacheKey = `files-${selectedRepo.owner.username}-${selectedRepo.name}-${pathStr || 'root'}`

        // 尝试从缓存读取
        console.log(`尝试从缓存读取文件列表: ${cacheKey}`)
        const cachedFiles = await cacheUtils.getJSON<GiteaFile[]>(cacheKey, { namespace: 'projects' })

        if (cachedFiles) {
          console.log(`从缓存加载文件列表成功: ${cacheKey}`)
          setFiles(cachedFiles)
          setLoading(false)
          return
        }

        // 缓存不存在，调用API获取
        console.log(`缓存不存在，调用API获取文件列表: ${cacheKey}`)
        const data = await giteaApi.getRepoContents(selectedRepo.owner.username, selectedRepo.name, pathStr)

        // 排序：文件夹优先，然后按名称排序
        const sortedData = data.sort((a, b) => {
          if (a.type === 'dir' && b.type !== 'dir') return -1
          if (a.type !== 'dir' && b.type === 'dir') return 1
          return a.name.localeCompare(b.name)
        })

        // 写入缓存
        console.log(`写入文件列表缓存: ${cacheKey}`)
        await cacheUtils.setJSON(cacheKey, sortedData, { namespace: 'projects' })

        setFiles(sortedData)
      } catch (error) {
        console.error("Failed to fetch files:", error)
        setFiles([])
      } finally {
        setLoading(false)
      }
    }

    fetchFiles()
  }, [selectedRepo, currentPath, repoTreeCache])


  const toggleExpand = (id: string) => {
    const toggleNode = (nodes: TreeItem[]): TreeItem[] => {
      return nodes.map(node => {
        if (node.id === id) {
          return { ...node, expanded: !node.expanded }
        }
        if (node.children) {
          return { ...node, children: toggleNode(node.children) }
        }
        return node
      })
    }
    setTreeData(toggleNode(treeData))
  }

  /**
   * 检测 Git 地址连通性
   */
  const checkGitConnectivity = async (repo: GiteaRepository) => {
    try {
      // 使用一个轻量级的 API 调用来测试连通性（获取根目录内容）
      await giteaApi.getRepoContents(repo.owner.username, repo.name, '', repo.default_branch)
      success(`Git 地址连接正常：${repo.name}`)
    } catch (error) {
      console.error('Git 地址连接失败:', error)
      showError(`Git 地址连接失败：${repo.name}`)
    }
  }

  /**
   * 处理项目下载
   */
  const handleDownloadProject = async () => {
    if (!selectedRepo) return

    try {
      // 1. 选择保存目录
      const result = await window.electronAPI.file.openDirectory()
      if (result.canceled || !result.path) return

      const targetPath = result.path

      // 2. 委托给 DownloadManager 开始下载（支持排队和进度显示）
      startDownload(selectedRepo.clone_url, targetPath, selectedBranch)

    } catch (error) {
      console.error('打开下载目录失败:', error)
      showError('无法启动下载')
    }
  }

  const handleTreeSelect = (item: TreeItem) => {
    setSelectedTreeId(item.id)

    if (item.type === 'project' && item.repoId) {
      const foundRepo = repos?.find(r => r.id === item.repoId)
      if (foundRepo) {
        setSelectedRepo(foundRepo)
        // 检测 Git 地址连通性
        checkGitConnectivity(foundRepo)
        // 自动预缓存仓库目录树
        prefetchRepoTree(foundRepo)
      }
    }

    setCurrentPath([])
    setSelectedFile(null)
    setIsEditorVisible(false)
    setFileContent('')
  }


  const getFileExtension = (filename: string) => {
    return filename.split('.').pop()?.toLowerCase() || 'text'
  }

  const handleFileClick = async (file: GiteaFile) => {
    if (file.type === 'dir') {
      setCurrentPath(prev => [...prev, file.name])
      setSelectedFile(null)
      setIsEditorVisible(false)
      setFileContent('')
      return
    }

    // 如果点击相同文件且编辑器可见，不执行任何操作（或切换）
    if (selectedFile?.path === file.path && isEditorVisible) {
      return
    }

    // Check for binary extensions
    const ext = getFileExtension(file.name)
    if (BINARY_EXTENSIONS.has(ext)) {
      setSelectedFile(file)
      setFileContent('此文件为二进制文件或不支持预览。')
      setIsEditorVisible(true)
      return
    }

    // Check file size
    if (file.size > MAX_PREVIEW_SIZE) {
      setSelectedFile(file)
      setFileContent(`文件过大 (${formatBytes(file.size)})，暂不支持在线预览。`)
      setIsEditorVisible(true)
      return
    }

    try {
      setLoading(true)
      setSelectedFile(file)

      // 生成缓存键: content-owner-repo-filepath
      if (selectedRepo) {
        const cacheKey = `content-${selectedRepo.owner.username}-${selectedRepo.name}-${file.path}`

        // 尝试从缓存读取文件内容
        console.log(`尝试从缓存读取文件内容: ${cacheKey}`)
        const cachedContent = await cacheUtils.getJSON<string>(cacheKey, { namespace: 'projects' })

        if (cachedContent) {
          console.log(`从缓存加载文件内容成功: ${cacheKey}`)
          setFileContent(cachedContent)
          setIsEditorVisible(true)
          setLoading(false)
          return
        }

        // 缓存不存在，调用API获取
        console.log(`缓存不存在，调用API获取文件内容: ${cacheKey}`)
        const fileData = await giteaApi.getFileBlob(selectedRepo.owner.username, selectedRepo.name, file.path)

        if (fileData.content) {
          const decodedContent = decodeBase64(fileData.content)

          // 写入缓存
          console.log(`写入文件内容缓存: ${cacheKey}`)
          await cacheUtils.setJSON(cacheKey, decodedContent, { namespace: 'projects' })

          setFileContent(decodedContent)
        } else {
          setFileContent('无法获取文件内容或内容为空。')
        }
      }
      setIsEditorVisible(true)
    } catch (error) {
      console.error("Failed to fetch file content:", error)
      setFileContent('加载文件内容出错。')
    } finally {
      setLoading(false)
    }
  }

  const handleNavigateUp = () => {
    if (currentPath.length > 0) {
      setCurrentPath(prev => prev.slice(0, -1))
      setSelectedFile(null)
      setIsEditorVisible(false)
      setFileContent('')
    }
  }

  const handleBreadcrumbClick = (index: number) => {
    setCurrentPath(prev => prev.slice(0, index + 1))
    setSelectedFile(null)
    setIsEditorVisible(false)
    setFileContent('')
  }

  // Recursive Tree Renderer
  const renderTree = (nodes: TreeItem[], level = 0) => {
    return nodes.map(node => (
      <div key={node.id}>
        <div
          className={cn(
            "flex items-center gap-2 py-1.5 px-2 cursor-pointer transition-colors text-sm rounded-sm mb-0.5",
            selectedTreeId === node.id ? "bg-[#e0f2fe]" : "hover:bg-slate-100"
          )}
          style={{ paddingLeft: `${level * 16 + 8}px` }}
          onClick={() => handleTreeSelect(node)}
        >
          <div
            className="p-0.5 rounded-sm hover:bg-slate-200/50"
            onClick={(e) => {
              e.stopPropagation()
              if (node.children) toggleExpand(node.id)
            }}
          >
            {node.children ? (
              <ChevronDown className={cn("w-3.5 h-3.5 text-slate-400 transition-transform", !node.expanded && "-rotate-90")} />
            ) : (
              <div className="w-3.5 h-3.5" />
            )}
          </div>

          <Folder className={cn(
            "w-4 h-4",
            node.type === 'folder' ? "text-amber-400 fill-amber-400/20" : "text-amber-200 fill-amber-200/20"
          )} />

          <span className={cn("truncate flex-1 font-medium", selectedTreeId === node.id ? "text-slate-800" : "text-slate-600")}>
            {node.label}
          </span>

          {node.tag && (
            <span className={cn(
              "text-[10px] px-1.5 py-0.5 rounded border font-medium",
              node.tag === 'Git' && "bg-indigo-50 text-indigo-500 border-indigo-100",
              node.tag === 'Public' && "bg-emerald-50 text-emerald-500 border-emerald-100", // "公共"
              node.tag === 'Private' && "bg-orange-50 text-orange-500 border-orange-100", // "私有"
            )}>
              {node.tag === 'Public' ? '公共' : node.tag === 'Private' ? '私有' : node.tag}
            </span>
          )}
        </div>

        {node.children && node.expanded && (
          <div>
            {renderTree(node.children, level + 1)}
          </div>
        )}
      </div>
    ))
  }

  return (
    <div className="flex h-full bg-white rounded-xl shadow-sm overflow-hidden border border-slate-100">
      {/* Left Sidebar: Project Directory */}
      <div className="w-[280px] border-r border-slate-100 flex flex-col bg-white">
        <div className="h-14 px-4 border-b border-slate-100 flex items-center justify-between shrink-0">
          <h2 className="font-bold text-slate-800">项目目录</h2>
          <div className="flex items-center gap-1">
            <Button variant="ghost" size="sm" className="h-8 gap-1 text-slate-500 font-normal">
              <Filter className="w-3.5 h-3.5" />
              筛选
            </Button>
          </div>
        </div>

        <div className="flex-1 overflow-y-auto p-2">
          {renderTree(treeData)}
        </div>
      </div>

      {/* Right Content: Details */}
      <div className="flex-1 flex flex-col overflow-hidden bg-white">
        {selectedRepo ? (
          <>
            {/* Header Toolbar */}
            <div className="h-16 border-b border-slate-100 flex items-center justify-between px-6 bg-white shrink-0">
              <div className="flex items-center gap-2 text-sm text-slate-500">
                {/* Breadcrumb Mock based on selected tree item */}
                <span className="font-medium text-slate-800 text-lg">
                  物理仿真项目 / {selectedTreeId === 'proj-optics' ? '光学实验仿真' : selectedRepo.name}
                </span>
              </div>

              <div className="flex items-center gap-3">
                <Button variant="ghost" className="gap-2 h-9 text-slate-600 hover:text-[#0e7490] hover:bg-[#e0f2fe]"
                  onClick={() => window.location.hash = '#/app/projects/new'}
                >
                  <Plus className="w-4 h-4" />
                  新建项目
                </Button>
                <Button variant="ghost" className="gap-2 h-9 text-slate-600 hover:text-[#0e7490] hover:bg-[#e0f2fe]"
                  onClick={handleDownloadProject}
                >
                  <ArrowDownToLine className="w-4 h-4" />
                  下载项目
                </Button>
                <Button
                  variant="ghost"
                  className="gap-2 h-9 text-slate-600 hover:text-[#0e7490] hover:bg-[#e0f2fe]"
                  onClick={handleGitSync}
                >
                  <GitCommitHorizontal className="w-4 h-4" />
                  Git同步
                </Button>
              </div>
            </div>

            <div className="flex-1 overflow-y-auto p-6 space-y-6">
              {/* Info Banner */}
              <div className="bg-slate-50/80 rounded-sm p-6 grid grid-cols-3 gap-8 text-sm shrink-0 border-0">

                <div className="space-y-2">
                  <div className="text-slate-400 text-xs flex items-center gap-1">
                    <GitBranch className="w-3 h-3" />
                    分支
                  </div>
                  <div className="relative">
                    <div
                      className="flex items-center gap-2 cursor-pointer hover:bg-slate-200/50 rounded p-1 -ml-1 transition-colors"
                      onClick={() => setIsBranchDropdownOpen(!isBranchDropdownOpen)}
                    >
                      <span className="text-slate-700 font-medium">{selectedBranch || 'Loading...'}</span>
                      <ChevronsUpDown className="w-3 h-3 text-slate-400" />
                    </div>

                    {/* Branch Dropdown */}
                    {isBranchDropdownOpen && (
                      <>
                        <div
                          className="fixed inset-0 z-10"
                          onClick={() => setIsBranchDropdownOpen(false)}
                        />
                        <div className="absolute top-full left-0 mt-1 w-56 max-h-60 overflow-y-auto bg-white border border-slate-200 rounded-md shadow-lg z-20 py-1">
                          {branches.map((branch) => (
                            <div
                              key={branch.name}
                              className={cn(
                                "px-3 py-2 text-sm flex items-center justify-between cursor-pointer hover:bg-slate-50",
                                selectedBranch === branch.name && "bg-cyan-50 text-[#0e7490]"
                              )}
                              onClick={() => {
                                setSelectedBranch(branch.name)
                                setIsBranchDropdownOpen(false)
                              }}
                            >
                              <div className="flex items-center gap-2">
                                <GitBranch className="w-3.5 h-3.5 opacity-70" />
                                <span>{branch.name}</span>
                              </div>
                              {selectedBranch === branch.name && <Check className="w-3.5 h-3.5" />}
                            </div>
                          ))}
                        </div>
                      </>
                    )}
                  </div>
                </div>

                <div className="space-y-2">
                  <div className="text-slate-400 text-xs">最后提交</div>
                  <div className="text-slate-700 font-medium truncate">
                    {commitsLoading ? (
                      <span className="text-slate-400 italic">加载中...</span>
                    ) : commits.length > 0 ? (
                      <div className="flex flex-col">
                        <span className="truncate" title={`${commits[0].commit.message} (${commits[0].sha.substring(0, 7)})`}>
                          {commits[0].commit.message}
                          <span className="ml-2 font-mono text-[10px] text-[#0e7490] bg-cyan-50 px-1 rounded">
                            {commits[0].sha.substring(0, 7)}
                          </span>
                        </span>
                        <span className="text-[10px] text-slate-400 mt-0.5">
                          {new Date(commits[0].commit.author.date).toLocaleString()}
                        </span>
                      </div>
                    ) : (
                      <span className="text-slate-400 italic">暂无记录</span>
                    )}
                  </div>
                </div>

                <div className="space-y-2">
                  <div className="text-slate-400 text-xs">克隆/拉取命令</div>
                  <div className="text-slate-700 font-medium break-all select-all">
                    git clone {selectedRepo.clone_url}
                  </div>
                </div>
              </div>

              {/* 缓存进度条 */}
              {isCaching && (
                <div className="bg-blue-50 border border-blue-100 rounded-lg p-4 animate-in fade-in duration-300">
                  <div className="flex items-center justify-between mb-2">
                    <span className="text-sm font-medium text-blue-700">{cacheProgress.status}</span>
                    <span className="text-xs text-blue-500">
                      {cacheProgress.total > 0 ? `${Math.round((cacheProgress.current / cacheProgress.total) * 100)}%` : ''}
                    </span>
                  </div>
                  <div className="w-full bg-blue-100 rounded-full h-2">
                    <div
                      className="bg-blue-500 h-2 rounded-full transition-all duration-300"
                      style={{ width: cacheProgress.total > 0 ? `${(cacheProgress.current / cacheProgress.total) * 100}%` : '0%' }}
                    />
                  </div>
                </div>
              )}

              {/* 同步结果提示 */}
              {syncResult && !isCaching && (
                <div className="bg-emerald-50 border border-emerald-100 rounded-lg p-4 animate-in fade-in duration-300">
                  <div className="flex items-center gap-4 text-sm">
                    <span className="font-medium text-emerald-700">同步完成</span>
                    <div className="flex items-center gap-3 text-emerald-600">
                      {syncResult.added.length > 0 && (
                        <span className="flex items-center gap-1">
                          <span className="w-2 h-2 bg-green-500 rounded-full"></span>
                          新增 {syncResult.added.length} 个
                        </span>
                      )}
                      {syncResult.modified.length > 0 && (
                        <span className="flex items-center gap-1">
                          <span className="w-2 h-2 bg-amber-500 rounded-full"></span>
                          更新 {syncResult.modified.length} 个
                        </span>
                      )}
                      {syncResult.deleted.length > 0 && (
                        <span className="flex items-center gap-1">
                          <span className="w-2 h-2 bg-red-500 rounded-full"></span>
                          删除 {syncResult.deleted.length} 个
                        </span>
                      )}
                      <span className="text-slate-400">
                        未变化 {syncResult.unchanged} 个
                      </span>
                    </div>
                  </div>
                </div>
              )}

              {/* Git提交记录 */}
              <div className="space-y-3">
                <h3 className="font-bold text-slate-800 flex items-center gap-2">
                  <GitCommitHorizontal className="w-4 h-4 text-[#0e7490]" />
                  Git提交记录
                </h3>
                <div className="bg-slate-50 border border-slate-100 rounded-lg divide-y divide-slate-100 max-h-[420px] overflow-y-auto">
                  {commitsLoading ? (
                    <div className="p-4 text-sm text-slate-400 text-center">加载提交记录中...</div>
                  ) : commits.length === 0 ? (
                    <div className="p-4 text-sm text-slate-400 text-center">暂无提交记录</div>
                  ) : (
                    commits.map((commit) => (
                      <div key={commit.sha} className="p-4 hover:bg-white transition-colors">
                        <div className="flex items-start justify-between gap-4">
                          <div className="space-y-1">
                            <div className="font-medium text-sm text-slate-700">{commit.commit.message}</div>
                            <div className="flex items-center gap-3 text-xs text-slate-400">
                              <div className="flex items-center gap-1">
                                <User className="w-3 h-3" />
                                {commit.commit.author.name}
                              </div>
                              <div className="flex items-center gap-1">
                                <Calendar className="w-3 h-3" />
                                {new Date(commit.commit.author.date).toLocaleString()}
                              </div>
                            </div>
                          </div>
                          <div className="font-mono text-xs text-[#0e7490] bg-cyan-50 px-2 py-1 rounded">
                            {commit.sha.substring(0, 7)}
                          </div>
                        </div>
                      </div>
                    ))
                  )}
                </div>
              </div>

              {/* File List */}


              <div className="space-y-3">
                <div className="flex items-center justify-between">
                  <h3 className="font-bold text-slate-800 flex items-center gap-2">
                    <Folder className="w-4 h-4 text-[#0e7490]" />
                    项目文件列表
                  </h3>

                  {/* Breadcrumbs */}
                  <div className="flex items-center text-sm bg-slate-50 px-3 py-1 rounded-md border border-slate-100">
                    <button
                      onClick={() => setCurrentPath([])}
                      className={cn("hover:text-[#0e7490] flex items-center gap-1", currentPath.length === 0 ? "font-bold text-[#0e7490]" : "text-slate-500")}
                    >
                      <Home className="w-3.5 h-3.5" />
                      Root
                    </button>
                    {currentPath.map((folder, index) => (
                      <div key={index} className="flex items-center">
                        <ChevronRight className="w-3 h-3 text-slate-300 mx-1" />
                        <button
                          onClick={() => handleBreadcrumbClick(index)}
                          className={cn(
                            "hover:text-[#0e7490]",
                            index === currentPath.length - 1 ? "font-bold text-[#0e7490]" : "text-slate-500"
                          )}
                        >
                          {folder}
                        </button>
                      </div>
                    ))}
                  </div>
                </div>

                <div className="border border-slate-200 rounded-lg overflow-hidden bg-white">
                  {currentPath.length > 0 && (
                    <div
                      className="px-4 py-2 bg-slate-50 border-b border-slate-100 text-slate-500 text-sm hover:bg-slate-100 cursor-pointer flex items-center gap-2"
                      onClick={handleNavigateUp}
                    >
                      <ArrowLeft className="w-4 h-4" />
                      <span>返回上一级</span>
                    </div>
                  )}
                  <table className="w-full text-sm text-left">
                    <thead className="bg-slate-50 text-slate-500 border-b border-slate-200">
                      <tr>
                        <th className="px-4 py-3 font-medium w-[40%]">文件名</th>
                        <th className="px-4 py-3 font-medium">大小</th>
                        <th className="px-4 py-3 font-medium">类型</th>
                        <th className="px-4 py-3 font-medium text-right">操作</th>
                      </tr>
                    </thead>
                    <tbody>
                      {loading && files.length === 0 ? (
                        <tr>
                          <td colSpan={4} className="px-4 py-8 text-center text-slate-400">
                            加载中...
                          </td>
                        </tr>
                      ) : files.length === 0 ? (
                        <tr>
                          <td colSpan={4} className="px-4 py-8 text-center text-slate-400">
                            暂无文件
                          </td>
                        </tr>
                      ) : (
                        files.map((file) => (
                          <tr
                            key={file.path}
                            onClick={() => handleFileClick(file)}
                            className={cn(
                              "border-b border-slate-100 last:border-0 hover:bg-slate-50 transition-colors cursor-pointer group",
                              selectedFile?.path === file.path ? "bg-slate-50" : ""
                            )}
                          >
                            <td className="px-4 py-3">
                              <div className="flex items-center gap-2">
                                {file.type === 'dir' ? (
                                  <Folder className="w-4 h-4 text-[#0e7490] fill-[#0e7490]/20" />
                                ) : (
                                  getFileExtension(file.name) === 'ts' || getFileExtension(file.name) === 'tsx' || getFileExtension(file.name) === 'js' ? (
                                    <FileCode className="w-4 h-4 text-emerald-500" />
                                  ) : (
                                    <FileText className="w-4 h-4 text-slate-400" />
                                  )
                                )}
                                <span className={cn("font-medium", selectedFile?.path === file.path ? "text-[#0e7490]" : "text-slate-700")}>
                                  {file.name}
                                </span>
                              </div>
                            </td>
                            <td className="px-4 py-3 text-slate-500 font-mono text-xs">
                              {file.type === 'dir' ? '-' : formatBytes(file.size)}
                            </td>
                            <td className="px-4 py-3 text-slate-500 text-xs">
                              {file.type === 'dir' ? '文件夹' : '文件'}
                            </td>
                            <td className="px-4 py-3 text-right">
                              <Button variant="ghost" size="icon" className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity">
                                <MoreHorizontal className="w-4 h-4 text-slate-400" />
                              </Button>
                            </td>
                          </tr>
                        ))
                      )}
                    </tbody>
                  </table>
                </div>
              </div>

              {/* Code Editor Area (Collapsible, Now Below File List) */}
              {isEditorVisible && selectedFile && (
                <div className="space-y-3 animate-in fade-in slide-in-from-top-4 duration-300">
                  <div className="flex items-center justify-between">
                    <h3 className="font-bold text-slate-800 flex items-center gap-2">
                      <FileCode className="w-4 h-4 text-[#0e7490]" />
                      代码预览: {selectedFile.name}
                    </h3>
                    <div className="flex items-center gap-2">
                      <Button variant="outline" size="sm" className="h-7 text-xs">
                        历史记录
                      </Button>
                      <Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => setIsEditorVisible(false)}>
                        <ChevronDown className="w-4 h-4" />
                      </Button>
                    </div>
                  </div>

                  <div className="rounded-lg border border-slate-200 overflow-visible shadow-sm relative group">
                    <div className="absolute right-4 top-4 z-10 opacity-0 group-hover:opacity-100 transition-opacity">
                      <Button variant="secondary" size="sm" className="h-8 text-xs shadow-sm bg-white/90 backdrop-blur">
                        <Copy className="w-3.5 h-3.5 mr-1" />
                        复制
                      </Button>
                    </div>

                    {loading ? (
                      <div className="h-[400px] flex items-center justify-center bg-[#1e1e1e] text-slate-400">
                        加载中...
                      </div>
                    ) : (
                      <SyntaxHighlighter
                        language={getFileExtension(selectedFile.name)}
                        style={vscDarkPlus}
                        customStyle={{
                          margin: 0,
                          padding: '1.5rem',
                          height: 'auto',
                          minHeight: 'auto',
                          fontSize: '14px',
                          lineHeight: '1.5',
                          overflow: 'visible',
                          overflowY: 'visible',
                          overflowX: 'visible',
                          whiteSpace: 'pre-wrap',
                          wordBreak: 'break-word',
                        }}
                        showLineNumbers={true}
                        PreTag="div"
                        wrapLines={true}
                        wrapLongLines={true}
                      >
                        {fileContent}
                      </SyntaxHighlighter>
                    )}
                  </div>
                </div>
              )}
            </div>
          </>
        ) : (
          <div className="flex-1 flex flex-col items-center justify-center text-slate-400">
            <Folder className="w-16 h-16 mb-4 text-slate-200" />
            <p>请选择一个项目以查看详情</p>
          </div>
        )}
      </div>
    </div>
  )
}
