import { useState } from 'react'
import {
  CheckCircle2,
  FileUp,
  FolderOpen,
  ListTree,
  Monitor,
  RefreshCw,
  Server,
  Target,
  Upload,
  Zap,
} from 'lucide-react'
import Modal from './Modal'
import SftpFileSelectorModal from './SftpFileSelectorModal'
import {
  cancelRemoteTransferTask,
  createRemoteTransferTask,
  subscribeRemoteTransferProgress,
  subscribeUploadProgress,
  uploadFile,
} from '../services/sftp'
import type { Connection, ConnectionReachabilityStatus, TransferTaskGroup, TransferTaskItem } from '../types'

function aggregate(items: TransferTaskItem[]) {
  const total = items.length || 1
  const progress = Math.round(items.reduce((sum, item) => sum + item.progress, 0) / total)
  const allDone = items.every((item) => ['success', 'error', 'cancelled'].includes(item.status))
  const hasError = items.some((item) => item.status === 'error')
  const hasRunning = items.some((item) => item.status === 'running' || item.status === 'queued')
  const status = hasRunning ? 'running' : hasError ? 'error' : allDone ? 'success' : 'queued'
  return { progress, status: status as TransferTaskGroup['status'] }
}

function StatusDot({ status }: { status: ConnectionReachabilityStatus | undefined }) {
  if (status === 'online')
    return <span className="h-2 w-2 shrink-0 rounded-full bg-emerald-400" title="在线" />
  if (status === 'offline')
    return <span className="h-2 w-2 shrink-0 rounded-full bg-red-400" title="离线" />
  if (status === 'checking')
    return <span className="h-2 w-2 shrink-0 animate-pulse rounded-full bg-yellow-400" title="检测中" />
  return <span className="h-2 w-2 shrink-0 rounded-full bg-slate-600" title="未知" />
}



export default function TransferCenterModal({
  open,
  connections,
  connectionStatuses,
  tasks,
  onClose,
  onTasksChange,
}: {
  open: boolean
  connections: Connection[]
  connectionStatuses: Record<number, ConnectionReachabilityStatus>
  tasks: TransferTaskGroup[]
  onClose: () => void
  onTasksChange: (updater: TransferTaskGroup[] | ((prev: TransferTaskGroup[]) => TransferTaskGroup[])) => void
}) {
  const [tab, setTab] = useState<'local' | 'remote'>('local')
  const [targetIds, setTargetIds] = useState<number[]>(connections.length ? [connections[0].id] : [])
  const [localFiles, setLocalFiles] = useState<FileList | null>(null)
  const [localTargetPath, setLocalTargetPath] = useState('/usr/local/nginx/html')
  const [remoteSourceId, setRemoteSourceId] = useState<number>(connections[0]?.id ?? 0)
  const [remoteSourcePath, setRemoteSourcePath] = useState('/opt/app/build.tar.gz')
  const [remoteTargetPath, setRemoteTargetPath] = useState('/data/deploy/')
  const [showBrowser, setShowBrowser] = useState(false)

  if (!open) return null

  function updateTaskGroup(groupId: string, updater: (group: TransferTaskGroup) => TransferTaskGroup) {
    // Use functional update to always read latest state, avoiding stale-closure bugs in async callbacks
    onTasksChange((prev) => prev.map((task) => (task.id === groupId ? updater(task) : task)))
  }

  async function handleStartLocal() {
    if (!localFiles?.length || targetIds.length === 0) return
    const file = localFiles[0]
    const groupId = String(Date.now())
    const group: TransferTaskGroup = {
      id: groupId,
      mode: 'LOCAL_TO_MANY',
      title: `本地文件批量分发 · ${file.name}`,
      status: 'running',
      progress: 0,
      createdAt: new Date().toLocaleTimeString(),
      items: targetIds.map((id) => ({
        id: `${groupId}-${id}`,
        label: connections.find((item) => item.id === id)?.name || String(id),
        status: 'queued',
        progress: 0,
        message: '等待上传',
      })),
    }
    onTasksChange((prev) => [group, ...prev])

    targetIds.forEach(async (targetId) => {
      const response = await uploadFile(targetId, localTargetPath, file, { overwrite: true })
      const taskId = response.data.taskId
      updateTaskGroup(groupId, (current) => ({
        ...current,
        items: current.items.map((item) =>
          item.label === connections.find((conn) => conn.id === targetId)?.name
            ? { ...item, status: 'running', message: '正在传输...', taskId }
            : item,
        ),
      }))
      const unsubscribe = subscribeUploadProgress(taskId, (task) => {
        updateTaskGroup(groupId, (current) => {
          const nextItems = current.items.map((item) =>
                item.taskId === task.taskId
              ? {
                  ...item,
                  progress: task.progress,
                  status: task.status,
                  message: task.error || (task.status === 'success' ? '上传完成' : task.status === 'error' ? '上传失败' : '正在传输...'),
                }
              : item,
          )
          const next = aggregate(nextItems)
          return { ...current, items: nextItems, progress: next.progress, status: next.status }
        })
        if (['success', 'error'].includes(task.status)) {
          unsubscribe()
        }
      })
    })
  }

  async function handleStartRemote() {
    if (!remoteSourceId || targetIds.length === 0 || !remoteSourcePath.trim()) return
    const groupId = String(Date.now())
    const sourceName = remoteSourcePath.trim().split('/').filter(Boolean).pop() || remoteSourcePath.trim()
    const group: TransferTaskGroup = {
      id: groupId,
      mode: 'REMOTE_TO_MANY',
      title: `跨主机分发 · ${sourceName}`,
      status: 'running',
      progress: 0,
      createdAt: new Date().toLocaleTimeString(),
      items: targetIds.map((id) => ({
        id: `${groupId}-${id}`,
        label: connections.find((item) => item.id === id)?.name || String(id),
        status: 'queued',
        progress: 0,
        message: '等待创建任务',
      })),
    }
    onTasksChange((prev) => [group, ...prev])

    targetIds.forEach(async (targetId) => {
      const response = await createRemoteTransferTask(remoteSourceId, remoteSourcePath, targetId, remoteTargetPath)
      const taskId = response.data.taskId
      updateTaskGroup(groupId, (current) => ({
        ...current,
        items: current.items.map((item) =>
          item.label === connections.find((conn) => conn.id === targetId)?.name
            ? { ...item, status: 'running', message: '正在跨服同步...', taskId }
            : item,
        ),
      }))
      const unsubscribe = subscribeRemoteTransferProgress(taskId, (task) => {
        updateTaskGroup(groupId, (current) => {
          const nextItems = current.items.map((item) =>
            item.taskId === task.taskId
              ? {
                  ...item,
                  progress: task.progress,
                  status: task.status,
                  message: task.error || (task.status === 'success' ? '同步完成' : task.status === 'error' ? '同步失败' : task.status === 'cancelled' ? '已取消' : '正在同步...'),
                }
              : item,
          )
          const next = aggregate(nextItems)
          return { ...current, items: nextItems, progress: next.progress, status: next.status }
        })
        if (['success', 'error', 'cancelled'].includes(task.status)) {
          unsubscribe()
        }
      })
    })
  }

  return (
    <>
      <Modal title="文件传输中心" onClose={onClose} maxWidth="max-w-7xl">
      <div className="flex h-[74vh] flex-col overflow-hidden rounded-2xl border border-slate-800 bg-[#0d1117]">
        {/* Tabs */}
        <div className="flex gap-8 border-b border-slate-800 bg-slate-900 px-6 pt-4">
          <button
            className={`border-b-2 pb-3 text-sm font-medium ${tab === 'local' ? 'border-blue-500 text-blue-400' : 'border-transparent text-slate-400'}`}
            onClick={() => setTab('local')}
          >
            <span className="flex items-center gap-2">
              <Monitor size={16} />
              本地分发到多台
            </span>
          </button>
          <button
            className={`border-b-2 pb-3 text-sm font-medium ${tab === 'remote' ? 'border-purple-500 text-purple-400' : 'border-transparent text-slate-400'}`}
            onClick={() => { setTab('remote'); setShowBrowser(false) }}
          >
            <span className="flex items-center gap-2">
              <Server size={16} />
              远程分发到多台
            </span>
          </button>
        </div>

        <div className="flex flex-1 overflow-hidden">
          {/* Left panel */}
          <div className="flex flex-1 overflow-hidden border-r border-slate-800 bg-slate-900/70 p-6">
            {tab === 'local' ? (
              <div className="flex h-full flex-1 gap-6 overflow-hidden">
                {/* Source config */}
                <div className="flex w-1/2 shrink-0 flex-col gap-4 overflow-y-auto border-r border-slate-800 pr-6">
                  <h3 className="flex items-center gap-2 text-sm font-bold text-blue-400">
                    <Monitor size={16} />
                    源配置
                  </h3>

                  <div className="space-y-2">
                    <span className="text-sm text-slate-300">选择本地文件</span>
                    <label className="group flex cursor-pointer flex-col items-center justify-center rounded-2xl border-2 border-dashed border-slate-700 bg-slate-800/30 px-6 py-8 transition-all hover:border-blue-500 hover:bg-blue-500/5">
                      <div className="mb-3 rounded-full bg-slate-800 p-3 shadow-sm transition-colors group-hover:bg-blue-600">
                        <FileUp size={24} className="text-slate-400 transition-colors group-hover:text-white" />
                      </div>
                      <span className="text-sm font-medium text-slate-200 transition-colors group-hover:text-blue-400">
                        {localFiles && localFiles.length > 0 ? '重新选择文件' : '点击选择本地文件'}
                      </span>
                      <span className="mt-1 max-w-full truncate text-xs text-slate-500">
                        {localFiles && localFiles.length > 0 ? (
                          <span className="text-emerald-400">{localFiles.length === 1 ? localFiles[0].name : `已选择 ${localFiles.length} 个文件`}</span>
                        ) : (
                          '支持多选文件/文件夹'
                        )}
                      </span>
                      <input
                        type="file"
                        multiple
                        className="hidden"
                        onChange={(event) => setLocalFiles(event.target.files)}
                      />
                    </label>
                  </div>

                  <label className="space-y-2">
                    <span className="text-sm text-slate-300">目标路径</span>
                    <input className="w-full rounded-xl border border-slate-700 bg-black px-4 py-3 text-sm text-white" value={localTargetPath} onChange={(event) => setLocalTargetPath(event.target.value)} />
                  </label>

                  <div className="mt-auto rounded-xl border border-slate-800 bg-slate-950/50 px-4 py-3 text-xs text-slate-500">
                    <p className="font-medium text-slate-400">⚡ 并发执行</p>
                    <p className="mt-1">分发任务将按浏览器任务并行执行。</p>
                  </div>
                </div>

                {/* Target config */}
                <div className="flex min-w-0 flex-1 flex-col gap-4 overflow-hidden">
                  <h3 className="flex items-center gap-2 text-sm font-bold text-blue-400">
                    <Target size={16} />
                    目标配置
                  </h3>

                  <div className="flex min-h-0 flex-1 flex-col space-y-2">
                    <div className="flex shrink-0 items-center justify-between">
                      <span className="text-sm text-slate-300">目标服务器</span>
                      <button
                        className="text-xs text-blue-400"
                        onClick={() => setTargetIds(connections.filter((c) => connectionStatuses[c.id] === 'online').map((c) => c.id))}
                      >
                        全选在线
                      </button>
                    </div>
                    <div className="min-h-0 flex-1 overflow-y-auto rounded-2xl border border-slate-700 bg-black p-2">
                      {connections.map((server) => {
                        const st = connectionStatuses[server.id]
                        const isOnline = st === 'online'
                        return (
                          <label
                            key={server.id}
                            className={`flex items-center gap-2 rounded-xl px-3 py-2 ${
                              isOnline ? 'cursor-pointer hover:bg-slate-800' : 'cursor-not-allowed opacity-40'
                            }`}
                          >
                            <input
                              type="checkbox"
                              disabled={!isOnline}
                              checked={targetIds.includes(server.id)}
                              onChange={() =>
                                setTargetIds((prev) =>
                                  prev.includes(server.id) ? prev.filter((item) => item !== server.id) : [...prev, server.id],
                                )
                              }
                            />
                            <StatusDot status={st} />
                            <span className="text-sm text-slate-300">{server.name}</span>
                          </label>
                        )
                      })}
                    </div>
                  </div>

                  <button
                    className={`flex w-full items-center justify-center gap-2 rounded-xl py-3 font-medium transition ${
                      !localFiles?.length || targetIds.length === 0
                        ? 'cursor-not-allowed bg-slate-800 text-slate-500'
                        : 'bg-blue-600 text-white hover:bg-blue-500'
                    }`}
                    disabled={!localFiles?.length || targetIds.length === 0}
                    onClick={() => void handleStartLocal()}
                  >
                    <Upload size={18} />
                    {!localFiles?.length ? '请选择本地文件' : targetIds.length === 0 ? '请选择目标服务器' : '开始分发'}
                  </button>
                </div>
              </div>
            ) : (
              <div className="flex h-full flex-1 gap-6 overflow-hidden">
                {/* Source config */}
                <div className="flex w-1/2 shrink-0 flex-col gap-4 overflow-y-auto border-r border-slate-800 pr-6">
                  <h3 className="flex items-center gap-2 text-sm font-bold text-purple-400">
                    <Zap size={16} />
                    源配置
                  </h3>

                  <div className="space-y-2">
                    <div className="flex items-center gap-2">
                      <span className="text-sm text-slate-300">源服务器</span>
                      {(() => {
                        const st = connectionStatuses[remoteSourceId]
                        if (st === 'online') return <span className="flex items-center gap-1 rounded-full bg-emerald-500/15 px-2 py-0.5 text-xs font-medium text-emerald-400"><span className="h-1.5 w-1.5 rounded-full bg-emerald-400" />在线</span>
                        if (st === 'offline') return <span className="flex items-center gap-1 rounded-full bg-red-500/15 px-2 py-0.5 text-xs font-medium text-red-400"><span className="h-1.5 w-1.5 rounded-full bg-red-400" />离线</span>
                        if (st === 'checking') return <span className="flex items-center gap-1 rounded-full bg-yellow-500/15 px-2 py-0.5 text-xs font-medium text-yellow-400"><span className="h-1.5 w-1.5 animate-pulse rounded-full bg-yellow-400" />检测中</span>
                        return <span className="flex items-center gap-1 rounded-full bg-slate-700/60 px-2 py-0.5 text-xs font-medium text-slate-500"><span className="h-1.5 w-1.5 rounded-full bg-slate-500" />未知</span>
                      })()}
                    </div>
                    <select
                      className={`w-full rounded-xl border bg-black px-4 py-3 text-sm text-white ${
                        connectionStatuses[remoteSourceId] === 'online'
                          ? 'border-emerald-700'
                          : connectionStatuses[remoteSourceId] === 'offline'
                            ? 'border-red-800'
                            : 'border-slate-700'
                      }`}
                      value={remoteSourceId}
                      onChange={(event) => {
                        setRemoteSourceId(Number(event.target.value))
                        setShowBrowser(false)
                      }}
                    >
                      {connections.map((server) => {
                        const st = connectionStatuses[server.id]
                        const isOnline = st === 'online'
                        const label = st === 'online' ? '● ' : st === 'offline' ? '● ' : st === 'checking' ? '◔ ' : '◦ '
                        return (
                          <option key={server.id} value={server.id} disabled={!isOnline}>
                            {label}{server.name}{!isOnline ? (st === 'offline' ? ' (离线)' : ' (未知)') : ''}
                          </option>
                        )
                      })}
                    </select>
                  </div>

                  <div className="space-y-2">
                    <div className="flex items-center justify-between">
                      <span className="text-sm text-slate-300">源文件 / 文件夹路径</span>
                      <button
                        className={`flex items-center gap-1 rounded-lg px-2 py-1 text-xs transition ${
                          showBrowser
                            ? 'bg-purple-600 text-white'
                            : 'border border-slate-700 text-slate-400 hover:border-purple-500 hover:text-purple-400'
                        }`}
                        onClick={() => setShowBrowser((v) => !v)}
                      >
                        <FolderOpen size={12} />
                        {showBrowser ? '收起' : '浏览...'}
                      </button>
                    </div>
                    <input
                      className="w-full rounded-xl border border-slate-700 bg-black px-4 py-3 font-mono text-sm text-white"
                      value={remoteSourcePath}
                      onChange={(event) => setRemoteSourcePath(event.target.value)}
                      placeholder="/opt/app"
                    />
                  </div>

                  <div className="mt-auto rounded-xl border border-slate-800 bg-slate-950/50 px-4 py-3 text-xs text-slate-500">
                    <p className="font-medium text-slate-400">📁 支持文件夹传输</p>
                    <p className="mt-1">选择文件夹时，将在目标路径下创建同名子目录并递归传输所有内容。</p>
                  </div>
                </div>

                {/* Target config */}
                <div className="flex min-w-0 flex-1 flex-col gap-4 overflow-hidden">
                  <h3 className="flex items-center gap-2 text-sm font-bold text-blue-400">
                    <Target size={16} />
                    目标配置
                  </h3>

                  <label className="space-y-2">
                    <span className="text-sm text-slate-300">目标目录</span>
                    <input
                      className="w-full rounded-xl border border-slate-700 bg-black px-4 py-3 text-sm text-white"
                      value={remoteTargetPath}
                      onChange={(event) => setRemoteTargetPath(event.target.value)}
                    />
                  </label>

                  <div className="flex min-h-0 flex-1 flex-col space-y-2">
                    <div className="flex shrink-0 items-center justify-between">
                      <span className="text-sm text-slate-300">目标服务器</span>
                      <button
                        className="text-xs text-blue-400"
                        onClick={() => setTargetIds(connections.filter((c) => connectionStatuses[c.id] === 'online').map((c) => c.id))}
                      >
                        全选在线
                      </button>
                    </div>
                    <div className="min-h-0 flex-1 overflow-y-auto rounded-2xl border border-slate-700 bg-black p-2">
                      {connections.map((server) => {
                        const st = connectionStatuses[server.id]
                        const isOnline = st === 'online'
                        return (
                          <label
                            key={server.id}
                            className={`flex items-center gap-2 rounded-xl px-3 py-2 ${
                              isOnline ? 'cursor-pointer hover:bg-slate-800' : 'cursor-not-allowed opacity-40'
                            }`}
                          >
                            <input
                              type="checkbox"
                              disabled={!isOnline}
                              checked={targetIds.includes(server.id)}
                              onChange={() =>
                                setTargetIds((prev) =>
                                  prev.includes(server.id) ? prev.filter((item) => item !== server.id) : [...prev, server.id],
                                )
                              }
                            />
                            <StatusDot status={st} />
                            <span className="text-sm text-slate-300">{server.name}</span>
                          </label>
                        )
                      })}
                    </div>
                  </div>

                  <button
                    className={`flex w-full items-center justify-center gap-2 rounded-xl py-3 font-medium transition ${
                      !remoteSourceId || targetIds.length === 0 || !remoteSourcePath.trim()
                        ? 'cursor-not-allowed bg-slate-800 text-slate-500'
                        : 'bg-purple-600 text-white hover:bg-purple-500'
                    }`}
                    disabled={!remoteSourceId || targetIds.length === 0 || !remoteSourcePath.trim()}
                    onClick={() => void handleStartRemote()}
                  >
                    <Zap size={18} fill="currentColor" />
                    {!remoteSourceId
                      ? '请选择源服务器'
                      : !remoteSourcePath.trim()
                        ? '请填写源路径'
                        : targetIds.length === 0
                          ? '请选择目标服务器'
                          : '跨服同步分发'}
                  </button>
                </div>
              </div>
            )}
          </div>

          {/* Task status panel */}
          <div className="flex w-[360px] shrink-0 flex-col bg-[#0d1117]">
            <div className="flex items-center justify-between border-b border-slate-800 bg-slate-900 px-4 py-4">
              <h4 className="flex items-center gap-2 text-sm font-medium text-slate-200">
                <ListTree size={16} className="text-slate-400" />
                任务状态
              </h4>
              <button className="text-xs text-slate-400" onClick={() => onTasksChange([])}>
                清空记录
              </button>
            </div>
            <div className="flex-1 space-y-4 overflow-auto p-3">
              {tasks.length === 0 ? (
                <div className="flex h-full flex-col items-center justify-center text-slate-500">
                  <FileUp size={32} className="mb-2 opacity-50" />
                  <p className="text-sm">暂无传输任务</p>
                </div>
              ) : (
                tasks.map((task) => (
                  <div key={task.id} className="overflow-hidden rounded-2xl border border-slate-700 bg-slate-800">
                    <div className="border-b border-slate-700 bg-slate-800/90 p-3">
                      <div className="mb-2 flex items-start justify-between">
                        <span className="pr-2 text-sm font-medium text-slate-100">{task.title}</span>
                        {task.status === 'running' ? (
                          <button
                            className="shrink-0 text-xs text-red-400"
                            onClick={() => {
                              task.items.forEach((item) => {
                                if (item.taskId) void cancelRemoteTransferTask(item.taskId)
                              })
                            }}
                          >
                            取消
                          </button>
                        ) : null}
                      </div>
                      <div className="text-xs text-slate-500">
                        {task.createdAt}
                      </div>
                    </div>
                    <div className="max-h-48 space-y-1 overflow-auto bg-slate-900/60 p-2">
                      {task.items.map((item) => (
                        <div key={item.id} className="rounded-xl p-2 hover:bg-slate-800">
                          <div className="flex justify-between text-xs">
                            <span className="truncate text-slate-300">{item.label}</span>
                            <div className="flex items-center gap-2">
                              <span className="text-slate-500">{item.message}</span>
                              <span className={item.status === 'success' ? 'text-emerald-400' : 'text-blue-400'}>{item.progress}%</span>
                            </div>
                          </div>
                          <div className="mt-2 flex items-center gap-2">
                            <div className="h-1 flex-1 rounded-full bg-black">
                              <div
                                className={`h-1 rounded-full ${item.status === 'success' ? 'bg-emerald-500' : item.status === 'error' ? 'bg-red-500' : 'bg-blue-400'}`}
                                style={{ width: `${item.progress}%` }}
                              />
                            </div>
                            {item.status === 'success' ? (
                              <CheckCircle2 size={12} className="text-emerald-500" />
                            ) : item.status === 'running' ? (
                              <RefreshCw size={12} className="animate-spin text-blue-400" />
                            ) : null}
                          </div>
                        </div>
                      ))}
                    </div>
                  </div>
                ))
              )}
            </div>
          </div>
        </div>
      </div>
    </Modal>

    {/* SFTP file selector popup — mounted outside the main modal so it overlays on top */}
    {showBrowser && (
      <SftpFileSelectorModal
        open={showBrowser}
        connection={connections.find((c) => c.id === remoteSourceId) ?? connections[0]}
        onSelect={(path) => {
          setRemoteSourcePath(path)
          setShowBrowser(false)
        }}
        onClose={() => setShowBrowser(false)}
      />
    )}
    </>
  )
}
