import React, { useState } from 'react'
import { clsx } from 'clsx'
import type { DocFile } from '@/lib/types'
import { getDisplayName } from '@/lib/parser'

interface DocTreeProps {
  files: DocFile[]
  selectedPath?: string
  onSelect: (file: DocFile) => void
}

interface TreeNodeProps {
  file: DocFile
  level: number
  isLast: boolean
  ancestorsLast: boolean[]
  selectedPath?: string
  onSelect: (file: DocFile) => void
  expandedSet: Set<string>
  onToggle: (path: string) => void
}

const TreeNode = React.memo(({
  file,
  level,
  isLast,
  ancestorsLast,
  selectedPath,
  onSelect,
  expandedSet,
  onToggle,
}: TreeNodeProps) => {
  const isDir = file.isDir
  const isExpanded = expandedSet.has(file.relativePath)
  const isSelected = selectedPath === file.relativePath

  const handleClick = () => {
    if (isDir) {
      onToggle(file.relativePath)
    } else {
      onSelect(file)
    }
  }

  const renderIndent = () => {
    const parts: React.ReactNode[] = []
    
    for (let i = 0; i < level; i++) {
      const showLine = !ancestorsLast[i]
      parts.push(
        <span key={i} className="inline-block w-4 text-center text-zinc-600">
          {showLine ? '│' : ' '}
        </span>
      )
    }
    
    const connector = isLast ? '└──' : '├──'
    parts.push(
      <span key="connector" className="text-zinc-500">
        {connector}
      </span>
    )
    
    return parts
  }

  const showChildren = isDir && isExpanded && file.children

  return (
    <>
      <div
        onClick={handleClick}
        className={clsx(
          'flex items-center py-1 cursor-pointer text-sm select-none rounded',
          isDir
            ? 'text-zinc-400 hover:text-zinc-200'
            : isSelected
              ? 'text-blue-400'
              : 'text-zinc-400 hover:text-zinc-200'
        )}
      >
        <span className="font-mono text-xs leading-none">
          {renderIndent()}
        </span>
        <span className={clsx(
          'ml-1 truncate',
          isDir && 'font-medium'
        )}>
          {getDisplayName(file.name)}
        </span>
      </div>

      {showChildren && file.children!.map((child, idx) => (
        <TreeNode
          key={child.relativePath}
          file={child}
          level={level + 1}
          isLast={idx === file.children!.length - 1}
          ancestorsLast={[...ancestorsLast, isLast]}
          selectedPath={selectedPath}
          onSelect={onSelect}
          expandedSet={expandedSet}
          onToggle={onToggle}
        />
      ))}
    </>
  )
})

TreeNode.displayName = 'TreeNode'

export const DocTree = ({ files, selectedPath, onSelect }: DocTreeProps) => {
  const [expandedSet, setExpandedSet] = useState<Set<string>>(() => {
    const set = new Set<string>()
    files.forEach(f => {
      if (f.isDir) set.add(f.relativePath)
    })
    return set
  })

  const handleToggle = (path: string) => {
    setExpandedSet(prev => {
      const next = new Set(prev)
      if (next.has(path)) {
        next.delete(path)
      } else {
        next.add(path)
      }
      return next
    })
  }

  return (
    <div className="select-none w-full h-full overflow-auto py-2 px-1">
      {files.map((file, idx) => (
        <TreeNode
          key={file.relativePath}
          file={file}
          level={0}
          isLast={idx === files.length - 1}
          ancestorsLast={[]}
          selectedPath={selectedPath}
          onSelect={onSelect}
          expandedSet={expandedSet}
          onToggle={handleToggle}
        />
      ))}
    </div>
  )
}
