import { useEffect, useRef, useState } from 'react'
import {
  Folder,
  File as FileIcon,
  ChevronRight,
  Upload,
  FolderPlus,
  Trash2,
  Download,
  Pencil,
  Save,
  X,
  RefreshCw,
} from 'lucide-react'
import { api, type FileEntry, type Integration } 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 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')
    }
  }

  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-2.5 py-1 text-xs" style={{ border: '1px solid rgba(255,255,255,0.1)', color: TEXT_PRIMARY }}>
              <RefreshCw size={12} /> Refresh
            </button>
            <button onClick={handleMkdir} className="flex items-center gap-1 rounded-md px-2.5 py-1 text-xs" style={{ border: '1px solid rgba(255,255,255,0.1)', color: TEXT_PRIMARY }}>
              <FolderPlus size={12} /> New Folder
            </button>
            <button
              onClick={() => fileInputRef.current?.click()}
              className="flex items-center gap-1 rounded-md px-2.5 py-1 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={() => 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>

      {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-2.5 py-1 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>
  )
}
