/* global React */
(function () {
  const { useState, useEffect, useRef, useCallback, memo } = React;
  const T   = window.SC_T;
  const Api = window.SC_Api;

  const PAGE_SIZE = 100;

  const LIMITS = {
    yandex_title:  56,
    yandex_title2: 56,
    yandex_desc:   81,
    google_title1: 30,
    google_desc1:  90,
  };

  const EMPTY_SET = new Set();

  const COLS = [
    { field: 'yandex_title',  label: 'Заголовок 1', group: 'yandex' },
    { field: 'yandex_title2', label: 'Заголовок 2', group: 'yandex' },
    { field: 'yandex_desc',   label: 'Текст',        group: 'yandex' },
    { field: 'google_title1', label: 'Заголовок',    group: 'google' },
    { field: 'google_desc1',  label: 'Описание',     group: 'google' },
  ];

  // ── Ячейка редактирования ─────────────────────────────────────────────────

  const AdCell = memo(function AdCell({ field, value, saving, onChange }) {
    const limit = LIMITS[field];
    const over  = (value || '').length > limit;
    const isLong = limit >= 81;

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 2, padding: '8px 10px', minWidth: 0 }}>
        <div style={{ position: 'relative' }}>
          {isLong ? (
            <textarea
              value={value || ''}
              onChange={(e) => onChange(field, e.target.value)}
              rows={2}
              style={{
                width: '100%', fontFamily: 'inherit', fontSize: 12,
                border: `1px solid ${over ? T.err : T.border}`, borderRadius: 5,
                padding: '5px 7px', background: T.bg, color: T.ink,
                outline: 'none', resize: 'vertical', lineHeight: 1.4,
                transition: 'border-color .15s',
              }}
            />
          ) : (
            <input
              type="text"
              value={value || ''}
              onChange={(e) => onChange(field, e.target.value)}
              style={{
                width: '100%', fontFamily: 'inherit', fontSize: 12,
                border: `1px solid ${over ? T.err : T.border}`, borderRadius: 5,
                padding: '5px 7px', background: T.bg, color: T.ink,
                outline: 'none', transition: 'border-color .15s',
              }}
            />
          )}
        </div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 6, minHeight: 14 }}>
          {over ? (
            <span style={{ fontSize: 10, color: T.err, fontWeight: 600 }}>слишком много символов</span>
          ) : saving ? (
            <span style={{ fontSize: 10, color: T.inkSubtle }}>сохраняется…</span>
          ) : null}
          <span style={{
            fontSize: 10, flexShrink: 0,
            fontVariantNumeric: 'tabular-nums',
            color: over ? T.err : (value || '').length >= limit * 0.85 ? T.warn : T.inkSubtle,
          }}>
            {(value || '').length}/{limit}
          </span>
        </div>
      </div>
    );
  });

  // ── Строка фразы ─────────────────────────────────────────────────────────

  const PhraseRow = memo(function PhraseRow({
    index, phrase, ad, status, savingFields, globalUrl, useCustomUrl, onFieldChange, onCustomUrlToggle,
  }) {
    const [hover, setHover] = useState(false);

    const statusColor = status === 'done' ? T.ok : status === 'generating' ? T.accent : T.inkSubtle;
    const rowBg = hover ? '#EDEFF2' : '#F8F9FB';

    const handleChange = useCallback(
      (field, value) => onFieldChange(phrase, field, value),
      [phrase, onFieldChange],
    );

    const handleUrlToggle = useCallback((e) => {
      onCustomUrlToggle(phrase, e.target.checked);
    }, [phrase, onCustomUrlToggle]);

    return (
      <tr
        onMouseEnter={() => setHover(true)}
        onMouseLeave={() => setHover(false)}
        style={{ borderBottom: `1px solid ${T.border}`, transition: 'background .1s' }}
      >
        {/* # */}
        <td style={{
          padding: '0 6px', textAlign: 'center', verticalAlign: 'middle',
          fontSize: 11, fontVariantNumeric: 'tabular-nums', color: T.inkSubtle,
          position: 'sticky', left: 0, zIndex: 2,
          background: hover ? '#EAECF0' : T.borderSoft,
          borderRight: `1px solid ${T.border}`, transition: 'background .1s',
          userSelect: 'none',
        }}>
          {index}
        </td>

        {/* Фраза + URL */}
        <td style={{
          padding: '8px 12px', fontSize: 12.5, fontWeight: 500, color: T.ink,
          verticalAlign: 'middle', position: 'sticky', left: 44, zIndex: 1,
          background: hover ? '#F3F4F6' : T.surface, minWidth: 180, maxWidth: 240,
          borderRight: `1px solid ${T.border}`, transition: 'background .1s',
        }}>
          <div style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{phrase}</div>
          <div style={{ fontSize: 10, color: statusColor, marginTop: 2 }}>
            {status === 'done' ? '✓ готово' : status === 'generating' ? '⟳ в очереди…' : '— ожидает'}
          </div>
          {/* URL */}
          <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column', gap: 3 }}>
            <label style={{ display: 'flex', alignItems: 'center', gap: 5, cursor: 'pointer', userSelect: 'none' }}>
              <input
                type="checkbox"
                checked={useCustomUrl}
                onChange={handleUrlToggle}
                style={{ cursor: 'pointer', accentColor: T.accent }}
              />
              <span style={{ fontSize: 10, color: T.inkMuted }}>Своя ссылка</span>
            </label>
            {useCustomUrl ? (
              <input
                type="url"
                value={ad?.url || ''}
                onChange={(e) => handleChange('url', e.target.value)}
                placeholder="https://…"
                style={{
                  width: '100%', fontFamily: 'inherit', fontSize: 11,
                  border: `1px solid ${T.border}`, borderRadius: 4,
                  padding: '3px 6px', background: T.bg, color: T.ink, outline: 'none',
                }}
              />
            ) : globalUrl ? (
              <div style={{
                fontSize: 10, color: T.inkSubtle, overflow: 'hidden',
                textOverflow: 'ellipsis', whiteSpace: 'nowrap',
              }} title={globalUrl}>{globalUrl}</div>
            ) : (
              <div style={{ fontSize: 10, color: T.inkSubtle, fontStyle: 'italic' }}>ссылка не задана</div>
            )}
          </div>
        </td>

        {COLS.map(({ field }) => (
          <td key={field} style={{
            verticalAlign: 'top', borderRight: `1px solid ${T.border}`,
            minWidth: field.includes('desc') ? 200 : 150,
            background: rowBg, transition: 'background .1s',
          }}>
            <AdCell
              field={field}
              value={ad?.[field] || ''}
              saving={savingFields.has(field)}
              onChange={handleChange}
            />
          </td>
        ))}
      </tr>
    );
  });

  // ── Пагинация ─────────────────────────────────────────────────────────────

  const btnStyle = (disabled) => ({
    border: `1px solid ${T.border}`, borderRadius: 7,
    padding: '5px 14px', fontSize: 12, fontWeight: 500,
    fontFamily: 'inherit', cursor: disabled ? 'not-allowed' : 'pointer',
    background: disabled ? T.borderSoft : T.bg,
    color: disabled ? T.inkSubtle : T.ink,
    transition: 'background .12s',
  });

  function Pagination({ page, totalPages, onGoTo }) {
    const [inputVal, setInputVal] = useState(String(page));

    useEffect(() => { setInputVal(String(page)); }, [page]);

    const commit = () => {
      const n = parseInt(inputVal, 10);
      if (!isNaN(n)) onGoTo(n);
      else setInputVal(String(page));
    };

    if (totalPages <= 1) return null;

    return (
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
        padding: '8px 20px', borderTop: `1px solid ${T.border}`,
        background: T.surface, flexShrink: 0,
      }}>
        <button style={btnStyle(page === 1)} disabled={page === 1} onClick={() => onGoTo(page - 1)}>
          ← Пред.
        </button>
        <span style={{ fontSize: 12, color: T.inkMuted, whiteSpace: 'nowrap' }}>Страница</span>
        <input
          type="number" min={1} max={totalPages}
          value={inputVal}
          onChange={(e) => setInputVal(e.target.value)}
          onBlur={commit}
          onKeyDown={(e) => e.key === 'Enter' && commit()}
          style={{
            width: 52, fontFamily: 'inherit', fontSize: 12,
            border: `1px solid ${T.border}`, borderRadius: 6,
            padding: '4px 6px', background: T.bg, color: T.ink,
            outline: 'none', textAlign: 'center',
          }}
        />
        <span style={{ fontSize: 12, color: T.inkMuted, whiteSpace: 'nowrap' }}>из {totalPages}</span>
        <button style={btnStyle(page === totalPages)} disabled={page === totalPages} onClick={() => onGoTo(page + 1)}>
          Далее →
        </button>
      </div>
    );
  }

  // ── Главный компонент ─────────────────────────────────────────────────────

  function AdGenScreen({ jobId, phrases, onBack }) {
    const [prompt, setPrompt]         = useState('');
    const [globalUrl, setGlobalUrl]   = useState('');
    const [ads, setAds]               = useState({});
    const [statuses, setStatuses]     = useState({});
    const [generating, setGenerating] = useState(false);
    const [progress, setProgress]     = useState({ done: 0, total: 0 });
    const [savingFields, setSavingFields] = useState({});
    const [startFrom, setStartFrom]   = useState(1);
    const [customUrls, setCustomUrls] = useState(new Set());
    const [page, setPage]             = useState(1);

    const adsRef       = useRef({});
    const saveTimers   = useRef({});
    const urlSaveTimer = useRef(null);
    const tableRef     = useRef(null);

    const total      = phrases.length;
    const totalPages = Math.ceil(total / PAGE_SIZE) || 1;

    const goToPage = useCallback((p) => {
      const clamped = Math.max(1, Math.min(totalPages, p));
      setPage(clamped);
      if (tableRef.current) tableRef.current.scrollTop = 0;
    }, [totalPages]);

    // ── Загрузка данных с сервера ──────────────────────────────────────────

    const loadAdsFromServer = useCallback(async () => {
      try {
        const adsData = await Api.getJson(`/api/job/${jobId}/ads`);
        const map = {}, st = {}, customSet = new Set();
        adsData.forEach((a) => {
          map[a.phrase] = a;
          st[a.phrase] = 'done';
          if (a.url) customSet.add(a.phrase);
        });
        setAds(map);
        adsRef.current = map;
        setStatuses(st);
        setCustomUrls(customSet);
      } catch {}
    }, [jobId]);

    // ── Инициализация: загрузка существующих данных + проверка статуса ────

    useEffect(() => {
      if (!jobId) return;
      Promise.all([
        Api.getJson(`/api/job/${jobId}/ads`),
        Api.getJson(`/api/job/${jobId}`),
        Api.getJson(`/api/job/${jobId}/ads/status`).catch(() => null),
      ]).then(([adsData, jobData, statusData]) => {
        const map = {}, st = {}, customSet = new Set();
        adsData.forEach((a) => {
          map[a.phrase] = a;
          st[a.phrase] = 'done';
          if (a.url) customSet.add(a.phrase);
        });
        setAds(map);
        adsRef.current = map;
        setStatuses(st);
        setCustomUrls(customSet);

        if (jobData.global_url) setGlobalUrl(jobData.global_url);

        // Восстанавливаем промпт из сервера если есть
        if (statusData?.prompt) setPrompt(statusData.prompt);

        // Если генерация уже идёт в фоне — подключаемся к прогрессу
        if (statusData?.generating) {
          setGenerating(true);
          setProgress({ done: statusData.done_count || 0, total: statusData.total || 0 });
        }
      }).catch(() => {});
    }, [jobId]);

    // ── Polling пока идёт генерация ───────────────────────────────────────

    useEffect(() => {
      if (!generating) return;

      const id = setInterval(async () => {
        try {
          const [adsData, statusData] = await Promise.all([
            Api.getJson(`/api/job/${jobId}/ads`),
            Api.getJson(`/api/job/${jobId}/ads/status`),
          ]);
          const map = {}, st = {}, customSet = new Set();
          adsData.forEach((a) => {
            map[a.phrase] = a;
            st[a.phrase] = 'done';
            if (a.url) customSet.add(a.phrase);
          });
          setAds(map);
          adsRef.current = map;
          setStatuses(st);
          setCustomUrls(customSet);
          setProgress({ done: statusData.done_count || 0, total: statusData.total || 0 });

          if (!statusData.generating) {
            setGenerating(false);
          }
        } catch {}
      }, 2500);

      return () => clearInterval(id);
    }, [generating, jobId]);

    // ── Управление генерацией ─────────────────────────────────────────────

    const startGeneration = useCallback(async () => {
      const from = Math.max(1, Math.min(phrases.length, startFrom || 1));
      const toGenerate = phrases.slice(from - 1);
      if (!prompt.trim() || generating || !toGenerate.length) return;

      setGenerating(true);
      setProgress({ done: 0, total: toGenerate.length });

      // Ставим все фразы в статус «в очереди»
      setStatuses((prev) => {
        const next = { ...prev };
        toGenerate.forEach((p) => { if (!next[p] || next[p] !== 'done') next[p] = 'generating'; });
        return next;
      });

      const token = localStorage.getItem('sc_token') || '';
      try {
        const resp = await fetch(`/api/job/${jobId}/ads/generate`, {
          method: 'POST',
          headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
          body: JSON.stringify({ phrases: toGenerate, prompt }),
        });
        if (!resp.ok) {
          setGenerating(false);
          return;
        }
        // Задача запущена на сервере — polling подхватит прогресс
      } catch {
        setGenerating(false);
      }
    }, [jobId, phrases, prompt, generating, startFrom]);

    const stopGeneration = useCallback(async () => {
      setGenerating(false);
      const token = localStorage.getItem('sc_token') || '';
      try {
        await fetch(`/api/job/${jobId}/ads/stop`, {
          method: 'POST',
          headers: { 'Authorization': 'Bearer ' + token },
        });
      } catch {}
      // Обновляем список — часть фраз могла успеть сгенерироваться
      await loadAdsFromServer();
    }, [jobId, loadAdsFromServer]);

    // ── Глобальный URL ────────────────────────────────────────────────────

    const handleGlobalUrlChange = useCallback((val) => {
      setGlobalUrl(val);
      if (urlSaveTimer.current) clearTimeout(urlSaveTimer.current);
      urlSaveTimer.current = setTimeout(() => {
        Api.patchJson(`/api/job/${jobId}/global-url`, { global_url: val }).catch(() => {});
      }, 1500);
    }, [jobId]);

    // ── Редактирование ячеек ──────────────────────────────────────────────

    const handleFieldChange = useCallback((phrase, field, value) => {
      setAds((prev) => {
        const next = { ...prev, [phrase]: { ...(prev[phrase] || {}), [field]: value } };
        adsRef.current = next;
        return next;
      });

      const key = `${phrase}\x00${field}`;
      if (saveTimers.current[key]) clearTimeout(saveTimers.current[key]);

      const limit = LIMITS[field];
      if (limit && (value || '').length > limit) return;

      saveTimers.current[key] = setTimeout(async () => {
        setSavingFields((prev) => {
          const set = new Set(prev[phrase] || []);
          set.add(field);
          return { ...prev, [phrase]: set };
        });
        const current = adsRef.current[phrase] || {};
        try { await Api.patchJson(`/api/job/${jobId}/ads`, { phrase, ...current }); } catch {}
        setSavingFields((prev) => {
          const set = new Set(prev[phrase] || []);
          set.delete(field);
          return { ...prev, [phrase]: set };
        });
        delete saveTimers.current[key];
      }, 2000);
    }, [jobId]);

    const handleCustomUrlToggle = useCallback((phrase, checked) => {
      setCustomUrls((prev) => {
        const next = new Set(prev);
        if (checked) next.add(phrase); else next.delete(phrase);
        return next;
      });
      if (!checked) handleFieldChange(phrase, 'url', '');
    }, [handleFieldChange]);

    // ── Производные ───────────────────────────────────────────────────────

    const fromIdx  = Math.max(1, Math.min(total, startFrom || 1));
    const genCount = total - fromIdx + 1;
    const done     = progress.done;

    const pageStart   = (page - 1) * PAGE_SIZE;
    const pagePhrases = phrases.slice(pageStart, pageStart + PAGE_SIZE);

    // ── Render ────────────────────────────────────────────────────────────

    return (
      <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>

        {/* Top bar */}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '12px 20px', borderBottom: `1px solid ${T.border}`,
          background: T.surface, flexShrink: 0,
        }}>
          <button onClick={onBack} style={{
            border: `1px solid ${T.border}`, background: T.bg, borderRadius: 8,
            padding: '6px 14px', fontSize: 13, color: T.inkMuted,
            cursor: 'pointer', fontFamily: 'inherit', display: 'flex', alignItems: 'center', gap: 6,
          }}>← Назад</button>
          <span style={{ fontSize: 14, fontWeight: 600, color: T.ink, flex: 1 }}>Генератор рекламы</span>
          {generating && (
            <span style={{ fontSize: 12, color: T.inkMuted }}>
              {done} / {progress.total || '?'} фраз • работает в фоне
            </span>
          )}
        </div>

        {/* Prompt + Global URL */}
        <div style={{
          padding: '14px 20px', borderBottom: `1px solid ${T.border}`,
          background: T.surface, flexShrink: 0,
        }}>
          <div style={{ fontSize: 12, fontWeight: 600, color: T.inkMuted, marginBottom: 6 }}>
            Промпт — опишите продукт или услугу для ИИ:
          </div>
          <div style={{ display: 'flex', gap: 10, marginBottom: 10 }}>
            <textarea
              value={prompt}
              onChange={(e) => setPrompt(e.target.value)}
              placeholder="Например: интернет-магазин диванов. Бесплатная доставка по Москве."
              rows={2}
              style={{
                flex: 1, fontFamily: 'inherit', fontSize: 13,
                border: `1px solid ${T.border}`, borderRadius: 8,
                padding: '8px 12px', background: T.bg, color: T.ink,
                outline: 'none', resize: 'vertical', lineHeight: 1.5,
              }}
            />
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, flexShrink: 0 }}>
              <button
                onClick={generating ? stopGeneration : startGeneration}
                disabled={!generating && (!prompt.trim() || !total)}
                style={{
                  border: 'none', borderRadius: 8, padding: '0 20px', height: 40,
                  background: generating
                    ? '#DC2626'
                    : (!prompt.trim() || !total) ? T.borderSoft : T.accent,
                  color: (!generating && (!prompt.trim() || !total)) ? T.inkSubtle : '#fff',
                  fontSize: 13, fontWeight: 600, fontFamily: 'inherit',
                  cursor: (!generating && (!prompt.trim() || !total)) ? 'not-allowed' : 'pointer',
                  whiteSpace: 'nowrap', transition: 'background .15s',
                  display: 'flex', alignItems: 'center', gap: 8,
                }}
              >
                {generating ? (
                  '⏹ Остановить'
                ) : (
                  <>
                    Сгенерировать
                    <span style={{
                      background: 'rgba(255,255,255,.2)', borderRadius: 5,
                      padding: '1px 7px', fontSize: 11, fontWeight: 700,
                    }}>{genCount}</span>
                  </>
                )}
              </button>
              {!generating && total > 0 && (
                <div style={{ display: 'flex', alignItems: 'center', gap: 5, justifyContent: 'flex-end' }}>
                  <span style={{ fontSize: 11, color: T.inkSubtle, whiteSpace: 'nowrap' }}>с фразы</span>
                  <input
                    type="number" min={1} max={total} value={startFrom}
                    onChange={(e) => setStartFrom(Math.max(1, Math.min(total, parseInt(e.target.value) || 1)))}
                    style={{
                      width: 52, fontFamily: 'inherit', fontSize: 12,
                      border: `1px solid ${T.border}`, borderRadius: 6,
                      padding: '3px 6px', background: T.bg, color: T.ink,
                      outline: 'none', textAlign: 'center',
                    }}
                  />
                  <span style={{ fontSize: 11, color: T.inkSubtle }}>/ {total}</span>
                </div>
              )}
            </div>
          </div>

          {/* Глобальный URL */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontSize: 12, fontWeight: 600, color: T.inkMuted, whiteSpace: 'nowrap' }}>
              Ссылка для всех фраз:
            </span>
            <input
              type="url"
              value={globalUrl}
              onChange={(e) => handleGlobalUrlChange(e.target.value)}
              placeholder="https://example.com/?utm_source=yandex&utm_medium=cpc"
              style={{
                flex: 1, fontFamily: 'inherit', fontSize: 12,
                border: `1px solid ${T.border}`, borderRadius: 7,
                padding: '6px 10px', background: T.bg, color: T.ink, outline: 'none',
              }}
            />
          </div>

          {generating && (
            <div style={{ marginTop: 10 }}>
              <div style={{ height: 4, background: T.borderSoft, borderRadius: 99, overflow: 'hidden' }}>
                <div style={{
                  height: '100%', background: T.accent, borderRadius: 99,
                  width: `${progress.total ? (done / progress.total) * 100 : 0}%`,
                  transition: 'width .5s ease',
                }} />
              </div>
              <div style={{ fontSize: 11, color: T.inkSubtle, marginTop: 4 }}>
                Генерация идёт в фоне — можно закрыть страницу, прогресс сохранится
              </div>
            </div>
          )}
        </div>

        {/* Table */}
        <div ref={tableRef} style={{ flex: 1, overflow: 'auto' }}>
          {phrases.length === 0 ? (
            <div style={{ textAlign: 'center', padding: 40, color: T.inkSubtle, fontSize: 13 }}>
              Нет фраз для генерации. Вернитесь к результатам.
            </div>
          ) : (
            <table style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
              <colgroup>
                <col style={{ width: 44 }} />
                <col style={{ width: 220 }} />
                <col style={{ width: 175 }} />
                <col style={{ width: 175 }} />
                <col style={{ width: 220 }} />
                <col style={{ width: 155 }} />
                <col style={{ width: 240 }} />
              </colgroup>
              <thead>
                <tr>
                  <th style={{
                    position: 'sticky', top: 0, left: 0, zIndex: 5,
                    background: '#EAECEF', borderBottom: `2px solid ${T.border}`,
                    borderRight: `1px solid ${T.border}`,
                    padding: '10px 6px', textAlign: 'center',
                    fontSize: 11, fontWeight: 600, color: T.inkMuted, letterSpacing: '0.04em',
                  }}>#</th>
                  <th style={{
                    position: 'sticky', top: 0, left: 44, zIndex: 4,
                    background: '#FAFBFC', borderBottom: `2px solid ${T.border}`,
                    borderRight: `1px solid ${T.borderSoft}`,
                    padding: '10px 12px', textAlign: 'left',
                    fontSize: 11, fontWeight: 600, color: T.inkMuted,
                    letterSpacing: '0.06em', textTransform: 'uppercase',
                  }}>Фраза / Ссылка</th>
                  {COLS.map(({ field, label, group }) => (
                    <th key={field} style={{
                      position: 'sticky', top: 0, zIndex: 3,
                      background: '#FAFBFC', borderBottom: `2px solid ${T.border}`,
                      borderRight: `1px solid ${T.borderSoft}`,
                      padding: '8px 10px', textAlign: 'left',
                      fontSize: 11, fontWeight: 600,
                    }}>
                      <div style={{
                        fontSize: 10, fontWeight: 700, marginBottom: 2,
                        color: group === 'yandex' ? T.accent : '#4285F4',
                        textTransform: 'uppercase', letterSpacing: '0.06em',
                      }}>
                        {group === 'yandex' ? 'Яндекс' : 'Google'}
                      </div>
                      <div style={{ color: T.inkMuted }}>{label}</div>
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {pagePhrases.map((phrase, i) => (
                  <PhraseRow
                    key={phrase}
                    index={pageStart + i + 1}
                    phrase={phrase}
                    ad={ads[phrase] || {}}
                    status={statuses[phrase] || 'pending'}
                    savingFields={savingFields[phrase] || EMPTY_SET}
                    globalUrl={globalUrl}
                    useCustomUrl={customUrls.has(phrase)}
                    onFieldChange={handleFieldChange}
                    onCustomUrlToggle={handleCustomUrlToggle}
                  />
                ))}
              </tbody>
            </table>
          )}
        </div>

        {/* Pagination */}
        <Pagination page={page} totalPages={totalPages} onGoTo={goToPage} />
      </div>
    );
  }

  window.AdGenScreen = AdGenScreen;
})();
