import { useEffect, useState, useRef } from 'react'
import { listFiles, downloadFile, uploadFile, readFile, writeFile, mkdirFile, renameFile, deleteFile } from '../api/client'
import { Folder, File, ArrowLeft, Download, Loader2, Upload, Edit2, FolderPlus, Trash2, Pencil, Check } from 'lucide-react'

interface FileItem {
  name: string
  is_dir: boolean
  size: number
}

function formatSize(bytes: number): string {
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / 1024 / 1024).toFixed(1) + ' MB'
}

const TEXT_EXT = ['.txt', '.html', '.htm', '.css', '.js', '.json', '.xml', '.md', '.py', '.php', '.sh', '.conf', '.env']

export function FilesPage() {
  const [path, setPath] = useState('/')
  const [items, setItems] = useState<FileItem[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')
  const [downloading, setDownloading] = useState<string | null>(null)
  const [uploading, setUploading] = useState(false)
  const [editingFile, setEditingFile] = useState<string | null>(null)
  const [editContent, setEditContent] = useState('')
  const [savingEdit, setSavingEdit] = useState(false)
  const [showMkdir, setShowMkdir] = useState(false)
  const [mkdirName, setMkdirName] = useState('')
  const [renaming, setRenaming] = useState<FileItem | null>(null)
  const [renameValue, setRenameValue] = useState('')
  const fileInputRef = useRef<HTMLInputElement>(null)

  const loadDir = (p: string) => {
    setLoading(true)
    setError('')
    listFiles(p)
      .then((data) => {
        setPath(data.path)
        setItems(data.items.sort((a, b) => (a.is_dir === b.is_dir ? 0 : a.is_dir ? -1 : 1)))
      })
      .catch((err) => setError(err.message))
      .finally(() => setLoading(false))
  }

  useEffect(() => {
    loadDir(path)
  }, [])

  const handleNavigate = (item: FileItem) => {
    if (item.is_dir) {
      const newPath = path.endsWith('/') ? path + item.name : path + '/' + item.name
      loadDir(newPath)
    }
  }

  const handleBack = () => {
    const parts = path.replace(/\/$/, '').split('/').filter(Boolean)
    if (parts.length <= 1) return
    parts.pop()
    const newPath = parts.length === 0 ? '/' : '/' + parts.join('/')
    loadDir(newPath)
  }

  const handleDownload = (item: FileItem) => {
    if (item.is_dir) return
    const fullPath = path.endsWith('/') ? path + item.name : path + '/' + item.name
    setDownloading(item.name)
    downloadFile(fullPath)
      .catch((err) => setError(err.message))
      .finally(() => setDownloading(null))
  }

  const handleUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return
    setUploading(true)
    setError('')
    uploadFile(path, file)
      .then(() => loadDir(path))
      .catch((err) => setError(err.message))
      .finally(() => {
        setUploading(false)
        e.target.value = ''
      })
  }

  const handleEdit = (item: FileItem) => {
    const fullPath = path.endsWith('/') ? path + item.name : path + '/' + item.name
    readFile(fullPath)
      .then((data) => {
        setEditingFile(fullPath)
        setEditContent(typeof data.content === 'string' ? data.content : String(data.content))
      })
      .catch((err) => setError(err.message))
  }

  const handleSaveEdit = () => {
    if (!editingFile) return
    setSavingEdit(true)
    writeFile(editingFile, editContent)
      .then(() => {
        setEditingFile(null)
        loadDir(path)
      })
      .catch((err) => setError(err.message))
      .finally(() => setSavingEdit(false))
  }

  const canEdit = (name: string) => TEXT_EXT.some((ext) => name.toLowerCase().endsWith(ext))

  const handleMkdir = (e: React.FormEvent) => {
    e.preventDefault()
    const name = mkdirName.trim()
    if (!name) return
    mkdirFile(path, name)
      .then(() => {
        setShowMkdir(false)
        setMkdirName('')
        loadDir(path)
      })
      .catch((err) => setError(err.message))
  }

  const handleRename = () => {
    if (!renaming || !renameValue.trim()) return
    const newName = renameValue.trim()
    if (newName === renaming.name) {
      setRenaming(null)
      return
    }
    renameFile(path, renaming.name, newName)
      .then(() => {
        setRenaming(null)
        setRenameValue('')
        loadDir(path)
      })
      .catch((err) => setError(err.message))
  }

  const handleDelete = (item: FileItem) => {
    if (!confirm(`Delete ${item.is_dir ? 'folder' : 'file'} "${item.name}"?`)) return
    deleteFile(path, item.name, item.is_dir)
      .then(() => loadDir(path))
      .catch((err) => setError(err.message))
  }

  const breadcrumbs = path.split('/').filter(Boolean)
  const canGoBack = breadcrumbs.length > 0

  return (
    <div>
      <h1 className="text-2xl font-bold mb-4 text-gray-800 dark:text-white">Files</h1>

      <div className="mb-4 flex items-center gap-2 flex-wrap">
        <button
          onClick={handleBack}
          disabled={!canGoBack}
          className="flex items-center gap-1 px-3 py-2 rounded-lg bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          <ArrowLeft className="w-4 h-4" />
          Back
        </button>
        <input
          ref={fileInputRef}
          type="file"
          className="hidden"
          onChange={handleUpload}
        />
        <button
          onClick={() => setShowMkdir(true)}
          className="flex items-center gap-1 px-3 py-2 rounded-lg bg-green-600 hover:bg-green-700 text-white"
        >
          <FolderPlus className="w-4 h-4" />
          New Folder
        </button>
        <button
          onClick={() => fileInputRef.current?.click()}
          disabled={uploading}
          className="flex items-center gap-1 px-3 py-2 rounded-lg bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50"
        >
          {uploading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Upload className="w-4 h-4" />}
          Upload
        </button>
        <div className="flex items-center gap-1 px-3 py-2 bg-gray-100 dark:bg-gray-700 rounded-lg text-sm">
          <span className="text-gray-500">Path:</span>
          <span className="text-gray-800 dark:text-white font-mono">{path}</span>
        </div>
      </div>

      {showMkdir && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
          <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 w-full max-w-md">
            <h2 className="text-xl font-bold mb-4 text-gray-800 dark:text-white">New Folder</h2>
            <form onSubmit={handleMkdir} className="space-y-4">
              <input
                value={mkdirName}
                onChange={(e) => setMkdirName(e.target.value)}
                placeholder="Folder name"
                className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700"
                autoFocus
              />
              <div className="flex gap-2 justify-end">
                <button type="button" onClick={() => { setShowMkdir(false); setMkdirName('') }} className="px-4 py-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700">
                  Cancel
                </button>
                <button type="submit" className="px-4 py-2 bg-green-600 text-white rounded-lg">Create</button>
              </div>
            </form>
          </div>
        </div>
      )}

      {editingFile && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
          <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] flex flex-col">
            <div className="p-4 border-b dark:border-gray-700 flex justify-between items-center">
              <span className="font-mono text-sm text-gray-600 dark:text-gray-400">{editingFile}</span>
              <div className="flex gap-2">
                <button onClick={() => setEditingFile(null)} className="px-3 py-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700">Cancel</button>
                <button onClick={handleSaveEdit} disabled={savingEdit} className="px-3 py-1 bg-blue-600 text-white rounded disabled:opacity-50">
                  {savingEdit ? 'Saving...' : 'Save'}
                </button>
              </div>
            </div>
            <textarea
              value={editContent}
              onChange={(e) => setEditContent(e.target.value)}
              className="flex-1 p-4 font-mono text-sm bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white resize-none min-h-[400px]"
              spellCheck={false}
            />
          </div>
        </div>
      )}

      {error && (
        <div className="mb-4 p-3 rounded-lg bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300">
          {error}
        </div>
      )}

      <div className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
        {loading ? (
          <div className="p-8 flex justify-center">
            <Loader2 className="w-8 h-8 animate-spin text-gray-400" />
          </div>
        ) : (
          <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
            <thead className="bg-gray-50 dark:bg-gray-700">
              <tr>
                <th className="px-4 py-2 text-left text-sm font-medium text-gray-700 dark:text-gray-300">Name</th>
                <th className="px-4 py-2 text-left text-sm font-medium text-gray-700 dark:text-gray-300">Size</th>
                <th className="px-4 py-2 text-right text-sm font-medium text-gray-700 dark:text-gray-300">Actions</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
              {items.length === 0 ? (
                <tr>
                  <td colSpan={3} className="px-4 py-8 text-center text-gray-500">
                    Empty directory
                  </td>
                </tr>
              ) : (
                items.map((item) => (
                  <tr
                    key={item.name}
                    className="hover:bg-gray-50 dark:hover:bg-gray-700/50"
                  >
                    <td className="px-4 py-2">
                      <button
                        onClick={() => handleNavigate(item)}
                        className="flex items-center gap-2 text-left w-full hover:text-blue-600 dark:hover:text-blue-400"
                      >
                        {item.is_dir ? (
                          <Folder className="w-5 h-5 text-amber-500" />
                        ) : (
                          <File className="w-5 h-5 text-gray-400" />
                        )}
                        <span className="text-gray-900 dark:text-white">{item.name}</span>
                      </button>
                    </td>
                    <td className="px-4 py-2 text-gray-600 dark:text-gray-400">
                      {item.is_dir ? '-' : formatSize(item.size)}
                    </td>
                    <td className="px-4 py-2 text-right">
                      <span className="flex gap-1 justify-end">
                        {renaming?.name === item.name ? (
                          <span className="flex gap-1 items-center">
                            <input
                              value={renameValue}
                              onChange={(e) => setRenameValue(e.target.value)}
                              onKeyDown={(e) => e.key === 'Enter' && handleRename()}
                              className="px-2 py-1 text-sm border rounded w-32"
                              autoFocus
                            />
                            <button onClick={handleRename} className="p-1.5 text-green-600 rounded" title="Save">
                              <Check className="w-4 h-4" />
                            </button>
                            <button onClick={() => { setRenaming(null); setRenameValue('') }} className="p-1.5 text-gray-500 rounded">Cancel</button>
                          </span>
                        ) : (
                          <>
                            <button
                              onClick={() => { setRenaming(item); setRenameValue(item.name) }}
                              className="p-2 text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
                              title="Rename"
                            >
                              <Pencil className="w-4 h-4" />
                            </button>
                            {!item.is_dir && canEdit(item.name) && (
                              <button
                                onClick={() => handleEdit(item)}
                                className="p-2 text-amber-600 hover:bg-amber-50 dark:hover:bg-amber-900/20 rounded"
                                title="Edit"
                              >
                                <Edit2 className="w-4 h-4" />
                              </button>
                            )}
                            {!item.is_dir && (
                              <button
                                onClick={() => handleDownload(item)}
                                disabled={downloading === item.name}
                                className="p-2 text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded disabled:opacity-50"
                                title="Download"
                              >
                                {downloading === item.name ? (
                                  <Loader2 className="w-4 h-4 animate-spin" />
                                ) : (
                                  <Download className="w-4 h-4" />
                                )}
                              </button>
                            )}
                            <button
                              onClick={() => handleDelete(item)}
                              className="p-2 text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded"
                              title="Delete"
                            >
                              <Trash2 className="w-4 h-4" />
                            </button>
                          </>
                        )}
                      </span>
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        )}
      </div>
    </div>
  )
}
