import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Settings, WifiOff, ArrowRight, ArrowLeft, BookOpen, Download, MousePointerClick, HelpCircle } from 'lucide-react';
import { FileItem, FileType, LogEntry, TransferItem, FileSystemState, SiteConfig } from './types';
import FilePane from './components/FilePane';
import LogConsole from './components/LogConsole';
import TransferQueue from './components/TransferQueue';
import SettingsModal from './components/SettingsModal';
import SiteManagerModal from './components/SiteManagerModal';
import HelpModal from './components/HelpModal';
import { CreateFolderModal, RenameModal, DeleteModal } from './components/FileActionModals';

const App: React.FC = () => {
  // --- State ---
  const savedPref = localStorage.getItem('save_connection_info') !== 'false';
  const [saveConnectionInfo, setSaveConnectionInfo] = useState(savedPref);

  const [connection, setConnection] = useState({
    host: savedPref ? (localStorage.getItem('last_host') || '') : '',
    user: savedPref ? (localStorage.getItem('last_user') || '') : '',
    pass: '',
    port: savedPref ? (localStorage.getItem('last_port') || '21') : '21',
    protocol: savedPref ? ((localStorage.getItem('last_protocol') as 'ftp' | 'sftp') || 'ftp') : 'ftp',
    passive: true,
    initialPath: '', // New field for Session-specific initial path
    connected: false,
    connecting: false
  });
  const [isBackendConnected, setIsBackendConnected] = useState(false);
  const [refreshKey, setRefreshKey] = useState(0); // To force FilePane input revert on error

  const [logs, setLogs] = useState<LogEntry[]>([]);
  const [queue, setQueue] = useState<TransferItem[]>([]);
  const [showSettings, setShowSettings] = useState(false);
  const [showConnectionHelp, setShowConnectionHelp] = useState(false);
  const [showSiteManager, setShowSiteManager] = useState(false);
  const [showHelp, setShowHelp] = useState(false);
  const [helpInitialTab, setHelpInitialTab] = useState<'sites' | 'connection' | 'files' | 'backend'>('sites');
  const [savedSites, setSavedSites] = useState<SiteConfig[]>([]);

  // Modals State
  const [activeModal, setActiveModal] = useState<'create' | 'rename' | 'delete' | null>(null);
  const [modalTargetIsLocal, setModalTargetIsLocal] = useState(true);
  const [renameTargetName, setRenameTargetName] = useState('');

  // Local File System
  const [local, setLocal] = useState<FileSystemState>({
    path: localStorage.getItem('last_local_path') || '',
    files: [],
    isLoading: false
  });
  const [selectedLocalIds, setSelectedLocalIds] = useState<Set<string>>(new Set());

  // Remote File System
  const [remote, setRemote] = useState<FileSystemState>({
    path: '/',
    files: [],
    isLoading: false
  });
  const [selectedRemoteIds, setSelectedRemoteIds] = useState<Set<string>>(new Set());

  // WebSocket
  const wsRef = useRef<WebSocket | null>(null);
  const connectionRef = useRef(connection);

  // --- Helpers ---
  const addLog = useCallback((type: LogEntry['type'], message: string) => {
    setLogs(prev => [...prev, {
      id: Math.random().toString(36),
      timestamp: new Date().toISOString(),
      type,
      message
    }]);
  }, []);

  const getSelectedFiles = (allFiles: FileItem[], ids: Set<string>) => {
    return allFiles.filter(f => ids.has(f.id));
  };

  // --- Persistence Effects ---
  useEffect(() => {
    localStorage.setItem('save_connection_info', String(saveConnectionInfo));

    if (saveConnectionInfo) {
      localStorage.setItem('last_host', connection.host);
      localStorage.setItem('last_user', connection.user);
      localStorage.setItem('last_port', connection.port);
      localStorage.setItem('last_protocol', connection.protocol);
    } else {
      localStorage.removeItem('last_host');
      localStorage.removeItem('last_user');
      localStorage.removeItem('last_port');
      localStorage.removeItem('last_protocol');
    }
  }, [connection.host, connection.user, connection.port, connection.protocol, saveConnectionInfo]);

  useEffect(() => {
    if (local.path) localStorage.setItem('last_local_path', local.path);
  }, [local.path]);

  // Sync connection state to ref for WS callbacks
  useEffect(() => {
    connectionRef.current = connection;
  }, [connection]);

  // --- WebSocket Setup ---
  useEffect(() => {
    let ws: WebSocket | null = null;
    let connectTimer: any = null;

    const connectWS = () => {
      // Debounce connection to avoid Strict Mode double-invocation issues
      connectTimer = setTimeout(() => {
        // Check if already connected/connecting to avoid dupes
        if (wsRef.current && (wsRef.current.readyState === WebSocket.OPEN || wsRef.current.readyState === WebSocket.CONNECTING)) {
          return;
        }

        addLog('system', '백엔드 프록시 서버(ws://localhost:8090) 연결 시도 중...');

        try {
          ws = new WebSocket('ws://localhost:8090');
          wsRef.current = ws;

          ws.onopen = () => {
            addLog('success', '백엔드 프록시 서버에 연결되었습니다.');
            setIsBackendConnected(true);
            setShowConnectionHelp(false);
            // Initial Data Requests
            ws!.send(JSON.stringify({ command: 'GET_SITES' }));
            const storedLocalPath = localStorage.getItem('last_local_path') || '';
            ws!.send(JSON.stringify({ command: 'LOCAL_LIST', path: storedLocalPath }));
          };

          ws.onmessage = (event) => {
            try {
              const data = JSON.parse(event.data);

              switch (data.type) {
                // ... (no change to inside of switch) ...
                case 'status':
                  if (data.status === 'connected') {
                    setConnection(prev => ({ ...prev, connected: true, connecting: false }));
                    addLog('success', data.message || 'FTP 연결 성공');

                    // Use Ref for latest state (especially initialPath from Site Manager)
                    const currentConn = connectionRef.current;

                    // 1. Initial Directory from Site Config
                    if (currentConn.initialPath) {
                      ws?.send(JSON.stringify({ command: 'LIST', path: currentConn.initialPath }));
                    }
                    // 2. Last Visited Path (Persistence)
                    else {
                      const lastRemote = localStorage.getItem(`last_remote_path_${currentConn.host}`);
                      const initialPath = lastRemote || '/';
                      ws?.send(JSON.stringify({ command: 'LIST', path: initialPath }));
                    }
                  } else if (data.status === 'disconnected') {
                    setConnection(prev => ({ ...prev, connected: false, connecting: false }));
                    setRemote(prev => ({ ...prev, files: [], path: '/' }));
                    addLog('system', 'FTP 연결 종료');
                  } else if (data.status === 'error') {
                    setConnection(prev => ({ ...prev, connecting: false }));
                    addLog('error', data.message);
                  }
                  break;

                case 'list':
                // ... (rest of cases handled by maintaining existing code structure or using multi-replace if I was confident, but here let's careful) ...
                // Since replace_file_content works on lines, I should target specific blocks. 
                // BE CAREFUL: attempting to replace too large block blindly.
                // I should stick to smaller replaces.
              }

              // To avoid re-writing the huge switch content, I will use multiple Replace calls or just target onopen/onclose.
            } catch (e) {
              // ...
            }
          }; // This close brace is problematic if I don't include the switch logic.
          // Better: just replace onopen and onclose separately.


          ws.onmessage = (event) => {
            try {
              const data = JSON.parse(event.data);

              switch (data.type) {
                case 'status':
                  if (data.status === 'connected') {
                    setConnection(prev => ({ ...prev, connected: true, connecting: false }));
                    addLog('success', data.message || 'FTP 연결 성공');

                    // Use Ref for latest state (especially initialPath from Site Manager)
                    const currentConn = connectionRef.current;

                    // 1. Initial Directory from Site Config
                    if (currentConn.initialPath) {
                      ws?.send(JSON.stringify({ command: 'LIST', path: currentConn.initialPath }));
                    }
                    // 2. Last Visited Path (Persistence)
                    else {
                      const lastRemote = localStorage.getItem(`last_remote_path_${currentConn.host}`);
                      const initialPath = lastRemote || '/';
                      ws?.send(JSON.stringify({ command: 'LIST', path: initialPath }));
                    }
                  } else if (data.status === 'disconnected') {
                    setConnection(prev => ({ ...prev, connected: false, connecting: false }));
                    addLog('info', 'FTP 연결 종료');
                    setRemote(prev => ({ ...prev, files: [], path: '/' }));
                  }
                  break;

                case 'list':
                  const sortedRemoteFiles = data.files
                    .map((f: any) => ({
                      ...f,
                      type: f.type === 'FOLDER' ? FileType.FOLDER : FileType.FILE
                    }))
                    .sort((a: any, b: any) => {
                      if (a.type !== b.type) return a.type === FileType.FOLDER ? -1 : 1;
                      return a.name.localeCompare(b.name);
                    });

                  setRemote({
                    path: data.path,
                    files: sortedRemoteFiles,
                    isLoading: false
                  });
                  if (connectionRef.current.host) {
                    localStorage.setItem(`last_remote_path_${connectionRef.current.host}`, data.path);
                  }
                  addLog('success', `목록 조회 완료: ${data.path}`);
                  break;

                case 'local_list':
                  const sortedLocalFiles = data.files
                    .map((f: any) => ({
                      ...f,
                      type: f.type === 'FOLDER' ? FileType.FOLDER : FileType.FILE
                    }))
                    .sort((a: any, b: any) => {
                      if (a.type !== b.type) return a.type === FileType.FOLDER ? -1 : 1;
                      return a.name.localeCompare(b.name);
                    });

                  setLocal({
                    path: data.path,
                    files: sortedLocalFiles,
                    isLoading: false
                  });
                  addLog('success', `[로컬] 이동 완료: ${data.path}`);
                  break;

                case 'error':
                  addLog('error', data.message);
                  window.alert(data.message); // Show error dialog
                  setConnection(prev => ({ ...prev, connecting: false }));
                  setRemote(prev => ({ ...prev, isLoading: false }));
                  setLocal(prev => ({ ...prev, isLoading: false }));
                  setRefreshKey(prev => prev + 1); // Revert invalid inputs
                  break;

                case 'success':
                  addLog('success', data.message);
                  if (connection.connected) {
                    ws?.send(JSON.stringify({ command: 'LIST', path: remote.path }));
                  }
                  ws?.send(JSON.stringify({ command: 'LOCAL_LIST', path: local.path }));
                  break;

                case 'sites_list':
                  setSavedSites(data.sites);
                  break;
              }
            } catch (e) {
              console.error("WS Message Error", e);
            }
          };

          ws.onclose = (e) => {
            setIsBackendConnected(false);
            setConnection(prev => ({ ...prev, connected: false, connecting: false }));
            if (e.code !== 1000) { // Not normal closure
              addLog('error', '백엔드 서버와 연결이 끊어졌습니다. 재연결 시도 중...');
              if (window.location.protocol === 'https:') {
                setShowConnectionHelp(true);
              }
              // Retry loop
              setTimeout(() => {
                // Only retry if component still mounted (implied by effect cleanup)
                // But cleaner to just call connectWS which checks state
                connectWS();
              }, 3000);
            }
          };

          ws.onerror = (err) => {
            console.error("WS Error", err);
            addLog('error', '백엔드 소켓 연결 오류');
            if (window.location.protocol === 'https:') {
              setShowConnectionHelp(true);
            }
          };
        } catch (e) {
          console.error("WS Setup Error", e);
          if (window.location.protocol === 'https:') {
            setShowConnectionHelp(true);
          }
        }
      }, 300);
    };

    connectWS();

    return () => {
      clearTimeout(connectTimer);
      if (wsRef.current) {
        wsRef.current.close(1000);
        wsRef.current = null;
      }
    };
  }, [addLog]); // Intentionally minimal deps




  // --- Connection Handlers ---
  const handleConnect = () => {
    if (connection.connected) {
      if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
        wsRef.current.send(JSON.stringify({ command: 'DISCONNECT' }));
      }
      return;
    }

    setConnection(prev => ({ ...prev, connecting: true }));
    addLog('command', `CONNECT [${connection.protocol.toUpperCase()}] ${connection.user}@${connection.host}:${connection.port} ${connection.passive ? '(Passive)' : ''}`);

    if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify({
        command: 'CONNECT',
        host: connection.host,
        user: connection.user,
        pass: connection.pass,
        port: connection.port,
        protocol: connection.protocol,
        passive: connection.passive
      }));
    } else {
      addLog('error', '백엔드 서버에 연결되어 있지 않습니다. 잠시 후 다시 시도하세요.');
      setConnection(prev => ({ ...prev, connecting: false }));
    }
  };

  const handleRemoteNavigate = (path: string) => {
    if (!connection.connected) return;
    setRemote(prev => ({ ...prev, isLoading: true }));
    setSelectedRemoteIds(new Set());
    if (wsRef.current) wsRef.current.send(JSON.stringify({ command: 'LIST', path }));
  };

  const handleLocalNavigate = (path: string) => {
    setLocal(prev => ({ ...prev, isLoading: true }));
    setSelectedLocalIds(new Set());
    if (wsRef.current) wsRef.current.send(JSON.stringify({ command: 'LOCAL_LIST', path }));
  };

  // --- File Action Handlers ---
  const initiateCreateFolder = (isLocal: boolean) => {
    if (!isLocal && !connection.connected) return;
    setModalTargetIsLocal(isLocal);
    setActiveModal('create');
  };
  const initiateRename = (isLocal: boolean) => {
    if (!isLocal && !connection.connected) return;
    const selectedIds = isLocal ? selectedLocalIds : selectedRemoteIds;
    if (selectedIds.size !== 1) return;
    const files = isLocal ? local.files : remote.files;
    const file = files.find(f => selectedIds.has(f.id));
    if (file) {
      setRenameTargetName(file.name);
      setModalTargetIsLocal(isLocal);
      setActiveModal('rename');
    }
  };
  const initiateDelete = (isLocal: boolean) => {
    if (!isLocal && !connection.connected) return;
    setModalTargetIsLocal(isLocal);
    setActiveModal('delete');
  };

  // --- Modal Confirms ---
  const handleCreateFolderConfirm = (name: string) => {
    if (!name.trim()) return;
    if (modalTargetIsLocal) {
      addLog('command', `LOCAL_MKD ${name}`);
      if (wsRef.current) {
        // Simple path join, assuming separators are handled by Node or we use /
        const separator = local.path.includes('\\') ? '\\' : '/';
        const cleanPath = local.path.endsWith(separator) ? local.path : local.path + separator;
        const targetPath = cleanPath + name;
        wsRef.current.send(JSON.stringify({ command: 'LOCAL_MKD', path: targetPath }));
        // Refresh list after short delay or wait for success response?
        // Success response triggers nothing specific yet, but we can hook into success message or just refresh manually here?
        // Better: success handler in onmessage triggers reload.
        // For now, let's trigger reload after delay or optimistic?
        // Let's rely on success message from backend to trigger reload?
        // Currently 'success' message just logs.
        // I'll add a reload request in the success handler logic or just request it here?
        setTimeout(() => {
          wsRef.current?.send(JSON.stringify({ command: 'LOCAL_LIST', path: local.path }));
        }, 500);
      }
    } else {
      addLog('command', `MKD ${name}`);
      if (wsRef.current) {
        const targetPath = remote.path === '/' ? `/${name}` : `${remote.path}/${name}`;
        wsRef.current.send(JSON.stringify({ command: 'MKD', path: targetPath }));
        setTimeout(() => {
          wsRef.current?.send(JSON.stringify({ command: 'LIST', path: remote.path }));
        }, 500);
      }
    }
    setActiveModal(null);
  };

  const handleRenameConfirm = (newName: string) => {
    if (!newName.trim()) return;
    if (modalTargetIsLocal) {
      const selectedIds = selectedLocalIds;
      const file = local.files.find(f => selectedIds.has(f.id));
      if (file && wsRef.current) {
        const separator = local.path.includes('\\') ? '\\' : '/';
        const cleanPath = local.path.endsWith(separator) ? local.path : local.path + separator;
        const from = cleanPath + file.name;
        const to = cleanPath + newName;

        addLog('command', `LOCAL_RENAME ${file.name} -> ${newName}`);
        wsRef.current.send(JSON.stringify({ command: 'LOCAL_RENAME', from, to }));
        setTimeout(() => {
          wsRef.current?.send(JSON.stringify({ command: 'LOCAL_LIST', path: local.path }));
        }, 500);
      }
    } else {
      const selectedIds = selectedRemoteIds;
      const file = remote.files.find(f => selectedIds.has(f.id));
      if (wsRef.current && file) {
        const from = remote.path === '/' ? `/${file.name}` : `${remote.path}/${file.name}`;
        const to = remote.path === '/' ? `/${newName}` : `${remote.path}/${newName}`;
        wsRef.current.send(JSON.stringify({ command: 'RENAME', from, to }));
        setTimeout(() => {
          wsRef.current?.send(JSON.stringify({ command: 'LIST', path: remote.path }));
        }, 500);
      }
    }
    setActiveModal(null);
  };

  const handleDeleteConfirm = () => {
    if (modalTargetIsLocal) {
      const ids = selectedLocalIds;
      addLog('command', `LOCAL_DELE [${ids.size} items]`);
      if (wsRef.current) {
        const separator = local.path.includes('\\') ? '\\' : '/';
        const cleanPath = local.path.endsWith(separator) ? local.path : local.path + separator;

        ids.forEach(id => {
          const file = local.files.find(f => f.id === id);
          if (file) {
            const targetPath = cleanPath + file.name;
            wsRef.current?.send(JSON.stringify({ command: 'LOCAL_DELE', path: targetPath }));
          }
        });
        setTimeout(() => {
          wsRef.current?.send(JSON.stringify({ command: 'LOCAL_LIST', path: local.path }));
        }, 500 + (ids.size * 50)); // Delay a bit more for multiple deletes
      }
      setSelectedLocalIds(new Set());
    } else {
      const ids = selectedRemoteIds;
      addLog('command', `DELE [${ids.size} items]`);
      if (wsRef.current) {
        ids.forEach(id => {
          const file = remote.files.find(f => f.id === id);
          if (file) {
            const targetPath = remote.path === '/' ? `/${file.name}` : `${remote.path}/${file.name}`;
            wsRef.current.send(JSON.stringify({
              command: 'DELE',
              path: targetPath,
              isFolder: file.type === FileType.FOLDER
            }));
          }
        });
        setTimeout(() => {
          wsRef.current?.send(JSON.stringify({ command: 'LIST', path: remote.path }));
        }, 500 + (ids.size * 50));
      }
      setSelectedRemoteIds(new Set());
    }
    setActiveModal(null);
  };

  const handleSiteConnect = (site: SiteConfig) => {
    // 1. Update State
    setConnection({
      host: site.host,
      port: site.port,
      user: site.user,
      pass: site.pass || '',
      protocol: site.protocol,
      passive: site.passiveMode !== false,
      initialPath: site.initialPath || '',
      connected: false,
      connecting: true
    });
    setShowSiteManager(false);

    // 2. Trigger Connection Immediately
    addLog('command', `CONNECT [${site.protocol.toUpperCase()}] ${site.user}@${site.host}:${site.port} ${site.passiveMode !== false ? '(Passive)' : ''}`);

    if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify({
        command: 'CONNECT',
        host: site.host,
        user: site.user,
        pass: site.pass || '',
        port: site.port,
        protocol: site.protocol,
        passive: site.passiveMode !== false
      }));
    } else {
      addLog('error', '백엔드 서버에 연결되어 있지 않습니다. 도움말을 참고하여 백엔드를 실행하세요.');
      setConnection(prev => ({ ...prev, connecting: false }));

      // Open Help on Backend Tab
      setHelpInitialTab('backend');
      setShowHelp(true);
    }
  };

  const handleSaveSites = (sites: SiteConfig[]) => {
    setSavedSites(sites);
    if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify({
        command: 'SAVE_SITES',
        sites: sites
      }));
    }
  };

  const getDeleteModalData = () => {
    const isLocal = modalTargetIsLocal;
    const ids = isLocal ? selectedLocalIds : selectedRemoteIds;
    const files = isLocal ? local.files : remote.files;
    const selectedFiles = files.filter(f => ids.has(f.id));
    return { count: ids.size, names: selectedFiles.map(f => f.name) };
  };

  return (
    <div className="flex flex-col h-screen bg-slate-50 text-slate-800 font-sans">
      {/* Modals */}

      <SettingsModal
        isOpen={showSettings}
        onClose={() => setShowSettings(false)}
        saveConnectionInfo={saveConnectionInfo}
        onToggleSaveConnectionInfo={setSaveConnectionInfo}
      />
      <HelpModal isOpen={showHelp} onClose={() => setShowHelp(false)} initialTab={helpInitialTab} />
      <SiteManagerModal
        isOpen={showSiteManager}
        onClose={() => setShowSiteManager(false)}
        initialSites={savedSites}
        onSaveSites={handleSaveSites}
        onConnect={handleSiteConnect}
      />
      <CreateFolderModal
        isOpen={activeModal === 'create'}
        onClose={() => setActiveModal(null)}
        onConfirm={handleCreateFolderConfirm}
      />
      <RenameModal
        isOpen={activeModal === 'rename'}
        currentName={renameTargetName}
        onClose={() => setActiveModal(null)}
        onConfirm={handleRenameConfirm}
      />
      <DeleteModal
        isOpen={activeModal === 'delete'}
        fileCount={getDeleteModalData().count}
        fileNames={getDeleteModalData().names}
        onClose={() => setActiveModal(null)}
        onConfirm={handleDeleteConfirm}
      />

      {/* Header */}
      <header className="bg-white border-b border-slate-200 p-2 shadow-sm z-20">
        <div className="flex flex-col xl:flex-row gap-4 items-center">
          <div className="flex items-center gap-2 shrink-0">
            <div className="w-8 h-8 bg-blue-600 rounded flex items-center justify-center font-bold text-white shadow-lg shadow-blue-500/20">WZ</div>
            <span className="font-bold text-lg tracking-tight hidden sm:inline text-slate-700">WebFTP</span>
          </div>

          <div className="flex-1 w-full flex flex-wrap items-center gap-2">
            <button
              onClick={() => setShowSiteManager(true)}
              className="h-[46px] flex flex-col items-center justify-center px-3 gap-0.5 rounded bg-white hover:bg-slate-50 border border-slate-300 text-[10px] font-semibold text-slate-600 transition-colors shadow-sm"
              title="사이트 관리자"
            >
              <BookOpen size={16} className="text-blue-600" />
              <span>사이트</span>
            </button>

            <div className="w-px h-8 bg-slate-200 mx-1"></div>

            <div className="flex flex-col gap-0.5">
              <label className="text-[10px] text-slate-500 font-semibold pl-1">호스트</label>
              <input
                type="text"
                value={connection.host}
                onChange={(e) => setConnection(c => ({ ...c, host: e.target.value }))}
                className="w-48 h-[30px] bg-white border border-slate-300 rounded px-2 text-sm focus:border-blue-500 focus:outline-none placeholder:text-slate-400 shadow-sm"
                placeholder="ftp.example.com"
              />
            </div>
            <div className="flex flex-col gap-0.5">
              <label className="text-[10px] text-slate-500 font-semibold pl-1">사용자</label>
              <input
                type="text"
                value={connection.user}
                onChange={(e) => setConnection(c => ({ ...c, user: e.target.value }))}
                className="w-32 h-[30px] bg-white border border-slate-300 rounded px-2 text-sm focus:border-blue-500 focus:outline-none shadow-sm placeholder:text-slate-400"
                placeholder="user"
              />
            </div>
            <div className="flex flex-col gap-0.5">
              <label className="text-[10px] text-slate-500 font-semibold pl-1">비밀번호</label>
              <input
                type="password"
                value={connection.pass}
                onChange={(e) => setConnection(c => ({ ...c, pass: e.target.value }))}
                className="w-32 h-[30px] bg-white border border-slate-300 rounded px-2 text-sm focus:border-blue-500 focus:outline-none shadow-sm"
              />
            </div>
            <div className="flex flex-col gap-0.5">
              <label className="text-[10px] text-slate-500 font-semibold pl-1">포트 / 패시브</label>
              <div className="flex items-center gap-3">
                <input
                  type="text"
                  value={connection.port}
                  onChange={(e) => setConnection(c => ({ ...c, port: e.target.value }))}
                  className="w-16 h-[30px] bg-white border border-slate-300 rounded px-2 text-sm text-center focus:border-blue-500 focus:outline-none shadow-sm"
                />
                <label className="relative inline-flex items-center cursor-pointer group" title="패시브 모드">
                  <input
                    type="checkbox"
                    className="sr-only peer"
                    checked={connection.passive}
                    onChange={(e) => setConnection(c => ({ ...c, passive: e.target.checked }))}
                  />
                  <div className="w-9 h-5 bg-slate-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:bg-blue-600 after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:after:translate-x-full peer-checked:after:border-white"></div>
                </label>
              </div>
            </div>

            <div className="flex-1"></div>

            <div className="flex items-end gap-2 pb-0.5">
              <button
                onClick={handleConnect}
                disabled={connection.connecting}
                className={`px-4 h-[30px] flex items-center justify-center gap-2 rounded font-semibold text-sm transition-all shadow-md ${connection.connected
                  ? 'bg-red-50 text-red-600 border border-red-200 hover:bg-red-100'
                  : 'bg-blue-600 text-white hover:bg-blue-50 shadow-blue-500/20'
                  }`}
              >
                {connection.connecting ? <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> : (connection.connected ? <><WifiOff size={16} /> 연결 해제</> : '빠른 연결')}
              </button>

              <a
                href={`${import.meta.env.BASE_URL}webftp-backend.exe`}
                download="webftp-backend.exe"
                className={`h-[30px] flex items-center justify-center px-3 rounded bg-emerald-600 hover:bg-emerald-500 text-white border border-emerald-500 shadow-md shadow-emerald-500/20 transition-all ${!connection.connected ? 'animate-pulse ring-2 ring-emerald-400/50' : ''}`}
                title="백엔드 다운로드"
              >
                <Download size={14} className="mr-1.5" /> 백엔드
              </a>

              <button
                onClick={() => setShowHelp(true)}
                className="w-[30px] h-[30px] flex items-center justify-center rounded bg-white border border-slate-300 text-slate-600 hover:text-slate-900 hover:bg-slate-50 shadow-sm"
                title="도움말"
              >
                <HelpCircle size={16} />
              </button>

              <button
                onClick={() => setShowSettings(true)}
                className="w-[30px] h-[30px] flex items-center justify-center rounded bg-white border border-slate-300 text-slate-600 hover:text-slate-900 hover:bg-slate-50 shadow-sm"
              >
                <Settings size={16} />
              </button>
            </div>
          </div>
        </div>
      </header>

      {/* Log View */}
      <div className="h-32 shrink-0 p-2 pb-0 flex gap-2">
        <div className="w-1/2 min-w-0 h-full">
          <LogConsole logs={logs} />
        </div>
        <div className="w-1/2 min-w-0 h-full bg-white border border-slate-300 rounded-lg shadow-sm flex flex-col items-center justify-center relative overflow-hidden group cursor-pointer">
          <div className="absolute top-0 right-0 bg-slate-100 text-[9px] text-slate-500 px-1.5 py-0.5 rounded-bl border-b border-l border-slate-200 z-10">SPONSORED</div>
          <div className="text-slate-300 flex flex-col items-center gap-1 group-hover:text-slate-400 transition-colors">
            <div className="font-bold text-lg tracking-widest flex items-center gap-2"><MousePointerClick size={20} /> GOOGLE ADSENSE</div>
            <div className="text-xs">Premium Ad Space Available</div>
          </div>
          <div className="absolute inset-0 -z-0 opacity-30" style={{ backgroundImage: 'radial-gradient(#cbd5e1 1px, transparent 1px)', backgroundSize: '10px 10px' }}></div>
        </div>
      </div>

      {/* Main Split View */}
      <div className="flex-1 flex flex-col md:flex-row min-h-0 p-2 gap-2">
        {/* Local Pane */}
        <div className="flex-1 min-h-0 flex flex-col min-w-[300px]">
          <FilePane
            title="로컬 (내 컴퓨터)"
            icon="local"
            path={local.path}
            files={local.files}
            isLoading={local.isLoading}
            onNavigate={handleLocalNavigate}
            onNavigateUp={() => handleLocalNavigate(local.path.split(/\/|\\/).slice(0, -1).join(local.path.includes('\\') ? '\\' : '/') || (local.path.includes('\\') ? 'C:\\' : '/'))}
            onSelectionChange={setSelectedLocalIds}
            selectedIds={selectedLocalIds}
            connected={isBackendConnected}
            refreshKey={refreshKey}
            onCreateFolder={() => initiateCreateFolder(true)}
            onDelete={() => initiateDelete(true)}
            onRename={() => initiateRename(true)}
          />
        </div>

        {/* Middle Actions */}
        <div className="flex md:flex-col items-center justify-center gap-2 p-1">
          <button className="p-3 bg-white border border-slate-300 shadow-sm rounded hover:bg-blue-50 text-slate-400">
            <ArrowRight size={24} strokeWidth={2.5} />
          </button>
          <button className="p-3 bg-white border border-slate-300 shadow-sm rounded hover:bg-green-50 text-slate-400">
            <ArrowLeft size={24} strokeWidth={2.5} />
          </button>
        </div>

        {/* Remote Pane */}
        <div className="flex-1 min-h-0 flex flex-col min-w-[300px]">
          <FilePane
            title={`리모트 (${connection.host})`}
            icon="remote"
            path={remote.path}
            files={remote.files}
            isLoading={remote.isLoading}
            onNavigate={handleRemoteNavigate}
            onNavigateUp={() => handleRemoteNavigate(remote.path.split('/').slice(0, -1).join('/') || '/')}
            onSelectionChange={setSelectedRemoteIds}
            selectedIds={selectedRemoteIds}
            connected={connection.connected}
            refreshKey={refreshKey}
            onCreateFolder={() => initiateCreateFolder(false)}
            onDelete={() => initiateDelete(false)}
            onRename={() => initiateRename(false)}
          />
        </div>
      </div>

      {/* Queue */}
      <div className="h-48 shrink-0 p-2 pt-0">
        <TransferQueue queue={queue} />
      </div>

      {/* Footer */}
      <footer className="bg-white border-t border-slate-200 px-3 py-1 text-[10px] text-slate-500 flex justify-between shadow-[0_-2px_10px_rgba(0,0,0,0.02)]">
        <span>WebZilla v1.3.0 <span className="mx-2 text-slate-300">|</span> © SIMP</span>
        <div className="flex gap-4">
          <span>Server: {connection.connected ? 'Connected' : 'Disconnected'}</span>
          <span>Protocol: {connection.protocol.toUpperCase()} {connection.passive ? '(Passive)' : ''}</span>
        </div>
      </footer>
    </div>
  );
};

export default App;