import React from "react";
import HelpTip from "./HelpTip.jsx";
import { getPresetLabel } from "../utils/presetLabels.js";

export default function TaskSettingsTab({
  selectedTaskName,
  taskForm,
  setTaskForm,
  activePreset,
  setActivePreset,
  applyTaskPreset,
  formatAccountLabel,
  accountById,
  competitorText,
  setCompetitorText,
  roleMode,
  applyRoleMode,
  normalizeIntervals,
  taskStatus,
  perAccountInviteSum,
  hasSelectedTask,
  inviteAccessStatus,
  inviteAccessCheckedAt,
  confirmAccessStatus,
  confirmAccessCheckedAt,
  formatTimestamp,
  checkInviteAccess,
  checkConfirmAccess,
  accounts,
  showNotification,
  copyToClipboard,
  sanitizeTaskForm,
  hasPerAccountInviteLimits,
  fileImportResult,
  importInviteFile,
  fileImportForm,
  setFileImportForm,
  criticalErrorAccounts
}) {
  const [customPresetName, setCustomPresetName] = React.useState("");
  const [customPresets, setCustomPresets] = React.useState(() => {
    try {
      const raw = localStorage.getItem("tia_custom_presets_v1");
      return raw ? JSON.parse(raw) : [];
    } catch {
      return [];
    }
  });
  const changedSections = (nextForm) => {
    const sections = [];
    const hasAny = (keys) => keys.some((k) => JSON.stringify(taskForm[k]) !== JSON.stringify(nextForm[k]));
    if (hasAny(["name", "ourGroup"])) sections.push("Основное");
    if (hasAny(["maxCompetitorBots", "maxOurBots", "separateConfirmRoles", "maxConfirmBots", "rolesMode", "requireSameBotInBoth"])) sections.push("Роли ботов и вступление");
    if (hasAny(["inviteViaAdmins", "inviteAdminMasterId", "inviteAdminAnonymous", "inviteAdminAllowFlood", "inviteLinkOnFail"])) sections.push("Инвайт через админов");
    if (hasAny(["minIntervalMinutes", "maxIntervalMinutes", "dailyLimit", "maxInvitesPerCycle", "warmupEnabled", "historyLimit"])) sections.push("Интервалы и лимиты");
    return sections;
  };
  const confirmApply = (nextForm, label, applyFn, sectionsOverride = null) => {
    const sections = Array.isArray(sectionsOverride) ? sectionsOverride : changedSections(nextForm);
    const msg = sections.length
      ? `Пресет "${label}" изменит текущие настройки.\n\nБудут изменены разделы:\n- ${sections.join("\n- ")}\n\nПрименить?`
      : `Пресет "${label}" не меняет текущие настройки.\nПрименить?`;
    if (!window.confirm(msg)) return;
    applyFn();
  };
  const saveCustomPreset = () => {
    const name = customPresetName.trim();
    if (!name) {
      showNotification("Введите имя пресета.", "error");
      return;
    }
    const next = [...customPresets.filter((p) => p.name !== name), { name, form: taskForm }];
    setCustomPresets(next);
    localStorage.setItem("tia_custom_presets_v1", JSON.stringify(next));
    setCustomPresetName("");
    showNotification(`Сохранен пользовательский пресет: ${name}`, "success");
  };
  const applyCustomPreset = (preset) => {
    const nextForm = sanitizeTaskForm({ ...taskForm, ...preset.form });
    confirmApply(nextForm, preset.name, () => {
      setTaskForm(nextForm);
      setActivePreset(`custom:${preset.name}`);
      showNotification(`Применен пользовательский пресет: ${preset.name}`, "success");
    });
  };
  const deleteCustomPreset = (name) => {
    const next = customPresets.filter((preset) => preset.name !== name);
    setCustomPresets(next);
    localStorage.setItem("tia_custom_presets_v1", JSON.stringify(next));
    if (activePreset === `custom:${name}`) {
      setActivePreset("");
    }
    showNotification(`Удален пользовательский пресет: ${name}`, "success");
  };
  const renameCustomPreset = (name) => {
    const nextName = window.prompt("Новое имя пресета:", name);
    if (!nextName) return;
    const trimmed = nextName.trim();
    if (!trimmed) return;
    const preset = customPresets.find((p) => p.name === name);
    if (!preset) return;
    const next = [
      ...customPresets.filter((p) => p.name !== name && p.name !== trimmed),
      { ...preset, name: trimmed }
    ];
    setCustomPresets(next);
    localStorage.setItem("tia_custom_presets_v1", JSON.stringify(next));
    if (activePreset === `custom:${name}`) {
      setActivePreset(`custom:${trimmed}`);
    }
    showNotification(`Переименован пресет: ${name} → ${trimmed}`, "success");
  };
  const exportCustomPresets = () => {
    try {
      const payload = {
        version: 1,
        exportedAt: new Date().toISOString(),
        presets: customPresets
      };
      const blob = new Blob([JSON.stringify(payload, null, 2)], { type: "application/json" });
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "custom-presets.json";
      link.click();
      URL.revokeObjectURL(url);
      showNotification("Пользовательские пресеты экспортированы.", "success");
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };
  const importCustomPresets = async (event) => {
    const file = event.target.files && event.target.files[0];
    event.target.value = "";
    if (!file) return;
    try {
      const text = await file.text();
      const parsed = JSON.parse(text);
      const list = Array.isArray(parsed) ? parsed : Array.isArray(parsed.presets) ? parsed.presets : [];
      const valid = list
        .filter((item) => item && typeof item.name === "string" && item.name.trim() && item.form && typeof item.form === "object")
        .map((item) => ({ name: item.name.trim(), form: item.form }));
      if (!valid.length) {
        showNotification("Файл не содержит корректных пресетов.", "error");
        return;
      }
      const replaceAll = window.confirm("Заменить все текущие пользовательские пресеты?\n\nОК — заменить полностью\nОтмена — объединить с текущими");
      const map = new Map();
      if (!replaceAll) {
        customPresets.forEach((preset) => map.set(preset.name, preset));
      }
      valid.forEach((preset) => map.set(preset.name, preset));
      const next = Array.from(map.values());
      setCustomPresets(next);
      localStorage.setItem("tia_custom_presets_v1", JSON.stringify(next));
      showNotification(`Импортировано пресетов: ${valid.length}. Режим: ${replaceAll ? "замена" : "объединение"}.`, "success");
    } catch (error) {
      showNotification(error.message || String(error), "error");
    }
  };

  const inviteChecks = Array.isArray(inviteAccessStatus) ? inviteAccessStatus : [];
  const inviteChecksById = React.useMemo(() => {
    const map = new Map();
    inviteChecks.forEach((item) => {
      map.set(Number(item.accountId), item);
    });
    return map;
  }, [inviteChecks]);
  const masterId = Number(taskForm.inviteAdminMasterId || 0);
  const masterAccount = masterId ? (accountById.get(masterId) || accounts.find((item) => Number(item.id) === masterId)) : null;
  const masterCheck = masterId ? inviteChecksById.get(masterId) : null;
  const checkedCount = inviteChecks.length;
  const canInviteCount = inviteChecks.filter((item) => item && item.canInvite).length;
  const confirmChecks = Array.isArray(confirmAccessStatus) ? confirmAccessStatus : [];
  const confirmCheckedCount = confirmChecks.length;
  const confirmOkCount = confirmChecks.filter((item) => item && item.ok).length;
  const diagnostics = [
    {
      title: "Режим",
      value: taskForm.inviteViaAdmins ? "включен" : "выключен",
      tone: taskForm.inviteViaAdmins ? "ok" : "warn"
    },
    {
      title: "Мастер-админ",
      value: masterId ? formatAccountLabel(masterAccount || { id: masterId, phone: `ID ${masterId}` }) : "не выбран",
      tone: masterId ? "ok" : "fail"
    },
    {
      title: "Проверка прав",
      value: checkedCount ? `выполнена (${checkedCount} аккаунтов)` : "не выполнялась",
      tone: checkedCount ? "ok" : "warn"
    },
    {
      title: "Права мастера",
      value: !masterId
        ? "нельзя проверить без выбора мастера"
        : !checkedCount
          ? "нет данных (нажмите «Проверить права»)"
          : masterCheck
            ? (masterCheck.canInvite ? "OK: может приглашать" : `ошибка: ${masterCheck.reason || "нет права приглашать"}`)
            : "мастер не вошел в результаты проверки",
      tone: !masterId ? "warn" : !checkedCount ? "warn" : (masterCheck && masterCheck.canInvite ? "ok" : "fail")
    },
    {
      title: "Инвайтеры с правом",
      value: checkedCount ? `${canInviteCount}/${checkedCount}` : "—",
      tone: !checkedCount ? "warn" : canInviteCount > 0 ? "ok" : "fail"
    }
  ];

  return (
    <div className="task-columns">
      <details className="card collapsible task-editor" open>
        <summary>
          <div className="row-header">
            <h3>Настройки задачи</h3>
            <div className="status-caption">Для: {selectedTaskName}</div>
          </div>
        </summary>
        <div className="section-title">Основное</div>
        <div className="row-inline">
          <div className="status-caption">Пресеты:</div>
              <button
                className={`secondary ${activePreset === "admin" ? "active" : ""}`}
                type="button"
                onClick={() => confirmApply(taskForm, "Автораспределение + Инвайт через админа", () => applyTaskPreset("admin"), ["Роли ботов и вступление", "Инвайт через админов", "Интервалы и лимиты"])}
              >
                Автораспределение + Инвайт через админа
              </button>
              <button
                className={`secondary ${activePreset === "no_admin" ? "active" : ""}`}
                type="button"
                onClick={() => confirmApply(taskForm, "Автораспределение + Без админки", () => applyTaskPreset("no_admin"), ["Роли ботов и вступление", "Инвайт через админов", "Интервалы и лимиты"])}
              >
                Автораспределение + Без админки
              </button>
              <button
                className={`secondary ${activePreset === "soft_50" ? "active" : ""}`}
                type="button"
                onClick={() => confirmApply(taskForm, "Мягкий 50/день (5 инвайтеров)", () => applyTaskPreset("soft_50"), ["Роли ботов и вступление", "Интервалы и лимиты"])}
              >
                Мягкий 50/день (5 инвайтеров)
              </button>
              <button
                className={`secondary ${activePreset === "soft_25" ? "active" : ""}`}
                type="button"
                onClick={() => confirmApply(taskForm, "Мягкий 25/день (2 инвайтера)", () => applyTaskPreset("soft_25"), ["Роли ботов и вступление", "Интервалы и лимиты"])}
              >
                Мягкий 25/день (2 инвайтера)
              </button>
              <button
                className={`secondary ${activePreset === "soft_50_admin" ? "active" : ""}`}
                type="button"
                onClick={() => confirmApply(taskForm, "Мягкий 50/день + админы", () => applyTaskPreset("soft_50_admin"), ["Роли ботов и вступление", "Инвайт через админов", "Интервалы и лимиты"])}
              >
                Мягкий 50/день + админы
              </button>
              <button
                className={`secondary ${activePreset === "soft_25_admin" ? "active" : ""}`}
                type="button"
                onClick={() => confirmApply(taskForm, "Мягкий 25/день + админы", () => applyTaskPreset("soft_25_admin"), ["Роли ботов и вступление", "Инвайт через админов", "Интервалы и лимиты"])}
              >
                Мягкий 25/день + админы
              </button>
          <span className="status-caption">
            Мастер-админ: {taskForm.inviteAdminMasterId ? formatAccountLabel(accountById.get(taskForm.inviteAdminMasterId)) : "не выбран"}
          </span>
        </div>
        <div className="status-caption">
          Выбранный пресет: {getPresetLabel(activePreset)}.
          При применении пресета будут изменены: «Роли ботов и вступление», «Инвайт через админов», «Интервалы и лимиты».
        </div>
        <div className="row-inline">
          <input
            type="text"
            value={customPresetName}
            onChange={(event) => setCustomPresetName(event.target.value)}
            placeholder="Имя пользовательского пресета"
          />
          <button className="secondary" type="button" onClick={saveCustomPreset}>Сохранить пресет</button>
          <button className="secondary" type="button" onClick={exportCustomPresets}>Экспорт пресетов</button>
          <label className="secondary" style={{ cursor: "pointer" }}>
            Импорт пресетов
            <input type="file" accept="application/json" onChange={importCustomPresets} style={{ display: "none" }} />
          </label>
          {customPresets.map((preset) => (
            <span key={preset.name} className="row-inline">
              <button
                className={`secondary ${activePreset === `custom:${preset.name}` ? "active" : ""}`}
                type="button"
                onClick={() => applyCustomPreset(preset)}
              >
                {preset.name}
              </button>
              <button className="ghost tiny" type="button" onClick={() => renameCustomPreset(preset.name)}>Переименовать</button>
              <button className="danger ghost tiny" type="button" onClick={() => deleteCustomPreset(preset.name)}>Удалить</button>
            </span>
          ))}
        </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="task-editor-grid">
          <details className="section" open>
            <summary className="section-title">Базовые настройки</summary>
            <details className="section" open>
              <summary className="section-title">Роли ботов и вступление</summary>
              <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="toggle-row">
                <label className="checkbox">
                  <input
                    type="radio"
                    name="roleMode"
                    checked={roleMode === "split"}
                    onChange={() => applyRoleMode("split")}
                  />
                  Разделить роли (конкуренты и наша группа разными аккаунтами)
                </label>
                <label className="checkbox">
                  <input
                    type="radio"
                    name="roleMode"
                    checked={roleMode === "same"}
                    onChange={() => applyRoleMode("same")}
                  />
                  Один и тот же бот в конкурентах и нашей группе
                </label>
              </div>
              <div className="status-text compact">
                Режим “один и тот же бот” нужен, когда аккаунт должен быть в конкурентах и в нашей группе для инвайта.
              </div>
            </details>
            <details className="section" open>
              <summary className="section-title">Интервалы и лимиты</summary>
              <div className="row">
                <label>
                  <span className="label-line">
                    Мин. интервал (мин) <span className="required">*</span>
                    <HelpTip text="Минимальная пауза между циклами приглашений. Фактический интервал выбирается случайно между мин/макс." />
                  </span>
                  <input
                    type="number"
                    min="1"
                    value={taskForm.minIntervalMinutes || ""}
                    onChange={(event) => {
                      const value = event.target.value;
                      setTaskForm({ ...taskForm, minIntervalMinutes: value === "" ? "" : Number(value) });
                    }}
                    onBlur={() => setTaskForm(normalizeIntervals(taskForm))}
                  />
                </label>
                <label>
                  <span className="label-line">
                    Макс. интервал (мин) <span className="required">*</span>
                    <HelpTip text="Максимальная пауза между циклами приглашений." />
                  </span>
                  <input
                    type="number"
                    min="1"
                    value={taskForm.maxIntervalMinutes || ""}
                    onChange={(event) => {
                      const value = event.target.value;
                      setTaskForm({ ...taskForm, maxIntervalMinutes: value === "" ? "" : Number(value) });
                    }}
                    onBlur={() => setTaskForm(normalizeIntervals(taskForm))}
                  />
                </label>
                <label>
                  <span className="label-line">
                    Лимит в день <span className="required">*</span>
                    <HelpTip text="Сколько успешных инвайтов разрешено в сутки. Итоговый лимит = min(дневной лимит, разогрев)." />
                  </span>
                  <input
                    type="number"
                    min="1"
                    value={taskForm.dailyLimit === "" ? "" : taskForm.dailyLimit}
                    onChange={(event) => {
                      const value = event.target.value;
                      setTaskForm({ ...taskForm, dailyLimit: value === "" ? "" : Number(value) });
                    }}
                    onBlur={() => {
                      const value = Number(taskForm.dailyLimit);
                      setTaskForm({ ...taskForm, dailyLimit: Number.isFinite(value) && value > 0 ? value : 1 });
                    }}
                  />
                  <span className="hint">Фактический лимит сегодня: {taskStatus.dailyLimit || "—"}</span>
                </label>
                <label>
                  <span className="label-line">
                    История сообщений (шт) <span className="required">*</span>
                    <HelpTip text="Сколько последних сообщений анализировать при сборе истории." />
                  </span>
                  <input
                    type="number"
                    min="1"
                    value={taskForm.historyLimit === 0 ? "" : taskForm.historyLimit}
                    onChange={(event) => {
                      const value = event.target.value;
                      setTaskForm({ ...taskForm, historyLimit: value === "" ? "" : Number(value) });
                    }}
                    onBlur={() => {
                      const value = Number(taskForm.historyLimit);
                      setTaskForm({ ...taskForm, historyLimit: Number.isFinite(value) && value > 0 ? value : 1 });
                    }}
                  />
                </label>
                <div className="limit-block">
                  <label>
                    <span className="label-line">
                      Инвайтов за цикл <span className="required">*</span>
                      <HelpTip text="Максимум приглашений за один цикл. Распределяется между инвайтерами по их лимитам." />
                    </span>
                    <input
                      type="number"
                      min="1"
                      value={taskForm.maxInvitesPerCycle === "" ? "" : taskForm.maxInvitesPerCycle}
                      onChange={(event) => {
                        const value = event.target.value;
                        setTaskForm({ ...taskForm, maxInvitesPerCycle: value === "" ? "" : Number(value) });
                      }}
                      onBlur={() => {
                        const value = Number(taskForm.maxInvitesPerCycle);
                        setTaskForm({ ...taskForm, maxInvitesPerCycle: Number.isFinite(value) && value > 0 ? value : 1 });
                      }}
                    />
                    <span className="hint">Это общий потолок на цикл. Пер‑аккаунтные лимиты распределяют инвайты внутри этого числа.</span>
                  </label>
                  <div className="hint">
                    Итоговая формула: <strong>фактический лимит сегодня</strong> = min(дневной лимит задачи, разогрев).
                    Внутри цикла инвайты распределяются по аккаунтам согласно их лимитам.
                  </div>
                  <div className="status-caption">Фактический лимит сегодня: {taskStatus.dailyLimit || "—"}</div>
                  <div className="status-caption">Сумма лимитов по аккаунтам: {perAccountInviteSum || "—"}</div>
                </div>
                <label className="checkbox">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.warmupEnabled)}
                    onChange={(event) => setTaskForm({ ...taskForm, warmupEnabled: event.target.checked })}
                  />
                  Разогрев лимита
                  <HelpTip text="Плавно увеличивает дневной лимит по дням. Итоговый лимит не превышает дневной лимит задачи." />
                  <span
                    className="hint"
                    title="График: дни 1–3 — 1/д; 4–7 — 2/д; 8–12 — 3/д; 13–18 — 4/д; 19–25 — 5/д; 26–33 — 6/д; с 34-го — 7/д. Итоговый лимит не превышает дневной лимит задачи."
                  >
                    Плавно увеличивает дневной лимит по дням.
                  </span>
                  <span className="hint">Нужен для “прогрева” новых аккаунтов и снижения риска флуда.</span>
                  <span className="hint">График: 1/д ×3, 2/д ×4, 3/д ×5, 4/д ×6, 5/д ×7, 6/д ×8, далее 7/д.</span>
                </label>
                {taskForm.warmupEnabled && (
                  <>
                    <label>
                      <span className="label-line">Стартовый лимит</span>
                      <input
                        type="number"
                        min="1"
                        value={taskForm.warmupStartLimit === "" ? "" : taskForm.warmupStartLimit}
                        onChange={(event) => {
                          const value = event.target.value;
                          setTaskForm({ ...taskForm, warmupStartLimit: value === "" ? "" : Number(value) });
                        }}
                        onBlur={() => {
                          const value = Number(taskForm.warmupStartLimit);
                          setTaskForm({ ...taskForm, warmupStartLimit: Number.isFinite(value) && value > 0 ? value : 1 });
                        }}
                      />
                    </label>
                    <div className="hint">
                      Стартовый лимит применяется в первый день. Далее лимит увеличивается по графику прогрева: итог = Стартовый лимит + (ступень прогрева − 1), но не выше дневного лимита задачи.
                    </div>
                    <label>
                      <span className="label-line">Прирост в день</span>
                      <input
                        type="number"
                        min="0"
                        value={taskForm.warmupDailyIncrease === "" ? "" : taskForm.warmupDailyIncrease}
                        onChange={(event) => {
                          const value = event.target.value;
                          setTaskForm({ ...taskForm, warmupDailyIncrease: value === "" ? "" : Number(value) });
                        }}
                        onBlur={() => {
                          const value = Number(taskForm.warmupDailyIncrease);
                          setTaskForm({ ...taskForm, warmupDailyIncrease: Number.isFinite(value) && value >= 0 ? value : 0 });
                        }}
                      />
                    </label>
                  </>
                )}
              </div>
            </details>
          </details>
          <details className="section">
            <summary className="section-title">Расширенные настройки</summary>
            <details className="section">
              <summary className="section-title">Инвайт через админов</summary>
              <div className="status-text compact">
                Шаги: 1) Включить режим  2) Выбрать мастер‑админа  3) Проверить права
              </div>
              <div className="admin-invite-grid">
                <label className="checkbox admin-invite-toggle">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.inviteViaAdmins)}
                    onChange={(event) => setTaskForm({ ...taskForm, inviteViaAdmins: event.target.checked })}
                  />
                  Инвайтить через админов
                  <HelpTip text="Мастер‑админ временно выдаёт право приглашать инвайтеру, затем снимает." />
                  <span className="hint">
                    Временно выдаём инвайтеру право “Приглашать”, затем снимаем права.
                  </span>
                </label>
                <div className="admin-invite-actions">
                  <button
                    type="button"
                    className="secondary"
                    onClick={() => checkInviteAccess("admin_block")}
                    disabled={!hasSelectedTask}
                  >
                    Проверить права
                  </button>
                  <span className={`status-pill ${inviteAccessStatus && inviteAccessStatus.length ? "ok" : "off"}`}>
                    {inviteAccessStatus && inviteAccessStatus.length
                      ? `Права проверены${inviteAccessCheckedAt ? ` (${formatTimestamp(inviteAccessCheckedAt)})` : ""}${
                          inviteAccessStatus.every((item) => item.canInvite) ? " · OK" : " · есть ошибки"
                        }`
                      : "Нет проверки"}
                  </span>
                </div>
                {taskForm.inviteViaAdmins && !taskForm.inviteAdminMasterId && (
                  <div className="notice inline warn">
                    Не выбран мастер‑админ. Инвайт через админов работать не будет.
                  </div>
                )}
                <label className="admin-invite-master">
                  <span className="label-line">
                    Главный аккаунт
                    <HelpTip text="Мастер‑админ: должен быть в целевой группе и иметь право выдавать админов." />
                  </span>
                  <div className="input-row">
                    <select
                      value={taskForm.inviteAdminMasterId || ""}
                      onChange={(event) => setTaskForm({ ...taskForm, inviteAdminMasterId: Number(event.target.value) || 0 })}
                      disabled={!taskForm.inviteViaAdmins}
                    >
                      <option value="">Не выбран</option>
                      {accounts.map((account) => (
                        <option key={`master-${account.id}`} value={account.id}>
                          {formatAccountLabel(account)}
                        </option>
                      ))}
                    </select>
                    <button
                      type="button"
                      className="secondary"
                      disabled={!taskForm.inviteViaAdmins || !taskForm.inviteAdminMasterId}
                      onClick={async () => {
                        const account = accountById.get(taskForm.inviteAdminMasterId);
                        const username = account && account.username ? `@${account.username}` : "";
                        if (!username) {
                          showNotification("У выбранного аккаунта нет username.", "error");
                          return;
                        }
                        const ok = await copyToClipboard(username);
                        showNotification(ok ? `Скопировано: ${username}` : "Не удалось скопировать.", ok ? "success" : "error");
                      }}
                    >
                      Копировать username
                    </button>
                  </div>
                  <span className="hint">
                    Этот аккаунт должен быть админом в целевой группе и уметь выдавать права другим.
                  </span>
                </label>
                <label className="checkbox admin-invite-toggle">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.inviteAdminAnonymous)}
                    onChange={(event) => setTaskForm({ ...taskForm, inviteAdminAnonymous: event.target.checked })}
                    disabled={!taskForm.inviteViaAdmins}
                  />
                  Делать админов анонимными
                  <HelpTip text="Выдаём права инвайтерам с анонимностью и минимальными правами." />
                  <span className="hint">
                    Мастер-админ назначает остальных админами с анонимностью и минимальными правами.
                  </span>
                </label>
                <label className="checkbox admin-invite-flood">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.inviteAdminAllowFlood)}
                    onChange={(event) => setTaskForm({ ...taskForm, inviteAdminAllowFlood: event.target.checked })}
                    disabled={!taskForm.inviteViaAdmins}
                  />
                  Инвайтить в чаты с флудом
                  <HelpTip text="Пробуем административный путь, если Telegram ограничивает инвайт." />
                  <span className="hint">
                    Использует выдачу прав между аккаунтами, если Telegram ограничивает инвайтинг.
                  </span>
                </label>
                <div className="admin-diagnostics" role="status" aria-live="polite">
                  <div className="admin-diagnostics-title">Диагностика мастер-админа</div>
                  <div className="admin-diagnostics-list">
                    {diagnostics.map((item) => (
                      <div key={item.title} className={`admin-diagnostics-item ${item.tone}`}>
                        <span className="name">{item.title}</span>
                        <span className="value">{item.value}</span>
                      </div>
                    ))}
                  </div>
                  <div className="hint">
                    Если есть ошибки: проверьте, что мастер-админ в целевой группе, у него есть право выдачи админов, а инвайтеры состоят в целевой группе.
                  </div>
                </div>
              </div>
            </details>
            <details className="section">
              <summary className="section-title">Распределение ботов</summary>
              <div className="row">
                {roleMode === "same" ? (
                  <label>
                    <span className="label-line">Ботов в обеих группах</span>
                    <input
                      type="number"
                      min="1"
                      disabled={taskForm.rolesMode === "manual"}
                      value={taskForm.maxCompetitorBots === "" ? "" : taskForm.maxCompetitorBots}
                      onChange={(event) => {
                        const value = event.target.value;
                        if (value === "") {
                          setTaskForm({ ...taskForm, maxCompetitorBots: "", maxOurBots: "" });
                          return;
                        }
                        const nextValue = Number(value);
                        const nextForm = { ...taskForm, maxCompetitorBots: nextValue, maxOurBots: nextValue };
                        setTaskForm(sanitizeTaskForm(nextForm));
                      }}
                      onBlur={() => {
                        const value = Number(taskForm.maxCompetitorBots);
                        const normalized = Number.isFinite(value) && value > 0 ? value : 1;
                        setTaskForm(sanitizeTaskForm({ ...taskForm, maxCompetitorBots: normalized, maxOurBots: normalized }));
                      }}
                    />
                    <span className="hint">
                      Одинаковое количество для конкурентов и нашей группы.
                      {taskForm.rolesMode === "manual" ? " В ручном режиме не используется." : ""}
                    </span>
                  </label>
                ) : (
                  <>
                    <label>
                      <span className="label-line">Ботов в конкурентах</span>
                      <input
                        type="number"
                        min="1"
                        disabled={taskForm.rolesMode === "manual"}
                        value={taskForm.maxCompetitorBots === "" ? "" : taskForm.maxCompetitorBots}
                        onChange={(event) => {
                          const value = event.target.value;
                          setTaskForm({
                            ...taskForm,
                            maxCompetitorBots: value === "" ? "" : Number(value)
                          });
                        }}
                        onBlur={() => {
                          const value = Number(taskForm.maxCompetitorBots);
                          setTaskForm({ ...taskForm, maxCompetitorBots: Number.isFinite(value) && value > 0 ? value : 1 });
                        }}
                      />
                      <span className="hint">
                        Используется для авто‑распределения ролей мониторинга и авто‑вступления в группы конкурентов.
                        В ручном режиме ролей не ограничивает мониторинг.
                        {taskForm.rolesMode === "manual" ? " В ручном режиме не используется." : ""}
                      </span>
                    </label>
                    <label>
                      <span className="label-line">Ботов в нашей группе</span>
                      <input
                        type="number"
                        min="1"
                        disabled={taskForm.rolesMode === "manual"}
                        value={taskForm.maxOurBots === "" ? "" : taskForm.maxOurBots}
                        onChange={(event) => {
                          const value = event.target.value;
                          setTaskForm({ ...taskForm, maxOurBots: value === "" ? "" : Number(value) });
                        }}
                        onBlur={() => {
                          const value = Number(taskForm.maxOurBots);
                          setTaskForm({ ...taskForm, maxOurBots: Number.isFinite(value) && value > 0 ? value : 1 });
                        }}
                      />
                      <span className="hint">
                        Используется для авто‑распределения инвайтеров и авто‑вступления в нашу группу.
                        В ручном режиме ролей инвайт идёт по отмеченным аккаунтам.
                        {taskForm.rolesMode === "manual" ? " В ручном режиме не используется." : ""}
                      </span>
                    </label>
                  </>
                )}
              </div>
              <div className="row">
                <label className="checkbox">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.separateConfirmRoles)}
                    onChange={(event) => setTaskForm({ ...taskForm, separateConfirmRoles: event.target.checked })}
                    disabled={!taskForm.separateBotRoles}
                  />
                  Подтверждение отдельными аккаунтами
                  <span className="hint">
                    Если включено, проверку участия выполняют отдельные аккаунты, не совпадающие с инвайтерами.
                    Ручные чекбоксы ролей в разделе “Аккаунты” имеют приоритет над авто‑распределением.
                    При включении нельзя совмещать роли “Инвайт” и “Подтверждение” у одного бота.
                  </span>
                  {taskForm.separateConfirmRoles && (
                    <div className="status-caption">
                      Проверка подтверждения: {confirmCheckedCount ? `OK ${confirmOkCount}/${confirmCheckedCount}` : "не выполнялась"}
                      {confirmAccessCheckedAt ? ` (${formatTimestamp(confirmAccessCheckedAt)})` : ""}
                      <button
                        type="button"
                        className="ghost tiny"
                        onClick={() => checkConfirmAccess("editor")}
                      >
                        Проверить
                      </button>
                    </div>
                  )}
                </label>
                <label>
                  <span className="label-line">Ботов для подтверждения</span>
                  <input
                    type="number"
                    min="1"
                    value={taskForm.maxConfirmBots === "" ? "" : taskForm.maxConfirmBots}
                    onChange={(event) => {
                      const value = event.target.value;
                      setTaskForm({ ...taskForm, maxConfirmBots: value === "" ? "" : Number(value) });
                    }}
                    onBlur={() => {
                      const value = Number(taskForm.maxConfirmBots);
                      const normalized = Number.isFinite(value) && value > 0 ? value : 1;
                      setTaskForm({ ...taskForm, maxConfirmBots: normalized });
                    }}
                    disabled={!taskForm.separateBotRoles || !taskForm.separateConfirmRoles}
                  />
                  <span className="hint">Используется при авто-разделении ролей.</span>
                </label>
              </div>
            </details>
          </details>
          <details className="section">
            <summary className="section-title">Дополнительные настройки</summary>
            <div className="status-text compact">Не трогайте, если не уверены.</div>
            <div className="section-title">Безопасность</div>
            <div className="toggle-row">
              {!hasPerAccountInviteLimits && (
                <label className="checkbox">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.randomAccounts)}
                    onChange={(event) => setTaskForm({ ...taskForm, randomAccounts: event.target.checked })}
                  />
                  Случайный выбор аккаунтов
                  <span className="hint">Инвайты распределяются случайно между доступными аккаунтами.</span>
                </label>
              )}
              {!hasPerAccountInviteLimits && (
                <label className="checkbox">
                  <input
                    type="checkbox"
                    checked={Boolean(taskForm.multiAccountsPerRun)}
                    onChange={(event) => setTaskForm({ ...taskForm, multiAccountsPerRun: event.target.checked })}
                  />
                  Несколько аккаунтов за цикл
                  <span className="hint">Если выключено — в каждом цикле используется один аккаунт.</span>
                </label>
              )}
              <label className="checkbox">
                <input
                  type="checkbox"
                  checked={Boolean(taskForm.retryOnFail)}
                  onChange={(event) => setTaskForm({ ...taskForm, retryOnFail: event.target.checked })}
                />
                Повторять при ошибке
                <HelpTip text="При неудаче делаем до 2 повторов (зависит от типа ошибки)." />
                <span className="hint">Повторяем до 2 раз при неудачном инвайте.</span>
              </label>
              <label className="checkbox">
                <input
                  type="checkbox"
                  checked={Boolean(taskForm.inviteLinkOnFail)}
                  onChange={(event) => setTaskForm({ ...taskForm, inviteLinkOnFail: event.target.checked })}
                />
                Отправлять ссылку при USER_NOT_MUTUAL_CONTACT
                <HelpTip text="Если инвайт невозможен, отправляем пользователю ссылку на нашу группу." />
                <span className="hint">
                  Отправляет пользователю ссылку из поля “Наша группа”.
                </span>
              </label>
              <label className="checkbox">
                <input
                  type="checkbox"
                  checked={Boolean(taskForm.stopOnBlocked)}
                  onChange={(event) => setTaskForm({ ...taskForm, stopOnBlocked: event.target.checked })}
                />
                Останавливать при блокировках
                <HelpTip text="Автоматическая пауза, если процент заблокированных аккаунтов выше порога." />
                <span className="hint">Останавливает задачу, если % ограниченных аккаунтов выше порога.</span>
              </label>
            </div>
            <div className="toggle-row">
              <label className="checkbox">
                <input
                  type="checkbox"
                  checked={Boolean(taskForm.allowStartWithoutInviteRights)}
                  onChange={(event) => setTaskForm({ ...taskForm, allowStartWithoutInviteRights: event.target.checked })}
                />
                Разрешать запуск без прав инвайта
                <HelpTip text="Полезно, если права инвайта будут выданы позже." />
                <span className="hint">Полезно, если вы выдаёте админов после автодобавления.</span>
              </label>
              <label className="checkbox">
                <input
                  type="checkbox"
                  checked={Boolean(taskForm.useWatcherInviteNoUsername)}
                  onChange={(event) => setTaskForm({ ...taskForm, useWatcherInviteNoUsername: event.target.checked })}
                />
                Инвайт через наблюдателя, если нет username
                <HelpTip text="Если username отсутствует, инвайт идёт аккаунтом‑наблюдателем, потому что access_hash валиден в его сессии." />
                <span className="hint">
                  Правило 1: сначала резолвим @username в сессии инвайтера — участие в группе конкурентов не требуется.
                </span>
                <span className="hint">
                  Правило 2: если username нет — инвайтим наблюдателем, потому что access_hash валиден только в его сессии.
                </span>
              </label>
            </div>
            <div className="row">
              <label>
                <span className="label-line">Остановить при блоке, %</span>
                <input
                  type="number"
                  min="1"
                  value={taskForm.stopBlockedPercent === "" ? "" : taskForm.stopBlockedPercent}
                  onChange={(event) => {
                    const value = event.target.value;
                    setTaskForm({ ...taskForm, stopBlockedPercent: value === "" ? "" : Number(value) });
                  }}
                  onBlur={() => {
                    const value = Number(taskForm.stopBlockedPercent);
                    setTaskForm({ ...taskForm, stopBlockedPercent: Number.isFinite(value) && value > 0 ? value : 1 });
                  }}
                  disabled={!taskForm.stopOnBlocked}
                />
              </label>
            </div>
            <details className="section">
              <summary className="section-title">Импорт аудитории <span className="status-caption">необязательно</span></summary>
              <div className="status-text compact">Используйте только если нужен импорт из файла или полный список участников.</div>
              <div className="row-inline">
                <button className="secondary" type="button" onClick={importInviteFile}>
                  Импортировать файл
                </button>
                {fileImportResult && (
                  <div className="status-text compact">
                    Импортировано: {fileImportResult.importedCount} · Пропущено: {fileImportResult.skippedCount} · Ошибок: {fileImportResult.failed.length}
                  </div>
                )}
              </div>
              <details className="section">
                <summary className="section-title">Дополнительные параметры</summary>
                <div className="row">
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.parseParticipants)}
                      onChange={(event) => setTaskForm({ ...taskForm, parseParticipants: event.target.checked })}
                    />
                    Собирать участников чатов конкурентов
                    <span className="hint">
                      Используется для закрытых участников и полного списка аудитории.
                    </span>
                  </label>
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(taskForm.cycleCompetitors)}
                      onChange={(event) => setTaskForm({ ...taskForm, cycleCompetitors: event.target.checked })}
                    />
                    Циклически обходить конкурентов
                    <span className="hint">
                      Мониторинг и сбор будут переключаться по группам по очереди.
                    </span>
                  </label>
                  <label className="checkbox">
                    <input
                      type="checkbox"
                      checked={Boolean(fileImportForm.onlyIds)}
                      onChange={(event) => setFileImportForm({ ...fileImportForm, onlyIds: event.target.checked })}
                    />
                    В файле только ID
                    <span className="hint">Если включено — нужен источник (чат), из которого брались ID.</span>
                  </label>
                  <label>
                    <span className="label-line">Источник для ID</span>
                    <input
                      type="text"
                      placeholder="https://t.me/чат"
                      value={fileImportForm.sourceChat}
                      onChange={(event) => setFileImportForm({ ...fileImportForm, sourceChat: event.target.value })}
                      disabled={!fileImportForm.onlyIds}
                    />
                    <span className="hint">Используется для резолва ID при инвайте.</span>
                  </label>
                </div>
              </details>
              {fileImportResult && fileImportResult.failed.length > 0 && (
                <div className="access-list">
                  {fileImportResult.failed.map((item, index) => (
                    <div key={`${item.path}-${index}`} className="access-row fail">
                      <div className="access-title">{item.path}</div>
                      <div className="access-error">{item.error}</div>
                    </div>
                  ))}
                </div>
              )}
            </details>
            <details className="section">
              <summary className="section-title">Ошибки аккаунтов</summary>
              {criticalErrorAccounts.length === 0 && (
                <div className="status-text compact">Ошибок нет.</div>
              )}
              {criticalErrorAccounts.length > 0 && (
                <div className="access-list">
                  {criticalErrorAccounts.map((account) => (
                    <div key={account.id} className="access-row fail">
                      <div className="access-title">{formatAccountLabel(account)}</div>
                      <div className="access-error">{account.last_error || "Ошибка сессии"}</div>
                    </div>
                  ))}
                </div>
              )}
            </details>
            <label>
              <span className="label-line">Заметки</span>
              <textarea
                rows="2"
                value={taskForm.notes}
                onChange={(event) => setTaskForm({ ...taskForm, notes: event.target.value })}
              />
            </label>
          </details>
        </div>
      </details>
    </div>
  );
}
