import { useEffect, useRef, useState } from 'react'
import {
  Folder,
  File as FileIcon,
  ChevronRight,
  Upload,
  FolderPlus,
  Trash2,
  Download,
  Pencil,
  Save,
  X,
  RefreshCw,
  Send,
} from 'lucide-react'
import { api, type FileEntry, type Integration, type TransferProgress } from '../lib/api'

const TEXT_PRIMARY = '#E8E6E0'
const TEXT_SECONDARY = '#7A7D85'
const GOLD = '#C8A434'

const cardBase: React.CSSProperties = {
  backgroundColor: 'rgba(10, 10, 12, 0.92)',
  border: '1px solid rgba(200, 164, 52, 0.08)',
  borderRadius: '12px',
  boxShadow: '0 0 20px rgba(200, 164, 52, 0.03)',
}

function inputStyle(): React.CSSProperties {
  return {
    backgroundColor: 'rgba(255,255,255,0.03)',
    border: '1px solid rgba(255,255,255,0.08)',
    borderRadius: '6px',
    padding: '6px 10px',
    color: TEXT_PRIMARY,
    fontSize: '13px',
  }
}

function formatSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`
  const units = ['KB', 'MB', 'GB', 'TB']
  let v = bytes
  let i = -1
  do {
    v /= 1024
    i++
  } while (v >= 1024 && i < units.length - 1)
  return `${v.toFixed(1)} ${units[i]}`
}

function joinPath(dir: string, name: string): string {
  if (dir === '.' || dir === '') return name
  return `${dir.replace(/\/$/, '')}/${name}`
}

export default function Files() {
  const [hosts, setHosts] = useState<Integration[]>([])
  const [integrationId, setIntegrationId] = useState<number | ''>('')
  const [path, setPath] = useState('.')
  const [entries, setEntries] = useState<FileEntry[]>([])
  const [error, setError] = useState<string | null>(null)
  const [loading, setLoading] = useState(false)

  const [editingPath, setEditingPath] = useState<string | null>(null)
  const [editingContent, setEditingContent] = useState('')
  const [editingEncoding, setEditingEncoding] = useState<'utf8' | 'base64'>('utf8')
  const [savingEdit, setSavingEdit] = useState(false)

  const [transferEntry, setTransferEntry] = useState<FileEntry | null>(null)
  const [transferDestId, setTransferDestId] = useState<number | ''>('')
  const [transferDestPath, setTransferDestPath] = useState('.')
  const [transferMove, setTransferMove] = useState(false)
  const [transfers, setTransfers] = useState<TransferProgress[]>([])

  const fileInputRef = useRef<HTMLInputElement | null>(null)

  useEffect(() => {
    api.listIntegrations().then(({ integrations }) => {
      const sshHosts = integrations.filter((i) => i.type === 'ssh')
      setHosts(sshHosts)
      if (sshHosts.length > 0) setIntegrationId(sshHosts[0].id)
    })
  }, [])

  function refresh() {
    if (!integrationId) return
    setLoading(true)
    setError(null)
    api
      .listFiles(integrationId, path)
      .then(({ entries }) => setEntries(entries))
      .catch((err) => setError(err instanceof Error ? err.message : 'Failed to list directory'))
      .finally(() => setLoading(false))
  }

  useEffect(() => {
    refresh()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [integrationId, path])

  function openDirectory(name: string) {
    setPath(joinPath(path, name))
  }

  function goUp() {
    if (path === '.' || path === '') return
    const parts = path.split('/').filter(Boolean)
    parts.pop()
    setPath(parts.length === 0 ? '.' : parts.join('/'))
  }

  async function openFile(name: string) {
    if (!integrationId) return
    const full = joinPath(path, name)
    setError(null)
    try {
      const result = await api.readFile(integrationId, full)
      setEditingPath(full)
      setEditingContent(result.content)
      setEditingEncoding(result.encoding)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to open file')
    }
  }

  async function saveEdit() {
    if (!integrationId || !editingPath) return
    setSavingEdit(true)
    try {
      await api.writeFile(integrationId, editingPath, editingContent, editingEncoding)
      setEditingPath(null)
      refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save file')
    } finally {
      setSavingEdit(false)
    }
  }

  async function handleMkdir() {
    if (!integrationId) return
    const name = prompt('New folder name')
    if (!name) return
    try {
      await api.mkdir(integrationId, joinPath(path, name))
      refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create directory')
    }
  }

  async function handleRename(entry: FileEntry) {
    if (!integrationId) return
    const next = prompt('Rename to', entry.name)
    if (!next || next === entry.name) return
    try {
      await api.renameFile(integrationId, joinPath(path, entry.name), joinPath(path, next))
      refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to rename')
    }
  }

  async function handleDelete(entry: FileEntry) {
    if (!integrationId) return
    if (!confirm(`Delete ${entry.name}?`)) return
    try {
      await api.deleteFile(integrationId, joinPath(path, entry.name), entry.isDirectory)
      refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to delete')
    }
  }

  function handleDownload(entry: FileEntry) {
    if (!integrationId) return
    window.open(api.downloadFileUrl(integrationId, joinPath(path, entry.name)), '_blank')
  }

  async function handleUpload(file: File) {
    if (!integrationId) return
    setError(null)
    try {
      await api.uploadFile(integrationId, path, file)
      refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to upload file')
    }
  }

  function openTransfer(entry: FileEntry) {
    const otherHost = hosts.find((h) => h.id !== integrationId)
    setTransferEntry(entry)
    setTransferDestId(otherHost ? otherHost.id : '')
    setTransferDestPath('.')
    setTransferMove(false)
  }

  async function startTransfer() {
    if (!integrationId || !transferEntry || !transferDestId) return
    setError(null)
    try {
      await api.startTransfer({
        sourceIntegrationId: integrationId,
        destIntegrationId: transferDestId,
        sourcePaths: [joinPath(path, transferEntry.name)],
        destPath: transferDestPath,
        move: transferMove,
      })
      setTransferEntry(null)
      pollTransfers()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to start transfer')
    }
  }

  function pollTransfers() {
    api.listTransfers().then(({ transfers }) => setTransfers(transfers)).catch(() => {})
  }

  useEffect(() => {
    pollTransfers()
    const anyRunning = transfers.some((t) => t.status === 'running')
    const interval = setInterval(pollTransfers, anyRunning ? 1000 : 5000)
    return () => clearInterval(interval)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [transfers.some((t) => t.status === 'running')])

  async function handleCancelTransfer(id: string) {
    try {
      await api.cancelTransfer(id)
      pollTransfers()
    } catch {
      // ignore — status poll will reflect reality
    }
  }

  function hostName(id: number): string {
    return hosts.find((h) => h.id === id)?.name ?? `#${id}`
  }

  const breadcrumbs = path === '.' || path === '' ? [] : path.split('/').filter(Boolean)

  return (
    <div className="p-6 space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold" style={{ color: TEXT_PRIMARY }}>
            Files
          </h1>
          <p className="text-sm" style={{ color: TEXT_SECONDARY }}>
            Browse, edit, and transfer files on your remote SSH hosts.
          </p>
        </div>
        <select
          style={inputStyle()}
          value={integrationId}
          onChange={(e) => {
            setIntegrationId(e.target.value ? Number(e.target.value) : '')
            setPath('.')
          }}
        >
          {hosts.length === 0 && <option value="">No SSH hosts configured</option>}
          {hosts.map((h) => (
            <option key={h.id} value={h.id}>
              {h.name}
            </option>
          ))}
        </select>
      </div>

      {error && (
        <div style={{ color: '#E74C3C', fontSize: '13px' }} className="flex items-center justify-between">
          <span>{error}</span>
          <button onClick={() => setError(null)} style={{ color: TEXT_SECONDARY }}>
            <X size={14} />
          </button>
        </div>
      )}

      <div style={cardBase} className="p-3 space-y-3">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-1 text-sm flex-wrap" style={{ color: TEXT_SECONDARY }}>
            <button onClick={() => setPath('.')} style={{ color: TEXT_PRIMARY }}>
              root
            </button>
            {breadcrumbs.map((part, i) => (
              <span key={i} className="flex items-center gap-1">
                <ChevronRight size={12} />
                <button onClick={() => setPath(breadcrumbs.slice(0, i + 1).join('/'))} style={{ color: TEXT_PRIMARY }}>
                  {part}
                </button>
              </span>
            ))}
          </div>
          <div className="flex items-center gap-2">
            <button onClick={refresh} className="flex items-center gap-1 rounded-md px-3.5 py-1.5 text-xs" style={{ border: '1px solid rgba(200,164,52,0.2)', color: TEXT_PRIMARY }}>
              <RefreshCw size={12} /> Refresh
            </button>
            <button onClick={handleMkdir} className="flex items-center gap-1 rounded-md px-3.5 py-1.5 text-xs" style={{ border: '1px solid rgba(200,164,52,0.2)', color: TEXT_PRIMARY }}>
              <FolderPlus size={12} /> New Folder
            </button>
            <button
              onClick={() => fileInputRef.current?.click()}
              className="flex items-center gap-1 rounded-md px-3.5 py-1.5 text-xs"
              style={{ backgroundColor: GOLD, color: '#0A0A0C' }}
            >
              <Upload size={12} /> Upload
            </button>
            <input
              ref={fileInputRef}
              type="file"
              className="hidden"
              onChange={(e) => {
                const file = e.target.files?.[0]
                if (file) handleUpload(file)
                e.target.value = ''
              }}
            />
          </div>
        </div>

        <table className="w-full text-sm">
          <tbody>
            {path !== '.' && path !== '' && (
              <tr>
                <td colSpan={4} className="py-1.5 cursor-pointer" style={{ color: TEXT_SECONDARY }} onClick={goUp}>
                  ../
                </td>
              </tr>
            )}
            {entries.map((entry) => (
              <tr key={entry.name} className="hover:bg-white/[0.02]">
                <td
                  className="py-1.5 cursor-pointer flex items-center gap-2"
                  style={{ color: TEXT_PRIMARY }}
                  onClick={() => (entry.isDirectory ? openDirectory(entry.name) : openFile(entry.name))}
                >
                  {entry.isDirectory ? <Folder size={14} color={GOLD} /> : <FileIcon size={14} color={TEXT_SECONDARY} />}
                  {entry.name}
                </td>
                <td className="py-1.5 text-right" style={{ color: TEXT_SECONDARY, width: '90px' }}>
                  {entry.isDirectory ? '' : formatSize(entry.size)}
                </td>
                <td className="py-1.5 text-right" style={{ color: TEXT_SECONDARY, width: '70px' }}>
                  {(entry.mode & 0o777).toString(8)}
                </td>
                <td className="py-1.5 text-right" style={{ width: '120px' }}>
                  <div className="flex items-center justify-end gap-2">
                    {!entry.isDirectory && (
                      <button onClick={() => handleDownload(entry)} title="Download" style={{ color: TEXT_SECONDARY }}>
                        <Download size={14} />
                      </button>
                    )}
                    <button
                      onClick={() => openTransfer(entry)}
                      title="Send to another host"
                      disabled={hosts.length < 2}
                      style={{ color: hosts.length < 2 ? '#4A4D55' : TEXT_SECONDARY }}
                    >
                      <Send size={14} />
                    </button>
                    <button onClick={() => handleRename(entry)} title="Rename" style={{ color: TEXT_SECONDARY }}>
                      <Pencil size={14} />
                    </button>
                    <button onClick={() => handleDelete(entry)} title="Delete" style={{ color: '#E74C3C' }}>
                      <Trash2 size={14} />
                    </button>
                  </div>
                </td>
              </tr>
            ))}
            {entries.length === 0 && !loading && (
              <tr>
                <td colSpan={4} className="py-4 text-center" style={{ color: TEXT_SECONDARY }}>
                  Empty directory
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {transfers.length > 0 && (
        <div style={cardBase} className="p-3 space-y-2">
          <div className="flex items-center justify-between">
            <span className="text-sm font-medium" style={{ color: TEXT_PRIMARY }}>
              Host-to-Host Transfers
            </span>
            <button onClick={pollTransfers} style={{ color: TEXT_SECONDARY }} title="Refresh">
              <RefreshCw size={12} />
            </button>
          </div>
          {transfers.map((t) => {
            const pct = t.totalBytes > 0 ? Math.round((t.bytesTransferred / t.totalBytes) * 100) : t.status === 'completed' ? 100 : 0
            const statusColor =
              t.status === 'completed' ? '#2ECC71' : t.status === 'failed' ? '#E74C3C' : t.status === 'cancelled' ? '#E67E22' : GOLD
            return (
              <div key={t.transferId} className="space-y-1" style={{ fontSize: '12px' }}>
                <div className="flex items-center justify-between">
                  <span style={{ color: TEXT_PRIMARY }}>
                    {t.move ? 'Move' : 'Copy'} {hostName(t.sourceIntegrationId)} → {hostName(t.destIntegrationId)}: {t.destPath}
                  </span>
                  <div className="flex items-center gap-2">
                    <span style={{ color: statusColor }}>
                      {t.status === 'running'
                        ? `${t.filesTransferred}/${t.totalFiles} files · ${formatSize(t.bytesTransferred)}`
                        : t.status}
                    </span>
                    {t.status === 'running' && (
                      <button onClick={() => handleCancelTransfer(t.transferId)} title="Cancel" style={{ color: '#E74C3C' }}>
                        <X size={12} />
                      </button>
                    )}
                  </div>
                </div>
                <div className="h-1.5 w-full overflow-hidden rounded-full" style={{ backgroundColor: 'rgba(255,255,255,0.06)' }}>
                  <div className="h-full rounded-full transition-all" style={{ width: `${pct}%`, backgroundColor: statusColor }} />
                </div>
                {t.error && <span style={{ color: '#E74C3C' }}>{t.error}</span>}
                {t.status === 'running' && t.currentFile && (
                  <span style={{ color: TEXT_SECONDARY }}>{t.currentFile}</span>
                )}
              </div>
            )
          })}
        </div>
      )}

      {transferEntry && (
        <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: 'rgba(0,0,0,0.6)' }}>
          <div style={cardBase} className="p-4 w-full max-w-md flex flex-col gap-3">
            <div className="flex items-center justify-between">
              <span className="text-sm font-medium" style={{ color: TEXT_PRIMARY }}>
                Send "{transferEntry.name}" to another host
              </span>
              <button onClick={() => setTransferEntry(null)} style={{ color: TEXT_SECONDARY }}>
                <X size={16} />
              </button>
            </div>
            <label style={{ fontSize: '12px', color: TEXT_SECONDARY }}>Destination host</label>
            <select
              style={inputStyle()}
              value={transferDestId}
              onChange={(e) => setTransferDestId(e.target.value ? Number(e.target.value) : '')}
            >
              {hosts
                .filter((h) => h.id !== integrationId)
                .map((h) => (
                  <option key={h.id} value={h.id}>
                    {h.name}
                  </option>
                ))}
            </select>
            <label style={{ fontSize: '12px', color: TEXT_SECONDARY }}>Destination directory</label>
            <input
              style={inputStyle()}
              value={transferDestPath}
              onChange={(e) => setTransferDestPath(e.target.value)}
              placeholder="e.g. /home/user or ."
            />
            <label className="flex items-center gap-2" style={{ fontSize: '12px', color: TEXT_PRIMARY }}>
              <input type="checkbox" checked={transferMove} onChange={(e) => setTransferMove(e.target.checked)} />
              Move (delete from source after copy)
            </label>
            <div className="flex justify-end gap-2">
              <button onClick={() => setTransferEntry(null)} className="rounded-md px-3.5 py-1.5 text-xs" style={{ border: '1px solid rgba(200,164,52,0.2)', color: TEXT_PRIMARY }}>
                Cancel
              </button>
              <button
                onClick={startTransfer}
                disabled={!transferDestId || !transferDestPath}
                className="flex items-center gap-1 rounded-md px-3.5 py-1.5 text-xs"
                style={{ backgroundColor: GOLD, color: '#0A0A0C', opacity: !transferDestId || !transferDestPath ? 0.5 : 1 }}
              >
                <Send size={12} /> Transfer
              </button>
            </div>
          </div>
        </div>
      )}

      {editingPath && (
        <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: 'rgba(0,0,0,0.6)' }}>
          <div style={cardBase} className="p-4 w-3/4 max-w-3xl h-3/4 flex flex-col gap-3">
            <div className="flex items-center justify-between">
              <span className="text-sm font-medium" style={{ color: TEXT_PRIMARY }}>
                {editingPath}
              </span>
              <div className="flex items-center gap-2">
                <button
                  onClick={saveEdit}
                  disabled={savingEdit || editingEncoding === 'base64'}
                  className="flex items-center gap-1 rounded-md px-3.5 py-1.5 text-xs"
                  style={{ backgroundColor: GOLD, color: '#0A0A0C', opacity: editingEncoding === 'base64' ? 0.5 : 1 }}
                >
                  <Save size={12} /> Save
                </button>
                <button onClick={() => setEditingPath(null)} style={{ color: TEXT_SECONDARY }}>
                  <X size={16} />
                </button>
              </div>
            </div>
            {editingEncoding === 'base64' ? (
              <div style={{ color: TEXT_SECONDARY, fontSize: '13px' }}>Binary file - editing not supported. Use download instead.</div>
            ) : (
              <textarea
                value={editingContent}
                onChange={(e) => setEditingContent(e.target.value)}
                className="flex-1 resize-none"
                style={{
                  ...inputStyle(),
                  fontFamily: 'monospace',
                  width: '100%',
                  height: '100%',
                }}
              />
            )}
          </div>
        </div>
      )}
    </div>
  )
}
