import { useState, useEffect, useRef, useMemo } from 'react'
import { useParams, useSearchParams } from 'react-router-dom'
import { Layout, Menu, Spin, FloatButton, Button, Modal, Input, message, Drawer, Anchor, Empty } from 'antd'
import { VerticalAlignTopOutlined, MenuOutlined, MenuFoldOutlined, MenuUnfoldOutlined, FileTextOutlined, FolderOutlined, FilePdfOutlined, LockOutlined, SearchOutlined } from '@ant-design/icons'
import { Viewer } from '@bytemd/react'
import gfm from '@bytemd/plugin-gfm'
import highlight from '@bytemd/plugin-highlight'
import breaks from '@bytemd/plugin-breaks'
import frontmatter from '@bytemd/plugin-frontmatter'
import gemoji from '@bytemd/plugin-gemoji'
import 'bytemd/dist/index.css'
import rehypeSlug from 'rehype-slug'
import 'highlight.js/styles/github.css'
import Mark from 'mark.js'
import Highlighter from 'react-highlight-words'
import GithubSlugger from 'github-slugger'
import { getPreviewInfo, getPreviewTree, getPreviewFile, verifyAccessPassword, getPreviewDocumentUrl } from '@/api/share'
import { searchDocuments } from '@/api/search'
import VirtualPDFViewer from '@/components/PDFViewer/VirtualPDFViewer'
import './PreviewPage.css'

const { Sider, Content } = Layout

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

function PreviewPage() {
  const { projectId } = useParams()
  const [searchParams] = useSearchParams()
  const [projectInfo, setProjectInfo] = useState(null)
  const [fileTree, setFileTree] = useState([])
  const [selectedFile, setSelectedFile] = useState('')
  const [markdownContent, setMarkdownContent] = useState('')
  const [loading, setLoading] = useState(false)
  const [openKeys, setOpenKeys] = useState([])
  const [tocCollapsed, setTocCollapsed] = useState(false)
  const [tocItems, setTocItems] = useState([])
  const [passwordModalVisible, setPasswordModalVisible] = useState(false)
  const [password, setPassword] = useState('')
  const [accessPassword, setAccessPassword] = useState(null)
  const [siderCollapsed, setSiderCollapsed] = useState(false)
  const [mobileDrawerVisible, setMobileDrawerVisible] = useState(false)
  const [isMobile, setIsMobile] = useState(false)
  const [pdfViewerVisible, setPdfViewerVisible] = useState(false)
  const [pdfUrl, setPdfUrl] = useState('')
  const [pdfFilename, setPdfFilename] = useState('')
  const [viewMode, setViewMode] = useState('markdown')
  
  // 搜索相关
  const [searchKeyword, setSearchKeyword] = useState('')
  const [matchedFilePaths, setMatchedFilePaths] = useState(new Set())
  const [isSearching, setIsSearching] = useState(false)

  const contentRef = useRef(null)
  const viewerRef = useRef(null)

  // ByteMD 插件配置
  const plugins = useMemo(() => [
    gfm(),
    highlight(),
    breaks(),
    frontmatter(),
    gemoji(),
    {
      rehype: (p) => p.use(rehypeSlug)
    }
  ], [])

  // mark.js 高亮
  useEffect(() => {
    if (viewerRef.current && viewMode === 'markdown') {
      const instance = new Mark(viewerRef.current)
      instance.unmark()
      
      if (searchKeyword.trim()) {
        instance.mark(searchKeyword, {
          element: 'span',
          className: 'search-highlight',
          exclude: ['pre', 'code', '.toc-content']
        })
      }
    }
  }, [markdownContent, searchKeyword, viewMode])

  // 检测是否为移动设备
  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 768)
    }
    checkMobile()
    window.addEventListener('resize', checkMobile)
    return () => window.removeEventListener('resize', checkMobile)
  }, [])

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

  // 加载项目基本信息
  const loadProjectInfo = async () => {
    try {
      const res = await getPreviewInfo(projectId)
      const info = res.data
      setProjectInfo(info)

      if (info.has_password) {
        setPasswordModalVisible(true)
      } else {
        loadFileTree()
      }
    } catch (error) {
      console.error('Load project info error:', error)
      message.error('项目不存在或已被删除')
    }
  }

  // 验证密码
  const handleVerifyPassword = async () => {
    if (!password.trim()) {
      message.warning('请输入访问密码')
      return
    }

    try {
      await verifyAccessPassword(projectId, password)
      setAccessPassword(password)
      setPasswordModalVisible(false)
      loadFileTree(password)
      message.success('验证成功')
    } catch (error) {
      message.error('访问密码错误')
    }
  }

  // 加载文件树
  const loadFileTree = async (pwd = null) => {
    try {
      const res = await getPreviewTree(projectId, pwd || accessPassword)
      const tree = res.data || []
      setFileTree(tree)

      const readmeNode = findReadme(tree)
      
      // Check query params
      const fileParam = searchParams.get('file')
      const keywordParam = searchParams.get('keyword')

      if (keywordParam) {
        handleSearch(keywordParam)
      }

      if (fileParam) {
        // Deep link to file
        if (fileParam.toLowerCase().endsWith('.pdf')) {
           let url = getPreviewDocumentUrl(projectId, fileParam)
           // ... params logic repeated from handleMenuClick ...
           // Simplify: just call logic or set state
           // Since we need token/password logic, let's reuse handleMenuClick logic if possible or copy it.
           // For simplicity, just set selection and let user click? No, auto load.
           
           // Copy logic for PDF url construction
           const params = []
           if (pwd || accessPassword) params.push(`access_pass=${encodeURIComponent(pwd || accessPassword)}`)
           const token = localStorage.getItem('access_token')
           if (token) params.push(`token=${encodeURIComponent(token)}`)
           if (params.length > 0) url += `?${params.join('&')}`
           
           setSelectedFile(fileParam)
           setPdfUrl(url)
           setPdfFilename(fileParam.split('/').pop())
           setViewMode('pdf')
        } else {
           setSelectedFile(fileParam)
           loadMarkdown(fileParam, pwd || accessPassword)
        }
        
        // Expand tree to file
        const parts = fileParam.split('/')
        const allParentPaths = []
        let currentPath = ''
        for (let i = 0; i < parts.length - 1; i++) {
          currentPath = currentPath ? `${currentPath}/${parts[i]}` : parts[i]
          allParentPaths.push(currentPath)
        }
        setOpenKeys(prev => [...new Set([...prev, ...allParentPaths])])

      } else if (readmeNode) {
        setSelectedFile(readmeNode.key)
        loadMarkdown(readmeNode.key, pwd || accessPassword)
      }
    } catch (error) {
      console.error('Load file tree error:', error)
      if (error.response?.status === 403) {
        message.error('访问密码错误或已过期')
        setPasswordModalVisible(true)
      }
    }
  }

  // 搜索处理
  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)
      
      // 自动展开匹配的节点 (Assuming this comment might be there or not, better context: keysToExpand)
      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 findReadme = (nodes) => {
    for (const node of nodes) {
      if (node.title === 'README.md' && node.isLeaf) {
        return node
      }
    }
    return null
  }

  const convertTreeToMenuItems = (nodes) => {
    return nodes.map((node) => {
      const labelNode = node.title.replace('.md', '')
      
      if (!node.isLeaf) {
        return {
          key: node.key,
          label: node.title,
          icon: <FolderOutlined />,
          children: node.children ? convertTreeToMenuItems(node.children) : [],
        }
      } else if (node.title && node.title.endsWith('.md')) {
        return {
          key: node.key,
          label: labelNode,
          icon: <FileTextOutlined />,
        }
      } else if (node.title && node.title.endsWith('.pdf')) {
        return {
          key: node.key,
          label: node.title,
          icon: <FilePdfOutlined style={{ color: '#f5222d' }} />,
        }
      }
      return null
    }).filter(Boolean)
  }

  const loadMarkdown = async (filePath, pwd = null) => {
    setLoading(true)
    setTocItems([])
    try {
      const res = await getPreviewFile(projectId, filePath, pwd || accessPassword)
      setMarkdownContent(res.data?.content || '')

      if (isMobile) {
        setMobileDrawerVisible(false)
      }

      if (contentRef.current) {
        contentRef.current.scrollTo({ top: 0, behavior: 'smooth' })
      }
    } catch (error) {
      console.error('Load markdown error:', error)
      if (error.response?.status === 403) {
        message.error('访问密码错误或已过期')
        setPasswordModalVisible(true)
      } else {
        setMarkdownContent('# 文档加载失败\n\n无法加载该文档，请稍后重试。')
      }
    } finally {
      setLoading(false)
    }
  }

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

      lines.forEach((line) => {
        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,
          })
        }
      })

      setTocItems(headings)
    }
  }, [markdownContent])

  const resolveRelativePath = (currentPath, relativePath) => {
    if (relativePath.startsWith('/')) {
      return relativePath.substring(1)
    }

    const lastSlashIndex = currentPath.lastIndexOf('/')
    const currentDir = lastSlashIndex !== -1 ? currentPath.substring(0, lastSlashIndex) : ''

    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 handleMarkdownLink = (e, href) => {
    if (!href || href.startsWith('http') || href.startsWith('//') || href.startsWith('#')) {
      return
    }

    const isMd = href.endsWith('.md')
    const isPdf = href.toLowerCase().endsWith('.pdf')

    if (!isMd && !isPdf) return

    e.preventDefault()

    let decodedHref = href
    try {
      decodedHref = decodeURIComponent(href)
    } catch (err) {
    }

    const targetPath = resolveRelativePath(selectedFile, decodedHref)

    const lastSlashIndex = targetPath.lastIndexOf('/')
    const parentPath = lastSlashIndex !== -1 ? 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])])
    }

    handleMenuClick({ key: targetPath })
  }

  const handleContentClick = (e) => {
    const target = e.target.closest('a')
    if (target) {
      const href = target.getAttribute('href')
      if (href) {
        handleMarkdownLink(e, href)
      }
    }
  }

  const handleMenuClick = ({ key }) => {
    setSelectedFile(key)

    if (key.toLowerCase().endsWith('.pdf')) {
      let url = getPreviewDocumentUrl(projectId, key)
      const params = []

      if (accessPassword) {
        params.push(`access_pass=${encodeURIComponent(accessPassword)}`)
      }

      const token = localStorage.getItem('access_token')
      if (token) {
        params.push(`token=${encodeURIComponent(token)}`)
      }

      if (params.length > 0) {
        url += `?${params.join('&')}`
      }

      setPdfUrl(url)
      setPdfFilename(key.split('/').pop())
      setViewMode('pdf')
    } else {
      setViewMode('markdown')
      loadMarkdown(key)
    }
  }

  const menuItems = convertTreeToMenuItems(filteredTreeData)

  return (
    <div className="preview-page">
      <Layout className="preview-layout">
        {isMobile ? (
          <>
            <Button
              type="primary"
              icon={<MenuOutlined />}
              className="mobile-menu-btn"
              onClick={() => setMobileDrawerVisible(true)}
            >
              目录索引
            </Button>
            <Drawer
              title={
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <img src="/favicon.svg" alt="logo" style={{ width: 24, height: 24 }} />
                  <span>{projectInfo?.name || '项目预览'}</span>
                </div>
              }
              placement="left"
              onClose={() => setMobileDrawerVisible(false)}
              open={mobileDrawerVisible}
              width="80%"
            >
              <div className="preview-sider-header" style={{ padding: '0 0 16px' }}>
                {projectInfo?.description && (
                  <p className="preview-project-desc">{projectInfo.description}</p>
                )}
              </div>
              
              {/* 搜索框 */}
              <div style={{ padding: '0 0 12px' }}>
                <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={[selectedFile]}
                  openKeys={openKeys}
                  onOpenChange={setOpenKeys}
                  items={menuItems}
                  onClick={handleMenuClick}
                  className="preview-menu"
                />
              ) : (
                <div style={{ padding: '20px', textAlign: 'center', color: '#999' }}>
                  <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="未找到匹配文档" />
                </div>
              )}
            </Drawer>
          </>
        ) : (
          <Sider
            width={280}
            className="preview-sider"
            theme="light"
            collapsed={siderCollapsed}
            collapsedWidth={0}
          >
            <div className="preview-sider-header">
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                <img src="/favicon.svg" alt="logo" style={{ width: 24, height: 24 }} />
                <h2 style={{ margin: 0 }}>{projectInfo?.name || '项目预览'}</h2>
              </div>
              {projectInfo?.description && (
                <p className="preview-project-desc">{projectInfo.description}</p>
              )}
            </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={[selectedFile]}
                openKeys={openKeys}
                onOpenChange={setOpenKeys}
                items={menuItems}
                onClick={handleMenuClick}
                className="preview-menu"
              />
            ) : (
              <div style={{ padding: '20px', textAlign: 'center', color: '#999' }}>
                <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="未找到匹配文档" />
              </div>
            )}
          </Sider>
        )}

        <Layout className="preview-content-layout">
          <Content className="preview-content" ref={contentRef}>
            <div className={`preview-content-wrapper ${viewMode === 'pdf' ? 'pdf-mode' : ''}`}>
              {loading ? (
                <div className="preview-loading">
                  <Spin size="large">
                    <div style={{ marginTop: 16 }}>加载中...</div>
                  </Spin>
                </div>
              ) : viewMode === 'pdf' ? (
                <VirtualPDFViewer
                  url={pdfUrl}
                  filename={pdfFilename}
                />
              ) : (
                <div className="markdown-body" onClick={handleContentClick} ref={viewerRef}>
                  <Viewer
                    value={markdownContent}
                    plugins={plugins}
                  />
                </div>
              )}
            </div>

            {viewMode === 'markdown' && (
              <FloatButton
                icon={<VerticalAlignTopOutlined />}
                type="primary"
                style={{ right: tocCollapsed || isMobile ? 24 : 280 }}
                onClick={() => {
                  if (contentRef.current) {
                    contentRef.current.scrollTo({ top: 0, behavior: 'smooth' })
                  }
                }}
              />
            )}
          </Content>

          {!isMobile && viewMode === 'markdown' && !tocCollapsed && (
            <Sider width={250} theme="light" className="preview-toc-sider">
              <div className="toc-header">
                <h3>文档索引</h3>
                <Button
                  type="text"
                  size="small"
                  icon={<MenuFoldOutlined />}
                  onClick={() => setTocCollapsed(true)}
                />
              </div>
              <div className="toc-content">
                {tocItems.length > 0 ? (
                  <Anchor
                    affix={false}
                    offsetTop={0}
                    getContainer={() => contentRef.current}
                    items={tocItems.map((item) => ({
                      key: item.key,
                      href: item.href,
                      title: (
                        <div style={{ paddingLeft: `${(item.level - 1) * 12}px`, display: 'flex', alignItems: 'center', gap: '4px' }}>
                          <FileTextOutlined style={{ fontSize: '12px', color: '#8c8c8c' }} />
                          <HighlightText text={item.title} keyword={searchKeyword} />
                        </div>
                      ),
                    }))}
                  />
                ) : (
                  <div className="toc-empty">当前文档无标题</div>
                )}
              </div>
            </Sider>
          )}
        </Layout>

        {!isMobile && tocCollapsed && (
          <Button
            type="primary"
            icon={<MenuUnfoldOutlined />}
            className="toc-toggle-btn"
            onClick={() => setTocCollapsed(false)}
          >
            文档索引
          </Button>
        )}
      </Layout>

      <Modal
        title={
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <LockOutlined />
            <span>访问验证</span>
          </div>
        }
        open={passwordModalVisible}
        onOk={handleVerifyPassword}
        onCancel={() => setPasswordModalVisible(false)}
        okText="验证"
        cancelText="取消"
        maskClosable={false}
      >
        <div style={{ marginTop: 16 }}>
          <p>该项目需要访问密码，请输入密码后继续浏览。</p>
          <Input.Password
            placeholder="请输入访问密码"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            onPressEnter={handleVerifyPassword}
            prefix={<LockOutlined />}
          />
        </div>
      </Modal>
    </div>
  )
}

export default PreviewPage