import { useCallback, useEffect, useRef, useState } from "react";
import { Chat } from "./Chat";
import { useWebSocket } from "./useWebSocket";
import type { ChatMessage, ServerMessage, UIButtonData } from "./types";

interface ChatState {
  messages: ChatMessage[];
  isTyping: boolean;
}

type ChatMap = Record<string, ChatState>;

function newChatState(): ChatState {
  return { messages: [], isTyping: false };
}

export function App() {
  const [chats, setChats] = useState<ChatMap>({ C1: newChatState() });
  const [activeChatId, setActiveChatId] = useState("C1");
  const [chatList, setChatList] = useState<string[]>(["C1"]);
  const [chatNames, setChatNames] = useState<Record<string, string>>({ C1: "Чат 1" });
  const [archived, setArchived] = useState<Set<string>>(new Set());
  const [showArchived, setShowArchived] = useState(false);
  const [showHelp, setShowHelp] = useState(false);
  const [showSettings, setShowSettings] = useState(false);
  const [sidebarOpen, setSidebarOpen] = useState(true);
  const [sideWidth, setSideWidth] = useState<number | null>(null);
  const [settingsData, setSettingsData] = useState<{ text: string; buttons?: UIButtonData[] } | null>(null);
  const [settingsView, setSettingsView] = useState<string>("main");
  const [skillsEnabled, setSkillsEnabled] = useState<Record<string, boolean>>({
    "web-search": true, "fetch-url": true, "email": false,
    "browser": false, "image-gen": false, "files": true,
  });
  const [safetyEnabled, setSafetyEnabled] = useState<Record<string, boolean>>({
    "email-send": true, "file-delete": true, "social-post": true,
  });
  const [soulName, setSoulName] = useState("");
  const [soulInstructions, setSoulInstructions] = useState("");
  const [toast, setToast] = useState<string | null>(null);
  const [showLoadDialog, setShowLoadDialog] = useState(false);
  const [showSaveDialog, setShowSaveDialog] = useState(false);
  const [saveName, setSaveName] = useState("");
  const [renameTarget, setRenameTarget] = useState<string | null>(null);
  const [renameName, setRenameName] = useState("");
  const [savedSessions, setSavedSessions] = useState<string[]>([]);
  const toastTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const sidebarRef = useRef<HTMLElement>(null);

  const showToast = useCallback((msg: string) => {
    setToast(msg);
    if (toastTimer.current) clearTimeout(toastTimer.current);
    toastTimer.current = setTimeout(() => setToast(null), 2500);
  }, []);
  const msgIdCounter = useRef(0);
  const settingsModalOpenRef = useRef(false);
  const activeChatIdRef = useRef(activeChatId);
  useEffect(() => { activeChatIdRef.current = activeChatId; }, [activeChatId]);
  useEffect(() => { settingsModalOpenRef.current = showSettings; }, [showSettings]);

  useEffect(() => {
    const saved = localStorage.getItem("web_side_width");
    if (saved) {
      const w = parseInt(saved, 10);
      if (w >= 120 && w <= 400) setSideWidth(w);
    }
  }, []);

  useEffect(() => {
    if (!sideWidth || !sidebarRef.current) return;
    sidebarRef.current.style.width = sideWidth + "px";
  }, [sideWidth]);

  const handleResizeStart = useCallback((e: React.MouseEvent | React.TouchEvent) => {
    const side = sidebarRef.current;
    if (!side) return;
    const startX = "touches" in e ? e.touches[0].clientX : e.clientX;
    const startW = side.getBoundingClientRect().width;
    const onMove = (ev: MouseEvent | TouchEvent) => {
      const x = "touches" in ev ? ev.touches[0].clientX : ev.clientX;
      let w = startW + (x - startX);
      if (w < 120) w = 120;
      if (w > 400) w = 400;
      side.style.width = w + "px";
      setSideWidth(w);
    };
    const onUp = () => {
      if (sidebarRef.current) {
        const w = parseInt(sidebarRef.current.style.width, 10);
        if (w >= 120 && w <= 400) localStorage.setItem("web_side_width", String(w));
      }
      document.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseup", onUp);
      document.removeEventListener("touchmove", onMove);
      document.removeEventListener("touchend", onUp);
      document.body.style.cursor = "";
      document.body.style.userSelect = "";
    };
    document.body.style.cursor = "col-resize";
    document.body.style.userSelect = "none";
    document.addEventListener("mousemove", onMove);
    document.addEventListener("mouseup", onUp);
    document.addEventListener("touchmove", onMove);
    document.addEventListener("touchend", onUp);
    e.preventDefault();
  }, []);

  const handleMessage = useCallback((msg: ServerMessage) => {
    // Capture settings sub-menu responses in modal while it's open
    if (settingsModalOpenRef.current && (msg.type === "message" || msg.type === "ui")) {
      const chatId = msg.chat_id || "C1";
      if (chatId === activeChatIdRef.current) {
        setSettingsData({ text: msg.text, buttons: (msg as any).buttons });
        return;
      }
    }

    if (msg.type === "history") {
      if (msg.chat_names) setChatNames((p) => ({ ...p, ...msg.chat_names }));
      if (msg.archived) setArchived(new Set(msg.archived));
      setChatList((prev) => {
        const ids = new Set(prev);
        Object.keys(msg.chats).forEach((cid) => ids.add(cid));
        return Array.from(ids);
      });
      const loaded: ChatMap = {};
      Object.entries(msg.chats).forEach(([cid, entries]) => {
        loaded[cid] = { messages: [], isTyping: false };
        entries.forEach((e) => {
          loaded[cid].messages.push({
            id: `hist-${msgIdCounter.current++}`,
            chat_id: e.chat_id || cid,
            text: e.text,
            from: e.from,
            timestamp: e.timestamp * 1000,
            attachments: e.attachments,
            buttons: e.buttons,
          });
        });
      });
      setChats((prev) => ({ ...prev, ...loaded }));
      return;
    }

    if (msg.type === "message") {
      const chatId = msg.chat_id || "C1";
      msgIdCounter.current += 1;
      const chatMsg: ChatMessage = {
        id: `msg-${msgIdCounter.current}`,
        chat_id: chatId,
        text: msg.text,
        from: "agent",
        parse_mode: msg.parse_mode,
        timestamp: Date.now(),
        attachments: msg.attachments?.filter((a) => a.download_url),
      };
      setChats((prev) => {
        const ch = prev[chatId] || newChatState();
        return {
          ...prev,
          [chatId]: { ...ch, messages: [...ch.messages, chatMsg], isTyping: false },
        };
      });
    } else if (msg.type === "chat_name") {
      setChatNames((p) => ({ ...p, [msg.chat_id]: msg.name }));
      setChatList((p) => p.includes(msg.chat_id) ? p : [...p, msg.chat_id]);
    } else if (msg.type === "chat_archived") {
      setArchived((p) => new Set(p).add(msg.chat_id));
    } else if (msg.type === "chat_unarchived") {
      setArchived((prev) => { const p = new Set(prev); p.delete(msg.chat_id); return p; });
    } else if (msg.type === "chat_new") {
      setChatList((p) => p.includes(msg.chat_id) ? p : [...p, msg.chat_id]);
      setActiveChatId(msg.chat_id);
    } else if (msg.type === "ui") {
      const chatId = msg.chat_id || "C1";
      msgIdCounter.current += 1;
      setChats((prev) => {
        const ch = prev[chatId] || newChatState();
        return {
          ...prev,
          [chatId]: {
            ...ch,
            messages: [...ch.messages, {
              id: `msg-${msgIdCounter.current}`,
              chat_id: chatId,
              text: msg.text,
              from: "agent" as const,
              buttons: msg.buttons,
              timestamp: Date.now(),
            }],
          },
        };
      });
    } else if (msg.type === "typing") {
      const chatId = msg.chat_id || "C1";
      setChats((prev) => {
        const ch = prev[chatId] || newChatState();
        return { ...prev, [chatId]: { ...ch, isTyping: msg.is_typing } };
      });
    } else if (msg.type === "notification") {
      const chatId = msg.chat_id || "C1";
      msgIdCounter.current += 1;
      setChats((prev) => {
        const ch = prev[chatId] || newChatState();
        return {
          ...prev,
          [chatId]: {
            ...ch,
            messages: [...ch.messages, {
              id: `msg-${msgIdCounter.current}`,
              chat_id: chatId,
              text: `[${msg.level.toUpperCase()}] ${msg.text}`,
              from: "agent" as const,
              timestamp: Date.now(),
            }],
          },
        };
      });
    } else if (msg.type === "sessions") {
      setSavedSessions(msg.sessions.map((s) => s.name));
      setShowLoadDialog(true);
    }
  }, []);

  const { status, userId, send, reconnect } = useWebSocket(handleMessage);

  const handleSendMessage = useCallback(
    (text: string, files?: { filename: string; size: number; mime_type: string; download_url: string }[]) => {
      if (!userId) return;

      if (text.startsWith("/")) {
        const parts = text.slice(1).split(/\s+/);
        const cmd = parts[0].toLowerCase();
        if (cmd === "settings") {
          setShowSettings(true);
          setSettingsView("main");
          setSettingsData(null);
          send({ type: "command", user_id: userId, chat_id: activeChatId, command: "settings", args: parts.slice(1) });
          return;
        }
        if (cmd === "save") {
          if (!parts[1]) { showToast("⚠ Укажите имя: /save <имя>"); return; }
          showToast("💾 Сохраняю контекст...");
        } else if (cmd === "load") {
          if (!parts[1]) { showToast("📂 Используйте кнопку 📂 в хедере для выбора сессии"); return; }
          showToast("📂 Загружаю контекст...");
        } else if (cmd === "context") {
          showToast("📋 Информация о контексте...");
        } else if (cmd === "reset") {
          if (!window.confirm("Сбросить контекст? Агент забудет предыдущий разговор.")) return;
          showToast("🔄 Сброс контекста...");
        }
        msgIdCounter.current += 1;
        setChats((prev) => {
          const ch = prev[activeChatId] || newChatState();
          return { ...prev, [activeChatId]: { ...ch, messages: [...ch.messages, {
            id: `msg-${msgIdCounter.current}`,
            chat_id: activeChatId, text, from: "user" as const,
            timestamp: Date.now(), attachments: files,
          }] } };
        });
        send({ type: "command", user_id: userId, chat_id: activeChatId, command: cmd, args: parts.slice(1) });
        return;
      }

      msgIdCounter.current += 1;
      setChats((prev) => {
        const ch = prev[activeChatId] || newChatState();
        return { ...prev, [activeChatId]: { ...ch, messages: [...ch.messages, {
          id: `msg-${msgIdCounter.current}`,
          chat_id: activeChatId, text, from: "user" as const,
          timestamp: Date.now(), attachments: files,
        }] } };
      });
      send({ type: "message", user_id: userId, chat_id: activeChatId, text });
    },
    [userId, activeChatId, send]
  );

  const handleButtonClick = useCallback(
    (chatId: string, button: { action: string; payload?: Record<string, unknown> }) => {
      if (!userId) return;
      send({ type: "callback", user_id: userId, chat_id: chatId, action: button.action, payload: button.payload });
    },
    [userId, send]
  );

  const handleArchiveChat = useCallback((chatId: string) => {
    if (!userId) return;
    const isArchived = archived.has(chatId);
    if (isArchived) {
      send({ type: "command", user_id: userId, chat_id: chatId, command: "unarchive", args: [] });
      setArchived((prev) => { const p = new Set(prev); p.delete(chatId); return p; });
    } else {
      send({ type: "command", user_id: userId, chat_id: chatId, command: "archive", args: [] });
      setArchived((prev) => new Set(prev).add(chatId));
      if (activeChatId === chatId) {
        const remaining = chatList.filter((id) => id !== chatId && !archived.has(id));
        if (remaining.length > 0) setActiveChatId(remaining[0]);
      }
    }
  }, [userId, send, activeChatId, chatList, archived]);

  const handleDeleteChat = useCallback((chatId: string) => {
    if (!userId) return;
    if (!window.confirm(`Удалить чат «${chatNames[chatId] || chatId}»?`)) return;
    send({ type: "command", user_id: userId, chat_id: chatId, command: "delete", args: [] });
    setChatList((prev) => prev.filter((id) => id !== chatId));
    setChatNames((prev) => { const p = { ...prev }; delete p[chatId]; return p; });
    setChats((prev) => { const p = { ...prev }; delete p[chatId]; return p; });
    setArchived((prev) => { const p = new Set(prev); p.delete(chatId); return p; });
    if (activeChatId === chatId) {
      const remaining = chatList.filter((id) => id !== chatId);
      setActiveChatId(remaining.length > 0 ? remaining[0] : "C1");
    }
  }, [userId, send, activeChatId, chatList, chatNames]);

  const handleNewChat = useCallback(() => {
    if (userId) send({ type: "command", user_id: userId, chat_id: activeChatId, command: "new", args: [] });
  }, [userId, send, activeChatId]);

  const visibleChats = showArchived
    ? [...chatList.filter((id) => !archived.has(id)), ...chatList.filter((id) => archived.has(id))]
    : chatList.filter((id) => !archived.has(id));
  const activeChat = chats[activeChatId] || newChatState();

  return (
    <div className="app">
      <header className="app-header">
        <div className="header-left">
          <button className="btn-icon" onClick={() => setSidebarOpen((p) => !p)} title={sidebarOpen ? "Скрыть панель" : "Показать панель"}>
            {sidebarOpen ? "◀" : "▶"}
          </button>
          <button className="btn-icon btn-help" onClick={() => setShowHelp((p) => !p)} title="Помощь">?</button>
          <h1>λ Lambda Chat</h1>
        </div>
        <div className="header-right">
          <button className="btn-icon btn-save" onClick={() => {
            if (!userId) return;
            setSaveName("");
            setShowSaveDialog(true);
          }} title="Сохранить контекст">💾</button>
          <button className="btn-icon btn-load" onClick={() => {
            if (!userId) return;
            setShowLoadDialog(true);
            send({ type: "command", user_id: userId, chat_id: activeChatId, command: "load", args: [] });
          }} title="Загрузить контекст">📂</button>
          <button className="btn-icon btn-settings" onClick={() => {
            const opening = !showSettings;
            setShowSettings(opening);
            if (opening && userId) {
              setSettingsView("main");
              setSettingsData(null);
              send({ type: "command", user_id: userId, chat_id: activeChatId, command: "settings", args: [] });
            }
          }} title="Настройки">⚙</button>
          <div className="connection-status">
            <span className={`dot dot-${status}`} />
            {status === "connected" ? "Подключено" : status === "connecting" ? "Подключение..." : "Отключено"}
          </div>
        </div>
      </header>

      {toast && <div className="toast">{toast}</div>}

      {showSaveDialog && (
        <div className="modal-overlay" onClick={() => setShowSaveDialog(false)}>
          <div className="modal save-modal" onClick={(e) => e.stopPropagation()}>
            <button className="modal-close" onClick={() => setShowSaveDialog(false)}>×</button>
            <h2>💾 Сохранить контекст</h2>
            <div className="save-input-row">
              <input className="save-input" type="text" placeholder="Введите имя сессии..."
                value={saveName} onChange={(e) => setSaveName(e.target.value)}
                onKeyDown={(e) => { if (e.key === "Enter" && saveName.trim()) {
                  if (!userId) return;
                  send({ type: "command", user_id: userId, chat_id: activeChatId, command: "save", args: [saveName.trim()] });
                  setShowSaveDialog(false);
                  showToast(`💾 Сохраняю «${saveName.trim()}»...`);
                }}}
                autoFocus />
              <button className="btn btn-primary save-confirm"
                disabled={!saveName.trim()}
                onClick={() => {
                  if (!userId || !saveName.trim()) return;
                  send({ type: "command", user_id: userId, chat_id: activeChatId, command: "save", args: [saveName.trim()] });
                  setShowSaveDialog(false);
                  showToast(`💾 Сохраняю «${saveName.trim()}»...`);
                }}>Сохранить</button>
            </div>
          </div>
        </div>
      )}

      {showLoadDialog && (
        <div className="modal-overlay" onClick={() => setShowLoadDialog(false)}>
          <div className="modal load-modal" onClick={(e) => e.stopPropagation()}>
            <button className="modal-close" onClick={() => setShowLoadDialog(false)}>×</button>
            <h2>📂 Загрузить контекст</h2>
            {savedSessions.length === 0
              ? <p className="settings-muted" style={{ textAlign: "center", padding: "16px 0" }}>Нет сохранённых сессий</p>
              : <div className="load-list">
                  {savedSessions.map((name) => (
                    <button key={name} className="load-item btn btn-secondary" onClick={() => {
                      if (!userId) return;
                      send({ type: "command", user_id: userId, chat_id: activeChatId, command: "load", args: [name] });
                      setShowLoadDialog(false);
                      showToast(`📂 Загружаю «${name}»...`);
                    }}>{name}</button>
                  ))}
                </div>
            }
          </div>
        </div>
      )}

      {renameTarget && (
        <div className="modal-overlay" onClick={() => setRenameTarget(null)}>
          <div className="modal rename-modal" onClick={(e) => e.stopPropagation()}>
            <button className="modal-close" onClick={() => setRenameTarget(null)}>×</button>
            <h2>✏️ Переименовать чат</h2>
            <div className="save-input-row">
              <input className="save-input" type="text" placeholder="Новое название..."
                value={renameName} onChange={(e) => setRenameName(e.target.value)}
                onKeyDown={(e) => { if (e.key === "Enter" && renameName.trim()) {
                  if (!userId) return;
                  send({ type: "command", user_id: userId, chat_id: renameTarget, command: "rename", args: [renameName.trim()] });
                  setRenameTarget(null);
                  showToast(`✏️ Переименован в «${renameName.trim()}»`);
                }}}
                autoFocus />
              <button className="btn btn-primary save-confirm"
                disabled={!renameName.trim()}
                onClick={() => {
                  if (!userId || !renameName.trim()) return;
                  send({ type: "command", user_id: userId, chat_id: renameTarget, command: "rename", args: [renameName.trim()] });
                  setRenameTarget(null);
                  showToast(`✏️ Переименован в «${renameName.trim()}»`);
                }}>Переименовать</button>
            </div>
          </div>
        </div>
      )}

      {showHelp && (
        <div className="modal-overlay" onClick={() => setShowHelp(false)}>
          <div className="modal" onClick={(e) => e.stopPropagation()}>
            <button className="modal-close" onClick={() => setShowHelp(false)}>×</button>
            <h2>Команды</h2>
            <table><tbody>
              <tr><td>/start</td><td>Начать диалог заново</td></tr>
              <tr><td>/new</td><td>Создать новый чат</td></tr>
              <tr><td>/chats</td><td>Список чатов</td></tr>
              <tr><td>/rename &lt;имя&gt;</td><td>Переименовать чат</td></tr>
              <tr><td>/archive</td><td>Архивировать чат</td></tr>
              <tr><td>/unarchive</td><td>Восстановить чат из архива</td></tr>
              <tr><td>/settings</td><td>Настройки</td></tr>
              <tr><td>/save [имя]</td><td>Сохранить контекст</td></tr>
              <tr><td>/load [имя]</td><td>Загрузить сохранённый контекст</td></tr>
              <tr><td>/context</td><td>Информация о контексте</td></tr>
              <tr><td>/reset</td><td>Сбросить контекст</td></tr>
            </tbody></table>
          </div>
        </div>
      )}

      {showSettings && (
        <div className="modal-overlay" onClick={() => setShowSettings(false)}>
          <div className="modal settings-modal" onClick={(e) => e.stopPropagation()}>
            <button className="modal-close" onClick={() => setShowSettings(false)}>×</button>

            {settingsView === "main" && (
              <>
                <h2>⚙ Настройки</h2>
                <div className="settings-section">
                  <label>Статус:</label>
                  <span className={`settings-value ${status}`}>{status === "connected" ? "Подключено" : status === "connecting" ? "Подключение..." : "Отключено"}</span>
                  {status === "disconnected" && (
                    <button className="btn btn-secondary settings-reconnect" onClick={reconnect}>Переподключиться</button>
                  )}
                </div>
                <div className="settings-section">
                  <label>Пользователь:</label>
                  <span className="settings-value">{userId || "—"}</span>
                </div>
                <div className="settings-section">
                  <label>Активный чат:</label>
                  <span className="settings-value">{chatNames[activeChatId] || activeChatId}</span>
                </div>
                <div className="settings-section">
                  <label>Всего чатов:</label>
                  <span className="settings-value">{chatList.length}</span>
                </div>

                {settingsData && (
                  <div className="settings-agent">
                    <div className="settings-agent-text">{settingsData.text}</div>
                    {settingsData.buttons && settingsData.buttons.length > 0 && (
                      <div className="btns settings-agent-btns">
                        {settingsData.buttons.map((b, i) => (
                          <button key={i}
                            className={`btn ${b.style === "danger" ? "btn-danger" : b.action === "callback" ? "btn-primary" : "btn-secondary"}`}
                            onClick={() => handleButtonClick(activeChatId, b)}>
                            {b.label}
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                )}

                <div className="settings-categories">
                  <div className="settings-cat-title">Категории</div>
                  <div className="btns settings-cat-btns">
                    <button className="btn btn-secondary" onClick={() => { setSettingsView("skills"); if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "settings_skills", payload: {} }); }}>🛠 Навыки</button>
                    <button className="btn btn-secondary" onClick={() => { setSettingsView("safety"); if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "settings_safety", payload: {} }); }}>🔒 Безопасность</button>
                    <button className="btn btn-secondary" onClick={() => { setSettingsView("soul"); if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "settings_soul", payload: {} }); }}>👤 Личность</button>
                    <button className="btn btn-secondary" onClick={() => { setSettingsView("connectors"); if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "settings_connectors", payload: {} }); }}>🔌 Интеграции</button>
                    <button className="btn btn-secondary" onClick={() => { setSettingsView("plan"); if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "settings_plan", payload: {} }); }}>📊 Тариф</button>
                  </div>
                </div>
              </>
            )}

            {settingsView === "skills" && (
              <>
                <div className="settings-sub-header">
                  <button className="btn-icon" onClick={() => setSettingsView("main")} title="Назад">◀</button>
                  <h2>🛠 Навыки</h2>
                </div>
                {settingsData && settingsData.text && (
                  <div className="settings-agent-text">{settingsData.text}</div>
                )}
                <div className="settings-toggles">
                  {Object.entries(skillsEnabled).map(([key, val]) => (
                    <label key={key} className="toggle-row">
                      <span className="toggle-label">{key}</span>
                      <span className={`toggle-switch ${val ? "on" : "off"}`} onClick={() => {
                        setSkillsEnabled((p) => ({ ...p, [key]: !p[key] }));
                        if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "toggle_skill", payload: { skill: key, enabled: !val } });
                      }}>
                        <span className="toggle-knob" />
                      </span>
                    </label>
                  ))}
                </div>
              </>
            )}

            {settingsView === "safety" && (
              <>
                <div className="settings-sub-header">
                  <button className="btn-icon" onClick={() => setSettingsView("main")} title="Назад">◀</button>
                  <h2>🔒 Безопасность</h2>
                </div>
                {settingsData && settingsData.text && (
                  <div className="settings-agent-text">{settingsData.text}</div>
                )}
                <div className="settings-toggles">
                  {Object.entries(safetyEnabled).map(([key, val]) => (
                    <label key={key} className="toggle-row">
                      <span className="toggle-label">{key}</span>
                      <span className={`toggle-switch ${val ? "on" : "off"}`} onClick={() => {
                        setSafetyEnabled((p) => ({ ...p, [key]: !p[key] }));
                        if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "set_safety", payload: { trigger: key, enabled: !val } });
                      }}>
                        <span className="toggle-knob" />
                      </span>
                    </label>
                  ))}
                </div>
              </>
            )}

            {settingsView === "soul" && (
              <>
                <div className="settings-sub-header">
                  <button className="btn-icon" onClick={() => setSettingsView("main")} title="Назад">◀</button>
                  <h2>👤 Личность</h2>
                </div>
                {settingsData && settingsData.text && (
                  <div className="settings-agent-text">{settingsData.text}</div>
                )}
                <div className="settings-soul-form">
                  <label className="soul-field">
                    <span>Имя</span>
                    <input type="text" value={soulName} onChange={(e) => setSoulName(e.target.value)} placeholder="Имя агента" />
                  </label>
                  <label className="soul-field">
                    <span>Инструкции</span>
                    <textarea value={soulInstructions} onChange={(e) => setSoulInstructions(e.target.value)} placeholder="Опишите характер..." rows={3} />
                  </label>
                  <button className="btn btn-primary" onClick={() => {
                    if (userId) send({ type: "callback", user_id: userId, chat_id: activeChatId, action: "set_soul", payload: { name: soulName, instructions: soulInstructions } });
                  }}>Сохранить</button>
                </div>
              </>
            )}

            {settingsView === "connectors" && (
              <>
                <div className="settings-sub-header">
                  <button className="btn-icon" onClick={() => setSettingsView("main")} title="Назад">◀</button>
                  <h2>🔌 Интеграции</h2>
                </div>
                {settingsData && settingsData.text && (
                  <div className="settings-agent-text">{settingsData.text}</div>
                )}
                <div className="settings-placeholder">
                  <p>Подключение внешних сервисов через OAuth.</p>
                  <p className="settings-muted">Скоро будет доступно</p>
                </div>
              </>
            )}

            {settingsView === "plan" && (
              <>
                <div className="settings-sub-header">
                  <button className="btn-icon" onClick={() => setSettingsView("main")} title="Назад">◀</button>
                  <h2>📊 Тариф</h2>
                </div>
                {settingsData && settingsData.text && (
                  <div className="settings-agent-text">{settingsData.text}</div>
                )}
                <div className="settings-plan">
                  <div className="settings-section">
                    <label>План:</label>
                    <span className="settings-value">Бесплатный</span>
                  </div>
                  <div className="settings-section">
                    <label>Токенов использовано:</label>
                    <span className="settings-value">0 / 1000</span>
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
      )}

      <div className="app-body">
        <aside className={`sidebar ${sidebarOpen ? "" : "collapsed"}`} ref={sidebarRef}>
          <div className="side-resizer" onMouseDown={handleResizeStart} onTouchStart={handleResizeStart}></div>
          <div className="sidebar-header">
            <div className="sidebar-header-left">
              <span>Чаты</span>
            </div>
            <button className="btn-icon btn-add" onClick={handleNewChat} title="Новый чат">+</button>
          </div>
          <div className="sidebar-tabs">
            {visibleChats.map((id) => (
              <div key={id} className={`chat-tab-row ${id === activeChatId ? "active" : ""} ${archived.has(id) ? "archived" : ""}`}
                onClick={() => setActiveChatId(id)}>
                <span className="chat-tab-label">{chatNames[id] || id}</span>
                <span className="chat-tab-actions" onClick={(e) => e.stopPropagation()}>
                  <button className="tab-action archive-action" onClick={() => handleArchiveChat(id)}
                    title={archived.has(id) ? "Разархивировать" : "Архивировать"}>
                    {archived.has(id) ? "📂" : "📁"}
                  </button>
                  <button className="tab-action rename-action" onClick={() => { setRenameTarget(id); setRenameName(chatNames[id] || id); }}
                    title="Переименовать">✏️</button>
                  <button className="tab-action delete-action" onClick={() => handleDeleteChat(id)}
                    title="Удалить чат">🗑</button>
                </span>
              </div>
            ))}
          </div>
          <div className="sidebar-footer">
            <button className="archive-toggle" onClick={archived.size > 0 ? () => setShowArchived((p) => !p) : undefined} disabled={archived.size === 0}>
              {showArchived ? "Скрыть архив" : archived.size > 0 ? `Показать архив (${archived.size})` : "Архив"}
            </button>
            <button className="btn-reconnect" onClick={reconnect} style={{ display: status === "disconnected" ? "block" : "none" }}>Переподключиться</button>
          </div>
        </aside>
        <main className="main">
          <Chat chatId={activeChatId} messages={activeChat.messages} isTyping={activeChat.isTyping}
            userId={userId} onSend={handleSendMessage} onButtonClick={handleButtonClick}
            disabled={status !== "connected"} />
        </main>
      </div>
    </div>
  );
}
