import React, { useEffect, useMemo, useRef, useState } from "react";

const emptySettings = {
  competitorGroups: [""],
  ourGroup: "",
  minIntervalMinutes: 5,
  maxIntervalMinutes: 10,
  dailyLimit: 100,
  historyLimit: 200,
  accountMaxGroups: 10,
  accountDailyLimit: 50,
  floodCooldownMinutes: 1440
};

const emptyTaskForm = {
  id: null,
  name: "",
  ourGroup: "",
  minIntervalMinutes: 5,
  maxIntervalMinutes: 10,
  dailyLimit: 100,
  historyLimit: 200,
  maxCompetitorBots: 2,
  maxOurBots: 10,
  randomAccounts: false,
  multiAccountsPerRun: false,
  retryOnFail: true,
  autoJoinCompetitors: true,
  autoJoinOurGroup: true,
  stopOnBlocked: true,
  stopBlockedPercent: 25,
  notes: "",
  enabled: true,
  autoAssignAccounts: true
};

const normalizeTask = (row) => ({
  id: row.id,
  name: row.name || "",
  ourGroup: row.our_group || "",
  minIntervalMinutes: Number(row.min_interval_minutes || 5),
  maxIntervalMinutes: Number(row.max_interval_minutes || 10),
  dailyLimit: Number(row.daily_limit || 100),
  historyLimit: Number(row.history_limit || 200),
  maxCompetitorBots: Number(row.max_competitor_bots || 1),
  maxOurBots: Number(row.max_our_bots || 1),
  randomAccounts: Boolean(row.random_accounts),
  multiAccountsPerRun: Boolean(row.multi_accounts_per_run),
  retryOnFail: Boolean(row.retry_on_fail),
  autoJoinCompetitors: Boolean(row.auto_join_competitors),
  autoJoinOurGroup: Boolean(row.auto_join_our_group),
  stopOnBlocked: Boolean(row.stop_on_blocked),
  stopBlockedPercent: Number(row.stop_blocked_percent || 25),
  notes: row.notes || "",
  enabled: Boolean(row.enabled)
});

export default function App() {
  const [settings, setSettings] = useState(emptySettings);
  const [accounts, setAccounts] = useState([]);
  const [accountStats, setAccountStats] = useState([]);
  const [accountAssignments, setAccountAssignments] = useState([]);
  const [logs, setLogs] = useState([]);
  const [invites, setInvites] = useState([]);
  const [tasks, setTasks] = useState([]);
  const [selectedTaskId, setSelectedTaskId] = useState(null);
  const [taskForm, setTaskForm] = useState(emptyTaskForm);
  const [competitorText, setCompetitorText] = useState("");
  const [selectedAccountIds, setSelectedAccountIds] = useState([]);
  const [taskStatus, setTaskStatus] = useState({
    running: false,
    queueCount: 0,
    dailyRemaining: 0,
    dailyUsed: 0,
    dailyLimit: 0,
    monitorInfo: { monitoring: false, groups: [], lastMessageAt: "", lastSource: "" }
  });
  const [taskStatusMap, setTaskStatusMap] = useState({});
  const [membershipStatus, setMembershipStatus] = useState({});
  const [accessStatus, setAccessStatus] = useState([]);
  const [accountEvents, setAccountEvents] = useState([]);
  const [loginForm, setLoginForm] = useState({
    apiId: "",
    apiHash: "",
    phone: "",
    code: "",
    password: ""
  });
  const [tdataForm, setTdataForm] = useState({
    apiId: "2040",
    apiHash: "b18441a1ff607e10a989891a5462e627"
  });
  const [tdataResult, setTdataResult] = useState(null);
  const [tdataLoading, setTdataLoading] = useState(false);
  const [loginId, setLoginId] = useState("");
  const [loginStatus, setLoginStatus] = useState("");
  const [taskNotice, setTaskNotice] = useState(null);
  const [settingsNotice, setSettingsNotice] = useState(null);
  const [tdataNotice, setTdataNotice] = useState(null);
  const [notification, setNotification] = useState(null);
  const [notifications, setNotifications] = useState([]);
  const [notificationsOpen, setNotificationsOpen] = useState(false);
  const [manualLoginOpen, setManualLoginOpen] = useState(false);
  const [taskSearch, setTaskSearch] = useState("");
  const [taskFilter, setTaskFilter] = useState("all");
  const [notificationFilter, setNotificationFilter] = useState("all");
  const [infoOpen, setInfoOpen] = useState(false);
  const [activeTab, setActiveTab] = useState("task");
  const [logsTab, setLogsTab] = useState("logs");
  const [logSearch, setLogSearch] = useState("");
  const [inviteSearch, setInviteSearch] = useState("");
  const [logPage, setLogPage] = useState(1);
  const [invitePage, setInvitePage] = useState(1);
  const [inviteFilter, setInviteFilter] = useState("all");
  const [taskSort, setTaskSort] = useState("activity");
  const [sidebarExpanded, setSidebarExpanded] = useState(false);
  const bellRef = useRef(null);

  const competitorGroups = useMemo(() => {
    return competitorText
      .split("\n")
      .map((line) => line.trim())
      .filter((line) => line.length > 0);
  }, [competitorText]);
  const hasSelectedTask = selectedTaskId != null;
  const selectedTask = tasks.find((task) => task.id === selectedTaskId) || null;
  const selectedTaskName = selectedTask ? (selectedTask.name || `Задача #${selectedTask.id}`) : "—";
  const canSaveTask = Boolean(
    taskForm.name.trim() &&
    taskForm.ourGroup.trim() &&
    competitorGroups.length > 0
  );
  const accountById = useMemo(() => {
    const map = new Map();
    accounts.forEach((account) => {
      map.set(account.id, account);
    });
    return map;
  }, [accounts]);
  const assignedAccountMap = useMemo(() => {
    const map = new Map();
    accountAssignments.forEach((row) => {
      const list = map.get(row.account_id) || [];
      list.push(row.task_id);
      map.set(row.account_id, list);
    });
    return map;
  }, [accountAssignments]);
  const filterFreeAccounts = tasks.length > 1;
  const accountBuckets = useMemo(() => {
    const selected = selectedTaskId;
    const freeOrSelected = [];
    const busy = [];
    const taskNameMap = new Map();
    tasks.forEach((task) => {
      taskNameMap.set(task.id, task.name || `Задача #${task.id}`);
    });
    accounts.forEach((account) => {
      const assignedTasks = assignedAccountMap.get(account.id) || [];
      const assignedToSelected = selected != null && assignedTasks.includes(selected);
      const isFree = assignedTasks.length === 0;
      if (filterFreeAccounts && !isFree && !assignedToSelected) {
        busy.push(account);
      } else {
        freeOrSelected.push(account);
      }
    });
    return { freeOrSelected, busy, taskNameMap };
  }, [accounts, assignedAccountMap, selectedTaskId, filterFreeAccounts, tasks]);

  const loadTasks = async () => {
    const tasksData = await window.api.listTasks();
    setTasks(tasksData);
    if (!tasksData.length) {
      setSelectedTaskId(null);
      return tasksData;
    }
    if (selectedTaskId == null) {
      setSelectedTaskId(tasksData[0].id);
      return tasksData;
    }
    if (!tasksData.some((task) => task.id === selectedTaskId)) {
      setSelectedTaskId(tasksData[0].id);
    }
    return tasksData;
  };

  const loadAccountAssignments = async () => {
    if (!window.api) return;
    const assignments = await window.api.listAccountAssignments();
    setAccountAssignments(assignments || []);
  };

  const loadTaskStatuses = async (tasksData) => {
    const entries = await Promise.all(
      (tasksData || []).map(async (task) => {
        const status = await window.api.taskStatus(task.id);
        return [task.id, status];
      })
    );
    const map = {};
    entries.forEach(([id, status]) => {
      map[id] = status;
    });
    setTaskStatusMap(map);
  };

  const loadSelectedTask = async (taskId) => {
    if (!taskId) {
      setTaskForm(emptyTaskForm);
      setCompetitorText("");
      setSelectedAccountIds([]);
      setLogs([]);
      setInvites([]);
      setTaskStatus({
        running: false,
        queueCount: 0,
        dailyRemaining: 0,
        dailyUsed: 0,
        dailyLimit: 0,
        monitorInfo: { monitoring: false, groups: [], lastMessageAt: "", lastSource: "" }
      });
      return;
    }
    const details = await window.api.getTask(taskId);
    if (!details) return;
    setTaskForm({ ...emptyTaskForm, ...normalizeTask(details.task) });
    setCompetitorText((details.competitors || []).join("\n"));
    setSelectedAccountIds(details.accountIds || []);
    setLogs(await window.api.listLogs({ limit: 100, taskId }));
    setInvites(await window.api.listInvites({ limit: 200, taskId }));
    setTaskStatus(await window.api.taskStatus(taskId));
  };

  const loadBase = async () => {
    const [settingsData, accountsData, eventsData, statusData] = await Promise.all([
      window.api.getSettings(),
      window.api.listAccounts(),
      window.api.listAccountEvents(200),
      window.api.getStatus()
    ]);
    setSettings(settingsData);
    setAccounts(accountsData);
    setAccountEvents(eventsData);
    setAccountStats(statusData.accountStats || []);
    const tasksData = await loadTasks();
    await loadAccountAssignments();
    await loadTaskStatuses(tasksData);
  };

  useEffect(() => {
    loadBase();
  }, []);

  useEffect(() => {
    loadSelectedTask(selectedTaskId);
    setAccessStatus([]);
    setMembershipStatus({});
    setTaskNotice(null);
  }, [selectedTaskId]);

  const taskSummary = useMemo(() => {
    const totals = {
      total: tasks.length,
      running: 0,
      queue: 0,
      dailyUsed: 0,
      dailyLimit: 0
    };
    tasks.forEach((task) => {
      const status = taskStatusMap[task.id];
      if (status && status.running) totals.running += 1;
      if (status) {
        totals.queue += Number(status.queueCount || 0);
        totals.dailyUsed += Number(status.dailyUsed || 0);
        totals.dailyLimit += Number(status.dailyLimit || 0);
      }
    });
    return totals;
  }, [tasks, taskStatusMap]);

  const filteredTasks = useMemo(() => {
    const query = taskSearch.trim().toLowerCase();
    const filtered = tasks.filter((task) => {
      const name = (task.name || "").toLowerCase();
      const group = (task.our_group || "").toLowerCase();
      const matchesQuery = !query || name.includes(query) || group.includes(query) || String(task.id).includes(query);
      if (!matchesQuery) return false;
      const status = taskStatusMap[task.id];
      if (taskFilter === "running") return Boolean(status && status.running);
      if (taskFilter === "stopped") return Boolean(status && !status.running);
      return true;
    });
    const sorted = [...filtered].sort((a, b) => {
      const statusA = taskStatusMap[a.id];
      const statusB = taskStatusMap[b.id];
      if (taskSort === "queue") {
        return (statusB ? statusB.queueCount : 0) - (statusA ? statusA.queueCount : 0);
      }
      if (taskSort === "limit") {
        return (statusB ? statusB.dailyLimit : 0) - (statusA ? statusA.dailyLimit : 0);
      }
      if (taskSort === "lastMessage") {
        const dateA = statusA && statusA.monitorInfo && statusA.monitorInfo.lastMessageAt
          ? Date.parse(statusA.monitorInfo.lastMessageAt) || 0
          : 0;
        const dateB = statusB && statusB.monitorInfo && statusB.monitorInfo.lastMessageAt
          ? Date.parse(statusB.monitorInfo.lastMessageAt) || 0
          : 0;
        return dateB - dateA;
      }
      if (taskSort === "activity") {
        const aActive = statusA && statusA.running ? 1 : 0;
        const bActive = statusB && statusB.running ? 1 : 0;
        if (bActive !== aActive) return bActive - aActive;
      }
      if (taskSort === "id") {
        return b.id - a.id;
      }
      return b.id - a.id;
    });
    return sorted;
  }, [tasks, taskSearch, taskFilter, taskSort, taskStatusMap]);

  useEffect(() => {
    const interval = setInterval(async () => {
      const tasksData = await window.api.listTasks();
      setTasks(tasksData);
      await loadTaskStatuses(tasksData);
      setAccounts(await window.api.listAccounts());
      setAccountAssignments(await window.api.listAccountAssignments());
      const statusData = await window.api.getStatus();
      setAccountStats(statusData.accountStats || []);
      setAccountEvents(await window.api.listAccountEvents(200));
      if (selectedTaskId != null) {
        setLogs(await window.api.listLogs({ limit: 100, taskId: selectedTaskId }));
        setInvites(await window.api.listInvites({ limit: 200, taskId: selectedTaskId }));
        setTaskStatus(await window.api.taskStatus(selectedTaskId));
      }
    }, 5000);
    return () => clearInterval(interval);
  }, [selectedTaskId]);

  useEffect(() => {
    if (selectedTaskId == null) return;
    setTaskStatusMap((prev) => ({
      ...prev,
      [selectedTaskId]: taskStatus
    }));
  }, [selectedTaskId, taskStatus]);

  const formatAccountStatus = (status) => {
    if (status === "limited") return "В спаме";
    if (status === "ok") return "ОК";
    return status || "Неизвестно";
  };

  const formatTimestamp = (value) => {
    if (!value) return "—";
    const date = value instanceof Date ? value : new Date(value);
    if (Number.isNaN(date.getTime())) return "—";
    return date.toLocaleString("ru-RU");
  };

  const showNotification = (text, tone) => {
    if (tone === "success") return;
    const entry = { text, tone, id: Date.now() };
    setNotification(entry);
    setNotifications((prev) => [entry, ...prev].slice(0, 6));
  };

  useEffect(() => {
    if (!notification) return undefined;
    const timer = setTimeout(() => {
      setNotification(null);
    }, 6000);
    return () => clearTimeout(timer);
  }, [notification]);

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (!notificationsOpen) return;
      if (!bellRef.current) return;
      if (!bellRef.current.contains(event.target)) {
        setNotificationsOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [notificationsOpen]);

  const filteredNotifications = useMemo(() => {
    if (notificationFilter === "all") return notifications;
    return notifications.filter((item) => item.tone === notificationFilter);
  }, [notifications, notificationFilter]);

  const filteredLogs = useMemo(() => {
    const query = logSearch.trim().toLowerCase();
    if (!query) return logs;
    return logs.filter((log) => {
      const text = [
        log.startedAt,
        log.finishedAt,
        String(log.invitedCount),
        (log.successIds || []).join(","),
        (log.errors || []).join("|")
      ]
        .join(" ")
        .toLowerCase();
      return text.includes(query);
    });
  }, [logs, logSearch]);

  const filteredInvites = useMemo(() => {
    const query = inviteSearch.trim().toLowerCase();
    return invites.filter((invite) => {
      if (inviteFilter === "success" && invite.status !== "success") return false;
      if (inviteFilter === "error" && invite.status === "success") return false;
      if (inviteFilter === "skipped" && !invite.skippedReason) return false;
      const text = [
        invite.invitedAt,
        invite.userId,
        invite.username,
        invite.sourceChat,
        invite.accountPhone,
        invite.error,
        invite.skippedReason
      ]
        .join(" ")
        .toLowerCase();
      if (!query) return true;
      return text.includes(query);
    });
  }, [invites, inviteSearch, inviteFilter]);

  const logPageSize = 20;
  const invitePageSize = 20;
  const logPageCount = Math.max(1, Math.ceil(filteredLogs.length / logPageSize));
  const invitePageCount = Math.max(1, Math.ceil(filteredInvites.length / invitePageSize));
  const pagedLogs = filteredLogs.slice((logPage - 1) * logPageSize, logPage * logPageSize);
  const pagedInvites = filteredInvites.slice((invitePage - 1) * invitePageSize, invitePage * invitePageSize);

  const onSettingsChange = (field, value) => {
    setSettings((prev) => ({
      ...prev,
      [field]: value
    }));
  };

  const resetCooldown = async (accountId) => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    try {
      await window.api.resetAccountCooldown(accountId);
      const updated = await window.api.listAccounts();
      setAccounts(updated);
      setTaskNotice({ text: "Аккаунт снова активен.", tone: "success", source: "accounts" });
    } catch (error) {
      setTaskNotice({ text: error.message || String(error), tone: "error", source: "accounts" });
      showNotification(error.message || String(error), "error");
    }
  };

  const deleteAccount = async (accountId) => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    try {
      await window.api.deleteAccount(accountId);
      setAccounts(await window.api.listAccounts());
      setTaskNotice({ text: "Аккаунт удален.", tone: "success", source: "accounts" });
    } catch (error) {
      setTaskNotice({ text: error.message || String(error), tone: "error", source: "accounts" });
      showNotification(error.message || String(error), "error");
    }
  };

  const refreshIdentity = async () => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    try {
      await window.api.refreshAccountIdentity();
      setAccounts(await window.api.listAccounts());
      setTaskNotice({ text: "ID аккаунтов обновлены.", tone: "success", source: "accounts" });
    } catch (error) {
      setTaskNotice({ text: error.message || String(error), tone: "error", source: "accounts" });
      showNotification(error.message || String(error), "error");
    }
  };

  const saveSettings = async () => {
    if (!window.api) {
      setSettingsNotice({ text: "Electron API недоступен. Откройте приложение в Electron.", tone: "error" });
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    try {
      showNotification("Сохраняем настройки...", "info");
      const updated = await window.api.saveSettings(settings);
      setSettings(updated);
      setSettingsNotice({ text: "Настройки сохранены.", tone: "success" });
    } catch (error) {
      const message = error.message || String(error);
      setSettingsNotice({ text: message, tone: "error" });
      showNotification(message, "error");
    }
  };

  const createTask = () => {
    setSelectedTaskId(null);
    setTaskForm(emptyTaskForm);
    setCompetitorText("");
    setSelectedAccountIds([]);
    setAccessStatus([]);
    setMembershipStatus({});
  };

  const selectTask = (taskId) => {
    if (taskId === selectedTaskId) return;
    setSelectedTaskId(taskId);
  };

  const saveTask = async (source = "editor") => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    try {
      showNotification("Сохраняем задачу...", "info");
      let accountIds = selectedAccountIds;
      if (taskForm.autoAssignAccounts && (!accountIds || accountIds.length === 0)) {
        accountIds = accounts.map((account) => account.id);
        setSelectedAccountIds(accountIds);
        if (accountIds.length) {
          setTaskNotice({ text: `Автоназначены аккаунты: ${accountIds.length}`, tone: "success", source });
        }
      }
      const result = await window.api.saveTask({
        task: taskForm,
        competitors: competitorGroups,
        accountIds
      });
      if (result.ok) {
        setTaskNotice({ text: "Задача сохранена.", tone: "success", source });
        await loadTasks();
        await loadAccountAssignments();
        setSelectedTaskId(result.taskId);
      } else {
        showNotification(result.error || "Не удалось сохранить задачу", "error");
      }
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const deleteTask = async () => {
    if (!window.api || selectedTaskId == null) {
      return;
    }
    try {
      await window.api.deleteTask(selectedTaskId);
      setTaskNotice({ text: "Задача удалена.", tone: "success", source: "tasks" });
      await loadTasks();
      await loadAccountAssignments();
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const startTask = async (source = "sidebar") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    showNotification("Запуск...", "info");
    try {
      const result = await window.api.startTaskById(selectedTaskId);
      if (result && result.ok) {
        setTaskNotice({ text: "Запущено.", tone: "success", source });
      } else {
        showNotification(result.error || "Не удалось запустить", "error");
      }
    } catch (error) {
      const message = error.message || String(error);
      setTaskNotice({ text: message, tone: "error", source });
      showNotification(message, "error");
    }
  };

  const startAllTasks = async () => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    if (!tasks.length) {
      showNotification("Нет задач для запуска.", "info");
      return;
    }
    showNotification("Запускаем все задачи...", "info");
    try {
      const result = await window.api.startAllTasks();
      if (result && result.errors && result.errors.length) {
        const errorText = result.errors.map((item) => `${item.id}: ${item.error}`).join(" | ");
        showNotification(`Ошибки запуска: ${errorText}`, "error");
      }
      const tasksData = await loadTasks();
      await loadTaskStatuses(tasksData);
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const stopTask = async (source = "sidebar") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    if (!window.confirm(`Остановить задачу: ${selectedTaskName}?`)) {
      return;
    }
    showNotification("Остановка...", "info");
    try {
      await window.api.stopTaskById(selectedTaskId);
      setTaskNotice({ text: "Остановлено.", tone: "success", source });
    } catch (error) {
      const message = error.message || String(error);
      setTaskNotice({ text: message, tone: "error", source });
      showNotification(message, "error");
    }
  };

  const stopAllTasks = async () => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    if (!tasks.length) {
      showNotification("Нет задач для остановки.", "info");
      return;
    }
    if (!window.confirm("Остановить все задачи?")) {
      return;
    }
    showNotification("Останавливаем все задачи...", "info");
    try {
      await window.api.stopAllTasks();
      const tasksData = await loadTasks();
      await loadTaskStatuses(tasksData);
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const parseHistory = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    showNotification("Собираем историю...", "info");
    try {
      const result = await window.api.parseHistoryByTask(selectedTaskId);
      if (result && result.ok) {
        setTaskNotice({ text: "История добавлена в очередь.", tone: "success", source });
        if (result.errors && result.errors.length) {
          showNotification(`Ошибки истории: ${result.errors.join(" | ")}`, "error");
        }
        setLogs(await window.api.listLogs({ limit: 100, taskId: selectedTaskId }));
        setInvites(await window.api.listInvites({ limit: 200, taskId: selectedTaskId }));
        return;
      }
      const message = result.error || "Ошибка при сборе истории";
      setTaskNotice({ text: message, tone: "error", source });
      showNotification(message, "error");
    } catch (error) {
      const message = error.message || String(error);
      setTaskNotice({ text: message, tone: "error", source });
      showNotification(message, "error");
    }
  };

  const refreshMembership = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    showNotification("Проверяем участие аккаунтов...", "info");
    try {
      const status = await window.api.membershipStatusByTask(selectedTaskId);
      const map = {};
      status.forEach((item) => {
        map[item.accountId] = item;
      });
      setMembershipStatus(map);
    setTaskNotice({ text: "Статус участия обновлен.", tone: "success", source });
  } catch (error) {
    const message = error.message || String(error);
    setTaskNotice({ text: message, tone: "error", source });
    showNotification(message, "error");
  }
  };

  const checkAccess = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    showNotification("Проверяем доступ к группам...", "info");
    try {
      const result = await window.api.checkAccessByTask(selectedTaskId);
      if (!result.ok) {
        showNotification(result.error || "Не удалось проверить доступ", "error");
        return;
      }
      setAccessStatus(result.result || []);
    setTaskNotice({ text: "Проверка доступа завершена.", tone: "success", source });
  } catch (error) {
    showNotification(error.message || String(error), "error");
  }
  };

  const clearLogs = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    try {
      await window.api.clearLogs(selectedTaskId);
      setLogs([]);
      setTaskNotice({ text: "Логи очищены.", tone: "success", source });
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const clearInvites = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    try {
      await window.api.clearInvites(selectedTaskId);
      setInvites([]);
      setTaskNotice({ text: "История инвайтов очищена.", tone: "success", source });
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const exportLogs = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    try {
      const result = await window.api.exportLogs(selectedTaskId);
      if (result && result.canceled) return;
      setTaskNotice({ text: `Логи выгружены: ${result.filePath}`, tone: "success", source });
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const exportInvites = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    try {
      const result = await window.api.exportInvites(selectedTaskId);
      if (result && result.canceled) return;
      setTaskNotice({ text: `История инвайтов выгружена: ${result.filePath}`, tone: "success", source });
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const clearQueue = async (source = "editor") => {
    if (!window.api || selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    try {
      await window.api.clearQueue(selectedTaskId);
      const data = await window.api.taskStatus(selectedTaskId);
      setTaskStatus(data);
      setTaskNotice({ text: "Очередь очищена.", tone: "success", source });
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const clearDatabase = async () => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    if (!window.confirm("Удалить все данные из базы? Это действие нельзя отменить.")) {
      return;
    }
    try {
      await window.api.clearDatabase();
      showNotification("База очищена.", "info");
      setSelectedTaskId(null);
      setTaskForm(emptyTaskForm);
      setCompetitorText("");
      setSelectedAccountIds([]);
      setLogs([]);
      setInvites([]);
      setTaskStatus({
        running: false,
        queueCount: 0,
        dailyRemaining: 0,
        dailyUsed: 0,
        dailyLimit: 0,
        monitorInfo: { monitoring: false, groups: [], lastMessageAt: "", lastSource: "" }
      });
      await loadBase();
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const toggleAccountSelection = (accountId) => {
    setSelectedAccountIds((prev) => {
      if (prev.includes(accountId)) {
        return prev.filter((id) => id !== accountId);
      }
      return [...prev, accountId];
    });
  };

  const assignAccountsToTask = async (accountIds) => {
    if (!window.api || selectedTaskId == null) return;
    if (!accountIds.length) return;
    const result = await window.api.appendTaskAccounts({
      taskId: selectedTaskId,
      accountIds
    });
    if (result && result.ok) {
      setSelectedAccountIds(result.accountIds || []);
      await loadAccountAssignments();
    }
  };

  const moveAccountToTask = async (accountId) => {
    if (!window.api || selectedTaskId == null) return;
    await assignAccountsToTask([accountId]);
    setTaskNotice({ text: "Аккаунт добавлен в задачу.", tone: "success", source: "accounts" });
  };

  const removeAccountFromTask = async (accountId) => {
    if (!window.api || selectedTaskId == null) return;
    const result = await window.api.removeTaskAccount({
      taskId: selectedTaskId,
      accountId
    });
    if (result && result.ok) {
      setSelectedAccountIds(result.accountIds || []);
      await loadAccountAssignments();
      setTaskNotice({ text: "Аккаунт удален из задачи.", tone: "success", source: "accounts" });
    }
  };

  const startLogin = async () => {
    if (!window.api) {
      setLoginStatus("Electron API недоступен. Откройте приложение в Electron.");
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    if (selectedTaskId == null) {
      setLoginStatus("Сначала выберите задачу.");
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    setLoginStatus("Отправляем код...");
    showNotification("Отправляем код...", "info");
    try {
      const result = await window.api.startLogin({
        apiId: loginForm.apiId,
        apiHash: loginForm.apiHash,
        phone: loginForm.phone
      });
      setLoginId(result.loginId);
      setLoginStatus("Код отправлен. Введите код для входа.");
      showNotification("Код отправлен. Введите код для входа.", "success");
    } catch (error) {
      const message = error.message || String(error);
      setLoginStatus(message);
      showNotification(message, "error");
    }
  };

  const completeLogin = async () => {
    if (!window.api) {
      setLoginStatus("Electron API недоступен. Откройте приложение в Electron.");
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    if (selectedTaskId == null) {
      setLoginStatus("Сначала выберите задачу.");
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    setLoginStatus("Завершаем вход...");
    showNotification("Завершаем вход...", "info");
    const result = await window.api.completeLogin({
      loginId,
      code: loginForm.code,
      password: loginForm.password
    });

    if (result.ok) {
      setLoginStatus("Аккаунт добавлен.");
      setLoginId("");
      setLoginForm({ apiId: "", apiHash: "", phone: "", code: "", password: "" });
      await assignAccountsToTask([result.accountId].filter(Boolean));
      setAccounts(await window.api.listAccounts());
      return;
    }

    if (result.error === "DUPLICATE_ACCOUNT") {
      setLoginStatus("Аккаунт уже добавлен. Привязан к задаче.");
      setLoginId("");
      setLoginForm({ apiId: "", apiHash: "", phone: "", code: "", password: "" });
      await assignAccountsToTask([result.accountId].filter(Boolean));
      setAccounts(await window.api.listAccounts());
      return;
    }

    if (result.error === "PASSWORD_REQUIRED") {
      setLoginStatus("Нужен пароль 2FA. Введите пароль.");
      showNotification("Нужен пароль 2FA. Введите пароль.", "info");
      return;
    }

    setLoginStatus(result.error || "Ошибка входа");
    showNotification(result.error || "Ошибка входа", "error");
  };

  const importTdata = async () => {
    if (!window.api) {
      showNotification("Electron API недоступен. Откройте приложение в Electron.", "error");
      return;
    }
    if (selectedTaskId == null) {
      showNotification("Сначала выберите задачу.", "error");
      return;
    }
    showNotification("Импортируем tdata...", "info");
    setTdataLoading(true);
    try {
      const result = await window.api.importTdata({
        apiId: tdataForm.apiId,
        apiHash: tdataForm.apiHash,
        taskId: selectedTaskId
      });
      if (result && result.canceled) return;
      if (!result.ok) {
        showNotification(result.error || "Ошибка импорта tdata", "error");
        return;
      }
      setTdataResult(result);
      const importedCount = (result.imported || []).length;
      const skippedCount = (result.skipped || []).length;
      const failedCount = (result.failed || []).length;
      const importedIds = (result.imported || []).map((item) => item.accountId).filter(Boolean);
      const skippedIds = (result.skipped || []).map((item) => item.accountId).filter(Boolean);
      if (importedIds.length || skippedIds.length) {
        await assignAccountsToTask([...importedIds, ...skippedIds]);
      }
      if (importedCount > 0) {
        setTdataNotice({ text: `Импортировано аккаунтов: ${importedCount}`, tone: "success" });
      } else if (skippedCount > 0 && failedCount === 0) {
        setTdataNotice({ text: `Пропущено дубликатов: ${skippedCount}`, tone: "success" });
      }
      if (failedCount > 0) {
        showNotification(`Не удалось импортировать: ${failedCount}`, "error");
      }
      setAccounts(await window.api.listAccounts());
    } catch (error) {
      showNotification(error.message || String(error), "error");
    } finally {
      setTdataLoading(false);
    }
  };

  return (
    <div className="app">
      <header className="header">
        <div>
          <h1>Автоматизация инвайтов</h1>
          <p>Парсинг сообщений и приглашения в целевые группы.</p>
        </div>
        <div className="header-actions">
          <div className="task-switcher">
            <div className="task-switcher-label">Текущая задача</div>
            <select
              value={selectedTaskId || ""}
              onChange={(event) => selectTask(event.target.value ? Number(event.target.value) : null)}
            >
              <option value="">Задача не выбрана</option>
              {tasks.map((task) => (
                <option key={task.id} value={task.id}>
                  {task.name || `Задача #${task.id}`}
                </option>
              ))}
            </select>
          </div>
          <div className="global-actions">
            <button
              type="button"
              className="primary"
              onClick={startAllTasks}
              disabled={!tasks.length}
            >
              Запустить все
            </button>
            <button
              type="button"
              className="danger"
              onClick={stopAllTasks}
              disabled={!tasks.length}
            >
              Остановить все
            </button>
          </div>
          <button type="button" className="danger" onClick={clearDatabase}>
            Очистить БД
          </button>
          <div className="notification-bell" ref={bellRef}>
            <button
              type="button"
              className={`icon-btn secondary ${notificationsOpen ? "active" : ""}`}
              onClick={() => setNotificationsOpen((prev) => !prev)}
            >
              🔔
            </button>
            {notifications.length > 0 && (
              <span className="bell-badge">{notifications.length}</span>
            )}
            {notificationsOpen && (
              <div className="bell-panel">
                <div className="bell-header">
                  <span>Уведомления</span>
                  <button type="button" className="ghost" onClick={() => setNotifications([])}>
                    Очистить
                  </button>
                </div>
                <div className="bell-filters">
                  <button
                    type="button"
                    className={`chip ${notificationFilter === "all" ? "active" : ""}`}
                    onClick={() => setNotificationFilter("all")}
                  >
                    Все
                  </button>
                  <button
                    type="button"
                    className={`chip ${notificationFilter === "error" ? "active" : ""}`}
                    onClick={() => setNotificationFilter("error")}
                  >
                    Ошибки
                  </button>
                  <button
                    type="button"
                    className={`chip ${notificationFilter === "info" ? "active" : ""}`}
                    onClick={() => setNotificationFilter("info")}
                  >
                    Инфо
                  </button>
                </div>
                {filteredNotifications.length === 0 && <div className="empty">Пока пусто.</div>}
                {filteredNotifications.map((item) => (
                  <div key={item.id} className={`notice ${item.tone}`}>
                    {item.text}
                  </div>
                ))}
              </div>
            )}
          </div>
          <button
            type="button"
            className={`icon-btn secondary ${infoOpen ? "active" : ""}`}
            onClick={() => setInfoOpen(true)}
          >
            ℹ️
          </button>
        </div>
      </header>
      {infoOpen && (
        <div className="modal-overlay" onClick={() => setInfoOpen(false)}>
          <div className="modal" onClick={(event) => event.stopPropagation()}>
            <div className="row-header">
              <h2>Как пользоваться</h2>
              <button className="ghost" type="button" onClick={() => setInfoOpen(false)}>Закрыть</button>
            </div>
            <ol className="help-list">
              <li>Создайте задачу: название, наша группа и группы конкурентов.</li>
              <li>Выберите аккаунты для задачи и сохраните.</li>
              <li>Нажмите “Собрать историю”, чтобы добавить авторов из последних сообщений.</li>
              <li>Нажмите “Запустить”, чтобы отслеживать новые сообщения и приглашать по расписанию.</li>
              <li>Создавайте несколько задач для разных групп и контролируйте их по списку.</li>
            </ol>
            <p className="help-note">
              “Собрать историю” добавляет в очередь пользователей, которые писали ранее. Без этого будут учитываться только новые сообщения.
            </p>
          </div>
        </div>
      )}

      <div className="top-row">
        <section className="card task-accounts">
          <div className="row-header">
            <h2>Аккаунты задачи</h2>
          </div>
          <div className="login-box">
            <div className="row-header">
              <h3>Добавить аккаунт по коду</h3>
              <button className="ghost" type="button" onClick={() => setManualLoginOpen(!manualLoginOpen)}>
                {manualLoginOpen ? "Свернуть" : "Развернуть"}
              </button>
            </div>
            {manualLoginOpen && (
              <div className="collapsible">
                {!hasSelectedTask && (
                  <div className="hint">Выберите задачу, чтобы добавить аккаунт.</div>
                )}
                <div className="row">
                  <label>
                    <span className="label-line">API ID <span className="required">*</span></span>
                    <input
                      type="text"
                      value={loginForm.apiId}
                      onChange={(event) => setLoginForm({ ...loginForm, apiId: event.target.value })}
                    />
                  </label>
                  <label>
                    <span className="label-line">API Hash <span className="required">*</span></span>
                    <input
                      type="text"
                      value={loginForm.apiHash}
                      onChange={(event) => setLoginForm({ ...loginForm, apiHash: event.target.value })}
                    />
                  </label>
                </div>
                <label>
                  <span className="label-line">Телефон <span className="required">*</span></span>
                  <input
                    type="text"
                    value={loginForm.phone}
                    onChange={(event) => setLoginForm({ ...loginForm, phone: event.target.value })}
                  />
                </label>
                <div className="row">
                  <label>
                    <span className="label-line">Код <span className="required">*</span></span>
                    <input
                      type="text"
                      value={loginForm.code}
                      onChange={(event) => setLoginForm({ ...loginForm, code: event.target.value })}
                    />
                  </label>
                  <label>
                    <span className="label-line">2FA пароль <span className="optional">необязательно</span></span>
                    <input
                      type="password"
                      value={loginForm.password}
                      onChange={(event) => setLoginForm({ ...loginForm, password: event.target.value })}
                    />
                  </label>
                </div>
                <div className="row actions">
                  <button className="secondary" onClick={startLogin} disabled={!hasSelectedTask}>Отправить код</button>
                  <button className="primary" onClick={completeLogin} disabled={!hasSelectedTask}>Подтвердить</button>
                </div>
                {loginStatus && <div className="status-text">{loginStatus}</div>}
              </div>
            )}
          </div>

          <div className="login-box">
            <h3>Импорт из tdata</h3>
            <div className="hint">
              Можно выбрать сразу несколько папок. Значения по умолчанию — API Telegram Desktop.
            </div>
            <div className="row">
              <label>
                <span className="label-line">API ID</span>
                <input
                  type="text"
                  value={tdataForm.apiId}
                  onChange={(event) => setTdataForm({ ...tdataForm, apiId: event.target.value })}
                />
              </label>
              <label>
                <span className="label-line">API Hash</span>
                <input
                  type="text"
                  value={tdataForm.apiHash}
                  onChange={(event) => setTdataForm({ ...tdataForm, apiHash: event.target.value })}
                />
              </label>
            </div>
            <button className="primary" onClick={importTdata} disabled={!hasSelectedTask || tdataLoading}>
              {tdataLoading ? "Импортируем..." : "Импортировать tdata"}
            </button>
            {tdataLoading && <div className="status-text">Идет импорт, это может занять несколько секунд.</div>}
            {tdataNotice && (
              <div className={`notice inline ${tdataNotice.tone}`}>{tdataNotice.text}</div>
            )}
            {tdataResult && (
              <div className="tdata-report">
                <div>Импортировано: {(tdataResult.imported || []).length}</div>
                <div>Пропущено: {(tdataResult.skipped || []).length}</div>
                <div>Ошибок: {(tdataResult.failed || []).length}</div>
                {(tdataResult.failed || []).length > 0 && (
                  <div className="tdata-errors">
                    {tdataResult.failed.map((item, index) => (
                      <div key={`${item.path}-${index}`} className="tdata-error-row">
                        <div className="tdata-error-path">{item.path}</div>
                        <div className="tdata-error-text">{item.error}</div>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )}
          </div>
        </section>

        <section className="card overview">
          <div className="row-header">
            <h2>Общий обзор</h2>
            <div className="status-caption">Все задачи</div>
          </div>
          <div className="summary-grid">
            <div className="summary-card">
              <div className="live-label">Всего задач</div>
              <div className="summary-value">{taskSummary.total}</div>
            </div>
            <div className="summary-card">
              <div className="live-label">Запущено</div>
              <div className="summary-value">{taskSummary.running}</div>
            </div>
            <div className="summary-card">
              <div className="live-label">Очередь</div>
              <div className="summary-value">{taskSummary.queue}</div>
            </div>
            <div className="summary-card">
              <div className="live-label">Лимит в день</div>
              <div className="summary-value">{taskSummary.dailyUsed}/{taskSummary.dailyLimit}</div>
            </div>
          </div>
        </section>
      </div>

      {notification && (
        <div className={`notice ${notification.tone}`}>
          {notification.text}
        </div>
      )}

      <div className="layout">
        <aside className="sidebar left">
          <section className="card sticky">
            <div className="row-header">
              <h2>Задачи</h2>
              <button className="ghost" type="button" onClick={createTask}>Новая задача</button>
            </div>
            <div className="task-search">
              <input
                type="text"
                value={taskSearch}
                onChange={(event) => setTaskSearch(event.target.value)}
                placeholder="Поиск по названию или ссылке"
              />
            </div>
            <div className="task-filters">
              <button
                type="button"
                className={`chip ${taskFilter === "all" ? "active" : ""}`}
                onClick={() => setTaskFilter("all")}
              >
                Все
              </button>
              <button
                type="button"
                className={`chip ${taskFilter === "running" ? "active" : ""}`}
                onClick={() => setTaskFilter("running")}
              >
                Запущены
              </button>
              <button
                type="button"
                className={`chip ${taskFilter === "stopped" ? "active" : ""}`}
                onClick={() => setTaskFilter("stopped")}
              >
                Остановлены
              </button>
            </div>
            <div className="row-inline">
              <label className="select-inline">
                <span>Сортировка</span>
                <select value={taskSort} onChange={(event) => setTaskSort(event.target.value)}>
                  <option value="activity">Активные сверху</option>
                  <option value="queue">По очереди</option>
                  <option value="limit">По лимиту</option>
                  <option value="lastMessage">По последнему сообщению</option>
                  <option value="id">По ID</option>
                </select>
              </label>
            </div>
            <div className="task-list">
              {filteredTasks.length === 0 && <div className="empty">Совпадений нет.</div>}
              {filteredTasks.map((task) => {
                const status = taskStatusMap[task.id];
                const statusLabel = status ? (status.running ? "Запущено" : "Остановлено") : "—";
                const statusClass = status ? (status.running ? "ok" : "off") : "off";
                const queueLabel = status ? `Очередь: ${status.queueCount}` : "Очередь: —";
                const dailyLabel = status ? `Лимит: ${status.dailyUsed}/${status.dailyLimit}` : "Лимит: —";
                const lastMessageRaw = status && status.monitorInfo && status.monitorInfo.lastMessageAt
                  ? status.monitorInfo.lastMessageAt
                  : "";
                const lastMessage = formatTimestamp(lastMessageRaw);
                const lastSource = status && status.monitorInfo && status.monitorInfo.lastSource
                  ? status.monitorInfo.lastSource
                  : "—";
                const monitoring = Boolean(status && status.monitorInfo && status.monitorInfo.monitoring);
                const monitorAccountId = status && status.monitorInfo ? status.monitorInfo.accountId : 0;
                const monitorAccount = monitorAccountId ? accountById.get(monitorAccountId) : null;
                const monitorLabel = monitorAccount
                  ? (monitorAccount.phone || monitorAccount.user_id || String(monitorAccountId))
                  : (monitorAccountId ? String(monitorAccountId) : "—");
                const tooltip = [
                  `Статус: ${statusLabel}`,
                  `Очередь: ${status ? status.queueCount : "—"}`,
                  `Лимит: ${status ? `${status.dailyUsed}/${status.dailyLimit}` : "—"}`,
                  `Мониторинг: ${monitoring ? "активен" : "нет"}`,
                  `Мониторит: ${monitorLabel}`,
                  `Последнее: ${lastMessage}`,
                  `Источник: ${lastSource}`
                ].join(" | ");
                return (
                  <button
                    key={task.id}
                    type="button"
                    className={`task-item ${selectedTaskId === task.id ? "active" : ""}`}
                    onClick={() => selectTask(task.id)}
                    title={tooltip}
                  >
                    <div className="task-info">
                      <div className="task-title">{task.name || `Задача #${task.id}`}</div>
                      <div className="task-meta">{queueLabel}</div>
                      <div className="task-meta">{dailyLabel}</div>
                    </div>
                    <div className="task-actions">
                      <div className={`task-status ${statusClass}`}>{statusLabel}</div>
                    </div>
                  </button>
                );
              })}
            </div>
            <div className="sidebar-actions">
              <button className="danger" type="button" onClick={deleteTask} disabled={!hasSelectedTask}>Удалить задачу</button>
            </div>
            {taskNotice && taskNotice.source === "tasks" && (
              <div className={`notice inline ${taskNotice.tone}`}>{taskNotice.text}</div>
            )}
          </section>
        </aside>

        <div className="main">
          <div className="tabs">
            <button
              type="button"
              className={`tab ${activeTab === "task" ? "active" : ""}`}
              onClick={() => setActiveTab("task")}
            >
              Задача
            </button>
            <button
              type="button"
              className={`tab ${activeTab === "accounts" ? "active" : ""}`}
              onClick={() => setActiveTab("accounts")}
            >
              Аккаунты
            </button>
            <button
              type="button"
              className={`tab ${activeTab === "logs" ? "active" : ""}`}
              onClick={() => setActiveTab("logs")}
            >
              Логи
            </button>
            <button
              type="button"
              className={`tab ${activeTab === "events" ? "active" : ""}`}
              onClick={() => setActiveTab("events")}
            >
              События
            </button>
            <button
              type="button"
              className={`tab ${activeTab === "settings" ? "active" : ""}`}
              onClick={() => setActiveTab("settings")}
            >
              Настройки
            </button>
          </div>

          {activeTab === "task" && (
            <>
              <section className="card live">
                <div className="row-header">
                  <h2>Статус задачи</h2>
                  <div className="status-caption">Для: {selectedTaskName}</div>
                </div>
                <div className="hint">Отображаются данные только для выбранной задачи.</div>
                <div className="live-grid">
                  <div>
                    <div className="live-label">Состояние</div>
                    <div className="live-value">{taskStatus.running ? "Запущено" : "Остановлено"}</div>
                  </div>
                  <div>
                    <div className="live-label">Наблюдение</div>
                    <div className="live-value">{taskStatus.monitorInfo && taskStatus.monitorInfo.monitoring ? "Активно" : "Нет"}</div>
                  </div>
                  <div>
                    <div className="live-label">Группы в мониторинге</div>
                    <div className="live-value">{taskStatus.monitorInfo && taskStatus.monitorInfo.groups ? taskStatus.monitorInfo.groups.length : 0}</div>
                  </div>
                  <div>
                    <div className="live-label">Мониторит</div>
                    <div className="live-value">
                      {(() => {
                        const monitorId = taskStatus.monitorInfo ? taskStatus.monitorInfo.accountId : 0;
                        const account = monitorId ? accountById.get(monitorId) : null;
                        if (!monitorId) return "—";
                        return account ? (account.phone || account.user_id || String(monitorId)) : String(monitorId);
                      })()}
                    </div>
                  </div>
                  <div>
                    <div className="live-label">Последнее сообщение</div>
                    <div className="live-value">{formatTimestamp(taskStatus.monitorInfo ? taskStatus.monitorInfo.lastMessageAt : "")}</div>
                  </div>
                  <div>
                    <div className="live-label">Источник</div>
                    <div className="live-value wrap">{taskStatus.monitorInfo && taskStatus.monitorInfo.lastSource ? taskStatus.monitorInfo.lastSource : "—"}</div>
                  </div>
                  <div>
                    <div className="live-label">Очередь инвайтов</div>
                    <div className="live-value">{taskStatus.queueCount}</div>
                  </div>
                  <div>
                    <div className="live-label">Лимит в день</div>
                    <div className="live-value">{taskStatus.dailyUsed}/{taskStatus.dailyLimit}</div>
                  </div>
                  <div>
                    <div className="live-label">Осталось сегодня</div>
                    <div className="live-value">{taskStatus.dailyRemaining}</div>
                  </div>
                </div>
              </section>

              <section className="card task-editor">
                <div className="row-header">
                  <h2>Настройки задачи</h2>
                  <div className="status-caption">Для: {selectedTaskName}</div>
                </div>
                <div className="row-inline">
                  <button className="secondary" onClick={() => saveTask("editor")} disabled={!canSaveTask}>Сохранить задачу</button>
                  <button className="secondary" onClick={() => parseHistory("editor")} disabled={!hasSelectedTask}>Собрать историю</button>
                  <button className="secondary" onClick={() => checkAccess("editor")} disabled={!hasSelectedTask}>Проверить доступ</button>
                  <button className="secondary" onClick={() => refreshMembership("editor")} disabled={!hasSelectedTask}>Проверить участие</button>
                </div>
                {taskNotice && taskNotice.source === "editor" && (
                  <div className={`notice inline ${taskNotice.tone}`}>{taskNotice.text}</div>
                )}
                <div className="section-title">Основное</div>
                <div className="row">
                  <label>
                    <span className="label-line">Название задачи <span className="required">*</span></span>
                    <input
                      type="text"
                      value={taskForm.name}
                      onChange={(event) => setTaskForm({ ...taskForm, name: event.target.value })}
                      placeholder="Например, Таиланд"
                    />
                  </label>
                  <label>
                    <span className="label-line">Наша группа <span className="required">*</span></span>
                    <input
                      type="text"
                      value={taskForm.ourGroup}
                      onChange={(event) => setTaskForm({ ...taskForm, ourGroup: event.target.value })}
                      placeholder="https://t.me/..."
                    />
                  </label>
                </div>
                <label>
                  <span className="label-line">Группы конкурентов <span className="required">*</span></span>
                  <textarea
                    rows="6"
                    value={competitorText}
                    onChange={(event) => setCompetitorText(event.target.value)}
                    placeholder="Каждая группа с новой строки"
                  />
                </label>
                <div className="section-title">Авто-вступление</div>
                <div className="toggle-row">
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.autoJoinCompetitors)}
                      onChange={(event) => setTaskForm({ ...taskForm, autoJoinCompetitors: event.target.checked })}
                    />
                    Автодобавление аккаунтов в группы конкурентов
                  </label>
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.autoJoinOurGroup)}
                      onChange={(event) => setTaskForm({ ...taskForm, autoJoinOurGroup: event.target.checked })}
                    />
                    Автодобавление аккаунтов в нашу группу
                  </label>
                </div>
                <div className="section-title">Интервалы и лимиты</div>
                <div className="row">
                  <label>
                    <span className="label-line">Мин. интервал (мин) <span className="required">*</span></span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.minIntervalMinutes}
                      onChange={(event) => setTaskForm({ ...taskForm, minIntervalMinutes: Number(event.target.value) })}
                    />
                  </label>
                  <label>
                    <span className="label-line">Макс. интервал (мин) <span className="required">*</span></span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.maxIntervalMinutes}
                      onChange={(event) => setTaskForm({ ...taskForm, maxIntervalMinutes: Number(event.target.value) })}
                    />
                  </label>
                  <label>
                    <span className="label-line">Лимит в день <span className="required">*</span></span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.dailyLimit}
                      onChange={(event) => setTaskForm({ ...taskForm, dailyLimit: Number(event.target.value) })}
                    />
                  </label>
                  <label>
                    <span className="label-line">История сообщений (шт) <span className="required">*</span></span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.historyLimit}
                      onChange={(event) => setTaskForm({ ...taskForm, historyLimit: Number(event.target.value) })}
                    />
                  </label>
                </div>
                <div className="section-title">Распределение ботов</div>
                <div className="row">
                  <label>
                    <span className="label-line">Ботов в конкурентах</span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.maxCompetitorBots}
                      onChange={(event) => setTaskForm({ ...taskForm, maxCompetitorBots: Number(event.target.value) })}
                    />
                  </label>
                  <label>
                    <span className="label-line">Ботов в нашей группе</span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.maxOurBots}
                      onChange={(event) => setTaskForm({ ...taskForm, maxOurBots: Number(event.target.value) })}
                    />
                  </label>
                  <label className="checkbox inline">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.autoAssignAccounts)}
                      onChange={(event) => setTaskForm({ ...taskForm, autoAssignAccounts: event.target.checked })}
                    />
                    Автоназначать аккаунты при сохранении, если не выбраны
                  </label>
                </div>
                <div className="section-title">Безопасность</div>
                <div className="toggle-row">
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.randomAccounts)}
                      onChange={(event) => setTaskForm({ ...taskForm, randomAccounts: event.target.checked })}
                    />
                    Случайный выбор аккаунтов
                  </label>
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.multiAccountsPerRun)}
                      onChange={(event) => setTaskForm({ ...taskForm, multiAccountsPerRun: event.target.checked })}
                    />
                    Несколько аккаунтов за цикл
                  </label>
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.retryOnFail)}
                      onChange={(event) => setTaskForm({ ...taskForm, retryOnFail: event.target.checked })}
                    />
                    Повторять при ошибке
                  </label>
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.stopOnBlocked)}
                      onChange={(event) => setTaskForm({ ...taskForm, stopOnBlocked: event.target.checked })}
                    />
                    Останавливать при блокировках
                  </label>
                </div>
                <div className="row">
                  <label>
                    <span className="label-line">Остановить при блоке, %</span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.stopBlockedPercent}
                      onChange={(event) => setTaskForm({ ...taskForm, stopBlockedPercent: Number(event.target.value) })}
                    />
                  </label>
                </div>
                <label>
                  <span className="label-line">Заметки</span>
                  <textarea
                    rows="3"
                    value={taskForm.notes}
                    onChange={(event) => setTaskForm({ ...taskForm, notes: event.target.value })}
                  />
                </label>
              </section>

            </>
          )}

          {activeTab === "accounts" && (
            <section className="card">
              <div className="row-header">
                <h2>Аккаунты</h2>
                <div className="row-inline">
                  <button className="ghost" type="button" onClick={() => refreshMembership("accounts")}>Проверить участие</button>
                  <button className="ghost" type="button" onClick={refreshIdentity}>Обновить ID</button>
                </div>
              </div>
              <div className="hint">
                Отметьте аккаунты для выбранной задачи. При нескольких задачах здесь показываются свободные аккаунты.
              </div>
              {!hasSelectedTask && (
                <div className="hint">Выберите задачу, чтобы управлять аккаунтами.</div>
              )}
              {taskNotice && taskNotice.source === "accounts" && (
                <div className={`notice inline ${taskNotice.tone}`}>{taskNotice.text}</div>
              )}
              <div className="account-list">
                {accounts.length === 0 && <div className="empty">Аккаунты не добавлены.</div>}
                {accountBuckets.freeOrSelected.map((account) => {
                  const assignedTasks = assignedAccountMap.get(account.id) || [];
                  const assignedToSelected = selectedTaskId != null && assignedTasks.includes(selectedTaskId);
                  const isFree = assignedTasks.length === 0;
                  const taskNames = assignedTasks
                    .map((taskId) => accountBuckets.taskNameMap.get(taskId) || `Задача #${taskId}`)
                    .join(", ");
                  const membership = membershipStatus[account.id];
                  const stats = accountStats.find((item) => item.id === account.id);
                  const remaining = stats && stats.remainingToday != null ? stats.remainingToday : null;
                  const used = stats ? stats.usedToday : 0;
                  const limit = stats ? stats.limit : settings.accountDailyLimit;
                  const cooldownUntil = account.cooldown_until ? new Date(account.cooldown_until).getTime() : 0;
                  const cooldownActive = cooldownUntil > Date.now();
                  const cooldownMinutes = cooldownActive ? Math.ceil((cooldownUntil - Date.now()) / 60000) : 0;
                  const competitorInfo = membership
                    ? `В конкурентах: ${membership.competitorCount}/${membership.competitorTotal}`
                    : "В конкурентах: —";
                  const ourInfo = membership
                    ? `В нашей: ${membership.ourGroupMember ? "да" : "нет"}`
                    : "В нашей: —";
                  const selected = selectedAccountIds.includes(account.id);

                  return (
                    <div key={account.id} className="account-row">
                      <div>
                        <div className="account-phone">{account.phone}</div>
                        <div className={`status ${account.status}`}>{formatAccountStatus(account.status)}</div>
                        <div className="account-meta">User ID: {account.user_id || "—"}</div>
                        <div className="account-meta">{competitorInfo}</div>
                        <div className="account-meta">{ourInfo}</div>
                        <div className="account-meta">Лимит групп: {account.max_groups || settings.accountMaxGroups}</div>
                        <div className="account-meta">Лимит действий: {account.daily_limit || settings.accountDailyLimit}</div>
                        <div className="account-meta">
                          Осталось действий сегодня: {remaining == null ? "без лимита" : remaining} (использовано: {used}/{limit || "∞"})
                        </div>
                        <div className="account-meta">Задачи: {assignedTasks.length ? taskNames : "—"}</div>
                        {cooldownActive && (
                          <div className="account-meta">
                            Таймер FLOOD: {cooldownMinutes} мин
                          </div>
                        )}
                      </div>
                      {account.status !== "ok" && account.last_error && (
                        <div className="account-error">{account.last_error}</div>
                      )}
                      <div className="account-actions">
                        {hasSelectedTask && (
                          <label className="checkbox">
                            <input
                              type="checkbox"
                              checked={selected}
                              onChange={() => toggleAccountSelection(account.id)}
                            />
                            В задаче
                          </label>
                        )}
                        {hasSelectedTask && selected && (
                          <button className="ghost" onClick={() => removeAccountFromTask(account.id)}>
                            Убрать из задачи
                          </button>
                        )}
                        {cooldownActive && (
                          <button className="secondary" onClick={() => resetCooldown(account.id)}>
                            Снять ограничение
                          </button>
                        )}
                        <button className="danger" onClick={() => deleteAccount(account.id)}>
                          Удалить
                        </button>
                      </div>
                    </div>
                  );
                })}
              </div>

              {filterFreeAccounts && accountBuckets.busy.length > 0 && (
                <div className="busy-accounts">
                  <div className="row-header">
                    <h3>Занятые аккаунты</h3>
                    <div className="status-caption">Используются в других задачах</div>
                  </div>
                  <div className="account-list">
                    {accountBuckets.busy.map((account) => {
                      const assignedTasks = assignedAccountMap.get(account.id) || [];
                      const taskNames = assignedTasks
                        .map((taskId) => accountBuckets.taskNameMap.get(taskId) || `Задача #${taskId}`)
                        .join(", ");
                      const membership = membershipStatus[account.id];
                      const stats = accountStats.find((item) => item.id === account.id);
                      const remaining = stats && stats.remainingToday != null ? stats.remainingToday : null;
                      const used = stats ? stats.usedToday : 0;
                      const limit = stats ? stats.limit : settings.accountDailyLimit;
                      const cooldownUntil = account.cooldown_until ? new Date(account.cooldown_until).getTime() : 0;
                      const cooldownActive = cooldownUntil > Date.now();
                      const cooldownMinutes = cooldownActive ? Math.ceil((cooldownUntil - Date.now()) / 60000) : 0;
                      const competitorInfo = membership
                        ? `В конкурентах: ${membership.competitorCount}/${membership.competitorTotal}`
                        : "В конкурентах: —";
                      const ourInfo = membership
                        ? `В нашей: ${membership.ourGroupMember ? "да" : "нет"}`
                        : "В нашей: —";

                  return (
                    <div key={account.id} className="account-row">
                      <div>
                        <div className="account-phone">{account.phone}</div>
                        <div className={`status ${account.status}`}>{formatAccountStatus(account.status)}</div>
                        <div className="account-meta">User ID: {account.user_id || "—"}</div>
                        <div className="account-meta">{competitorInfo}</div>
                        <div className="account-meta">{ourInfo}</div>
                        <div className="account-meta">Лимит групп: {account.max_groups || settings.accountMaxGroups}</div>
                        <div className="account-meta">Лимит действий: {account.daily_limit || settings.accountDailyLimit}</div>
                        <div className="account-meta">
                          Осталось действий сегодня: {remaining == null ? "без лимита" : remaining} (использовано: {used}/{limit || "∞"})
                        </div>
                        <div className="account-meta">Задачи: {assignedTasks.length ? taskNames : "—"}</div>
                        {cooldownActive && (
                          <div className="account-meta">
                            Таймер FLOOD: {cooldownMinutes} мин
                          </div>
                        )}
                          </div>
                          {account.status !== "ok" && account.last_error && (
                            <div className="account-error">{account.last_error}</div>
                          )}
                          <div className="account-actions">
                            {cooldownActive && (
                              <button className="secondary" onClick={() => resetCooldown(account.id)}>
                                Снять ограничение
                              </button>
                            )}
                            {hasSelectedTask && (
                              <button className="secondary" onClick={() => moveAccountToTask(account.id)}>
                                Добавить в задачу
                              </button>
                            )}
                            <button className="danger" onClick={() => deleteAccount(account.id)}>
                              Удалить
                            </button>
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              )}
            </section>
          )}

          {activeTab === "logs" && (
            <section className="card logs">
              <div className="row-header">
                <h2>Логи и история</h2>
                <div className="row-inline">
                  {logsTab === "logs" ? (
                    <>
                      <button className="secondary" onClick={() => exportLogs("logs")} disabled={!hasSelectedTask}>Выгрузить</button>
                      <button className="danger" onClick={() => clearLogs("logs")} disabled={!hasSelectedTask}>Сбросить</button>
                    </>
                  ) : (
                    <>
                      <button className="secondary" onClick={() => exportInvites("invites")} disabled={!hasSelectedTask}>Выгрузить</button>
                      <button className="danger" onClick={() => clearInvites("invites")} disabled={!hasSelectedTask}>Сбросить</button>
                    </>
                  )}
                </div>
              </div>
              <div className="log-tabs">
                <button
                  type="button"
                  className={`tab ${logsTab === "logs" ? "active" : ""}`}
                  onClick={() => setLogsTab("logs")}
                >
                  Логи
                </button>
                <button
                  type="button"
                  className={`tab ${logsTab === "invites" ? "active" : ""}`}
                  onClick={() => setLogsTab("invites")}
                >
                  История инвайтов
                </button>
              </div>
              {taskNotice && (taskNotice.source === "logs" || taskNotice.source === "invites") && (
                <div className={`notice inline ${taskNotice.tone}`}>{taskNotice.text}</div>
              )}
              {logsTab === "logs" && (
                <div className="row-inline">
                  <input
                    type="text"
                    value={logSearch}
                    onChange={(event) => {
                      setLogSearch(event.target.value);
                      setLogPage(1);
                    }}
                    placeholder="Поиск по логам"
                  />
                  <div className="pager">
                    <button
                      className="secondary"
                      type="button"
                      onClick={() => setLogPage((prev) => Math.max(1, prev - 1))}
                      disabled={logPage === 1}
                    >
                      Назад
                    </button>
                    <div className="pager-info">{logPage}/{logPageCount}</div>
                    <button
                      className="secondary"
                      type="button"
                      onClick={() => setLogPage((prev) => Math.min(logPageCount, prev + 1))}
                      disabled={logPage === logPageCount}
                    >
                      Вперед
                    </button>
                  </div>
                </div>
              )}
              {logsTab === "invites" && (
                <>
                  <div className="row-inline">
                    <input
                      type="text"
                      value={inviteSearch}
                      onChange={(event) => {
                        setInviteSearch(event.target.value);
                        setInvitePage(1);
                      }}
                      placeholder="Поиск по инвайтам"
                    />
                    <div className="pager">
                      <button
                        className="secondary"
                        type="button"
                        onClick={() => setInvitePage((prev) => Math.max(1, prev - 1))}
                        disabled={invitePage === 1}
                      >
                        Назад
                      </button>
                      <div className="pager-info">{invitePage}/{invitePageCount}</div>
                      <button
                        className="secondary"
                        type="button"
                        onClick={() => setInvitePage((prev) => Math.min(invitePageCount, prev + 1))}
                        disabled={invitePage === invitePageCount}
                      >
                        Вперед
                      </button>
                    </div>
                  </div>
                  <div className="task-filters">
                    <button
                      type="button"
                      className={`chip ${inviteFilter === "all" ? "active" : ""}`}
                      onClick={() => {
                        setInviteFilter("all");
                        setInvitePage(1);
                      }}
                    >
                      Все
                    </button>
                    <button
                      type="button"
                      className={`chip ${inviteFilter === "success" ? "active" : ""}`}
                      onClick={() => {
                        setInviteFilter("success");
                        setInvitePage(1);
                      }}
                    >
                      Успех
                    </button>
                    <button
                      type="button"
                      className={`chip ${inviteFilter === "error" ? "active" : ""}`}
                      onClick={() => {
                        setInviteFilter("error");
                        setInvitePage(1);
                      }}
                    >
                      Ошибка
                    </button>
                    <button
                      type="button"
                      className={`chip ${inviteFilter === "skipped" ? "active" : ""}`}
                      onClick={() => {
                        setInviteFilter("skipped");
                        setInvitePage(1);
                      }}
                    >
                      Пропуск
                    </button>
                  </div>
                </>
              )}
              {logsTab === "logs" && (
                <>
                  {pagedLogs.length === 0 && <div className="empty">Логи пока пустые.</div>}
                  {pagedLogs.map((log) => {
                    const successIds = Array.isArray(log.successIds) ? log.successIds : [];
                    const errors = Array.isArray(log.errors) ? log.errors : [];
                    return (
                    <div key={log.id} className="log-row">
                      <div className="log-time">
                        <div>Старт цикла: {formatTimestamp(log.startedAt)}</div>
                        <div>Завершение: {formatTimestamp(log.finishedAt)}</div>
                      </div>
                      <div className="log-details">
                        <div>Добавлено: {log.invitedCount}</div>
                        <div className="log-users wrap">
                          Пользователи: {successIds.length ? successIds.join(", ") : "—"}
                        </div>
                        {log.invitedCount === 0 && errors.length === 0 && (
                          <div className="log-errors">Причина: очередь пуста</div>
                        )}
                        {errors.length > 0 && (
                          <div className="log-errors">Ошибки: {errors.join(" | ")}</div>
                        )}
                      </div>
                    </div>
                  );
                  })}
                </>
              )}
              {logsTab === "invites" && (
                <>
                  {pagedInvites.length === 0 && <div className="empty">История пока пустая.</div>}
                  {pagedInvites.map((invite) => (
                    <div key={invite.id} className="log-row">
                      <div className="log-time">
                        <div>{formatTimestamp(invite.invitedAt)}</div>
                        <div>{invite.status === "success" ? "Успех" : "Ошибка"}</div>
                      </div>
                      <div className="log-details">
                        <div>ID: {invite.userId}</div>
                        <div className="log-users wrap">
                          Ник: {invite.username ? `@${invite.username}` : "—"}
                        </div>
                        <div className="log-users wrap">
                          Источник: {invite.sourceChat || "—"}
                        </div>
                        <div className="log-users">Аккаунт: {invite.accountPhone || "—"}</div>
                        {invite.skippedReason && invite.skippedReason !== "" && (
                          <div className="log-errors">Пропуск: {invite.skippedReason}</div>
                        )}
                        {invite.error && invite.error !== "" && (
                          <div className="log-errors">Причина: {invite.error}</div>
                        )}
                      </div>
                    </div>
                  ))}
                </>
              )}
            </section>
          )}

          {activeTab === "events" && (
            <section className="card logs">
              <h2>События аккаунтов</h2>
              {accountEvents.length === 0 && <div className="empty">Событий нет.</div>}
              {accountEvents.map((event) => (
                <div key={event.id} className="log-row">
                  <div className="log-time">
                    <div>{formatTimestamp(event.createdAt)}</div>
                    <div>{event.eventType}</div>
                  </div>
                  <div className="log-details">
                    <div>Аккаунт: {event.phone || event.accountId}</div>
                    <div className="log-errors">{event.message}</div>
                  </div>
                </div>
              ))}
            </section>
          )}

          {activeTab === "settings" && (
            <section className="card">
              <h2>Глобальные настройки аккаунтов</h2>
              <div className="row">
                <label>
                  <span className="label-line">Лимит групп на аккаунт</span>
                  <input
                    type="number"
                    min="1"
                    value={settings.accountMaxGroups}
                    onChange={(event) => onSettingsChange("accountMaxGroups", Number(event.target.value))}
                  />
                </label>
                <label>
                  <span className="label-line">Лимит действий в день на аккаунт</span>
                  <input
                    type="number"
                    min="1"
                    value={settings.accountDailyLimit}
                    onChange={(event) => onSettingsChange("accountDailyLimit", Number(event.target.value))}
                  />
                </label>
                <label>
                  <span className="label-line">Таймер после FLOOD (мин)</span>
                  <input
                    type="number"
                    min="1"
                    value={settings.floodCooldownMinutes}
                    onChange={(event) => onSettingsChange("floodCooldownMinutes", Number(event.target.value))}
                  />
                </label>
              </div>
              <div className="row actions">
                <button className="secondary" onClick={saveSettings}>Сохранить настройки</button>
              </div>
              {settingsNotice && (
                <div className={`notice inline ${settingsNotice.tone}`}>{settingsNotice.text}</div>
              )}
            </section>
          )}
        </div><aside className="sidebar right">
          <section className="card sticky">
            <div className="row-header">
              <h2>Управление задачей</h2>
              <div className="status-caption">{selectedTaskName}</div>
            </div>
            <div className="hint">Панель закреплена и относится к выбранной задаче.</div>
            <div className="side-stats">
              <div className="side-stat">
                <span>Группы конкурентов</span>
                <strong>{competitorGroups.length}</strong>
              </div>
              <div className="side-stat">
                <span>Аккаунты</span>
                <strong>{selectedAccountIds.length}</strong>
              </div>
              <div className="side-stat">
                <span>Очередь</span>
                <strong>{taskStatus.queueCount}</strong>
              </div>
              <div className="side-stat">
                <span>Лимит сегодня</span>
                <strong>{taskStatus.dailyUsed}/{taskStatus.dailyLimit}</strong>
              </div>
            </div>
            <div className="sidebar-actions">
              {taskStatus.running ? (
                <button className="danger" onClick={() => stopTask("sidebar")} disabled={!hasSelectedTask}>Остановить</button>
              ) : (
                <button className="primary" onClick={() => startTask("sidebar")} disabled={!hasSelectedTask}>Запустить</button>
              )}
              <button
                className="ghost"
                type="button"
                onClick={() => setSidebarExpanded((prev) => !prev)}
              >
                {sidebarExpanded ? "Свернуть действия" : "Показать действия"}
              </button>
            </div>
            {sidebarExpanded && (
              <div className="sidebar-actions expanded">
                <button className="secondary" onClick={() => saveTask("sidebar")} disabled={!canSaveTask}>Сохранить задачу</button>
                <button className="secondary" onClick={() => parseHistory("sidebar")} disabled={!hasSelectedTask}>Собрать историю</button>
                <button className="secondary" onClick={() => checkAccess("sidebar")} disabled={!hasSelectedTask}>Проверить доступ</button>
                <button className="secondary" onClick={() => refreshMembership("sidebar")} disabled={!hasSelectedTask}>Проверить участие</button>
                <button className="secondary" onClick={() => clearQueue("sidebar")} disabled={!hasSelectedTask}>Очистить очередь</button>
              </div>
            )}
            {taskNotice && taskNotice.source === "sidebar" && (
              <div className={`notice inline ${taskNotice.tone}`}>{taskNotice.text}</div>
            )}
            {accessStatus.length > 0 && (
              <div className="access-block">
                <div className="access-title">Доступ к группам</div>
                <div className="access-list">
                  {accessStatus.map((item, index) => (
                    <div key={`${item.value}-${index}`} className={`access-row ${item.ok ? "ok" : "fail"}`}>
                      <div className="access-title">
                        {item.type === "our" ? "Наша" : "Конкурент"}: {item.title || item.value}
                      </div>
                      <div className="access-status">
                        {item.ok ? "Доступ есть" : "Нет доступа"}
                      </div>
                      {!item.ok && <div className="access-error">{item.details}</div>}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </section>
        </aside>
      </div>
    </div>
  );
}
