import { useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { AlertTriangle, X } from 'lucide-react'
import {
  getAdminSettings,
  sendTestEmail,
  updateAdminSettings,
  type AiLevel,
  type SettingsOut,
  type SettingsUpdateIn,
  type TestEmailOut,
} from '@/api/admin'
import type { PublishQualityCap, SummaryRecipientsMode } from '@/api/conferences'
import { ApiError, errorDetail } from '@/api/client'
import { useAuth } from '@/auth/useAuth'
import { Select } from '@/components/ui/Select'
import { useToast } from '@/components/ui/ToastProvider'

const SUMMARY_RECIPIENTS_OPTIONS = [
  { value: 'all', label: 'Всем участникам' },
  { value: 'owner', label: 'Только организатору' },
]

const PUBLISH_QUALITY_CAP_OPTIONS = [
  { value: 'off', label: 'Без ограничения' },
  { value: '720p', label: 'Не выше 720p' },
  { value: '360p', label: 'Не выше 360p' },
  { value: '180p', label: 'Не выше 180p' },
]

const STAGE_MAX_TILES_OPTIONS = [
  { value: '25', label: '25 (5×5, без ограничения)' },
  { value: '16', label: '16 (4×4)' },
  { value: '9', label: '9 (3×3)' },
  { value: '4', label: '4 (2×2)' },
]

const AI_LEVEL_LABEL: Record<AiLevel, string> = {
  min: 'Минимальный (CPU, faster-whisper small + Qwen2.5-3B)',
  medium: 'Средний',
  max: 'Максимальный',
}

/**
 * Вкладка «Настройки» админки — раздела нет в макете `admin.html`, построена
 * по паттерну того же макета (`section-tab`/`table-card` → карточки-секции
 * с `toggle-row`/radio).
 * Тумблер «Транскрибация и суммаризация» — единый переключатель AI-модуля
 * (см. `SettingsOut.transcription_enabled`).
 *
 * Форма (`AdminSettingsForm`) вынесена отдельно и монтируется только после
 * загрузки `data` — локальное состояние инициализируется прямо из пропсов
 * при монтировании, без `useEffect`-синхронизации (react-hooks/set-state-in-effect).
 */
export function AdminSettingsTab() {
  const { data, isLoading } = useQuery({ queryKey: ['admin', 'settings'], queryFn: getAdminSettings })

  if (isLoading || !data) {
    return <p className="field-hint">Загрузка настроек…</p>
  }

  return <AdminSettingsForm data={data} />
}

function AdminSettingsForm({ data }: { data: SettingsOut }) {
  const queryClient = useQueryClient()
  const toast = useToast()
  const { user } = useAuth()

  const [chatEnabled, setChatEnabled] = useState(data.chat_enabled)
  const [handQueueEnabled, setHandQueueEnabled] = useState(data.hand_queue_enabled)
  const [deviceCheckEnabled, setDeviceCheckEnabled] = useState(data.device_check_enabled)
  const [virtualBackgroundEnabled, setVirtualBackgroundEnabled] = useState(
    data.virtual_background_enabled,
  )
  const [aiEnabled, setAiEnabled] = useState(data.transcription_enabled)
  const [aiLevel, setAiLevel] = useState<AiLevel>(data.ai_level)
  const [recipients, setRecipients] = useState<SummaryRecipientsMode>(data.summary_recipients)
  const [timezone, setTimezone] = useState(data.display_timezone)
  const [teamChoiceEnabled, setTeamChoiceEnabled] = useState(data.registration_team_choice)
  const [domainVerificationEnabled, setDomainVerificationEnabled] = useState(data.registration_email_domain_enabled)
  const [emailDomains, setEmailDomains] = useState(data.registration_email_domains)
  const [newDomainInput, setNewDomainInput] = useState('')
  const [contactEmailEnabled, setContactEmailEnabled] = useState(data.contact_email_enabled)
  const [contactEmail, setContactEmail] = useState(data.contact_email ?? '')
  const [publishQualityCap, setPublishQualityCap] = useState<PublishQualityCap>(data.publish_quality_cap)
  const [stageMaxTiles, setStageMaxTiles] = useState(data.stage_max_tiles)
  const [consentRequired, setConsentRequired] = useState(data.consent_required)
  const [consentPolicyText, setConsentPolicyText] = useState(data.consent_policy_text)
  const [testEmailTo, setTestEmailTo] = useState('')
  const [testEmailResult, setTestEmailResult] = useState<TestEmailOut | null>(null)

  const mutation = useMutation({
    mutationFn: (payload: SettingsUpdateIn) => updateAdminSettings(payload),
    onSuccess: (result) => {
      queryClient.setQueryData(['admin', 'settings'], result)
      toast.show('Настройки сохранены', 'success')
    },
    onError: (err: unknown) => {
      if (err instanceof ApiError && err.status === 400) {
        toast.show(
          errorDetail(err) ??
            'Недоступное значение — проверьте уровень AI, таймзону, домен почты и текст регламента',
          'error',
        )
      } else {
        toast.show('Не удалось сохранить настройки', 'error')
      }
    },
  })

  const testEmailMutation = useMutation({
    mutationFn: () => sendTestEmail(testEmailTo.trim() ? { to: testEmailTo.trim() } : {}),
    onSuccess: (result) => setTestEmailResult(result),
    onError: (err: unknown) => {
      setTestEmailResult({
        success: false,
        message: (err instanceof ApiError && errorDetail(err)) || 'Не удалось отправить тестовое письмо',
        smtp_host: null,
        smtp_port: null,
      })
    },
  })

  function addDomain() {
    const domain = newDomainInput.trim().toLowerCase().replace(/^@/, '')
    if (!domain || emailDomains.includes(domain)) {
      setNewDomainInput('')
      return
    }
    setEmailDomains([...emailDomains, domain])
    setNewDomainInput('')
  }

  function removeDomain(domain: string) {
    setEmailDomains(emailDomains.filter((d) => d !== domain))
  }

  function handleSave() {
    // Отправляем только реально изменённые поля (`SettingsUpdateIn` — набор
    // опциональных полей именно для этого): иначе, например, ai_level
    // уходил бы в PUT нетронутым при каждом сохранении и на слабом железе
    // валился бы в 400, блокируя правку вообще любой другой настройки.
    const payload: SettingsUpdateIn = {}
    if (chatEnabled !== data.chat_enabled) payload.chat_enabled = chatEnabled
    if (handQueueEnabled !== data.hand_queue_enabled) payload.hand_queue_enabled = handQueueEnabled
    if (deviceCheckEnabled !== data.device_check_enabled) payload.device_check_enabled = deviceCheckEnabled
    if (virtualBackgroundEnabled !== data.virtual_background_enabled)
      payload.virtual_background_enabled = virtualBackgroundEnabled
    if (aiEnabled !== data.transcription_enabled) payload.transcription_enabled = aiEnabled
    if (aiLevel !== data.ai_level) payload.ai_level = aiLevel
    if (recipients !== data.summary_recipients) payload.summary_recipients = recipients
    if (timezone.trim() !== data.display_timezone) payload.display_timezone = timezone.trim()
    if (teamChoiceEnabled !== data.registration_team_choice) {
      payload.registration_team_choice = teamChoiceEnabled
    }
    if (domainVerificationEnabled !== data.registration_email_domain_enabled) {
      payload.registration_email_domain_enabled = domainVerificationEnabled
    }
    if (JSON.stringify(emailDomains) !== JSON.stringify(data.registration_email_domains)) {
      payload.registration_email_domains = emailDomains
    }
    if (contactEmailEnabled !== data.contact_email_enabled) {
      payload.contact_email_enabled = contactEmailEnabled
    }
    const trimmedContactEmail = contactEmail.trim() || null
    if (trimmedContactEmail !== (data.contact_email ?? null)) {
      payload.contact_email = trimmedContactEmail
    }
    if (publishQualityCap !== data.publish_quality_cap) payload.publish_quality_cap = publishQualityCap
    if (stageMaxTiles !== data.stage_max_tiles) payload.stage_max_tiles = stageMaxTiles
    if (consentRequired !== data.consent_required) payload.consent_required = consentRequired
    if (consentPolicyText !== data.consent_policy_text) payload.consent_policy_text = consentPolicyText
    mutation.mutate(payload)
  }

  return (
    <div className="settings-grid">
      <section className="settings-card">
        <h2>Модули</h2>
        <p className="desc">Включение и отключение возможностей инстанса — переключатели плагинов из поставки.</p>

        <div className="settings-card-body settings-card-body--spread">
          <div className="toggle-row" style={{ borderTop: 'none', paddingTop: 0 }}>
            <div className="toggle-copy">
              <strong>Чат конференции</strong>
              <span>Текстовый чат внутри комнаты для участников</span>
            </div>
            <label className="switch">
              <input type="checkbox" checked={chatEnabled} onChange={(e) => setChatEnabled(e.target.checked)} />
              <span className="slider" />
            </label>
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Поднятие руки</strong>
              <span>Кнопка «Рука» и очередь поднятых рук в комнате — целиком</span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={handQueueEnabled}
                onChange={(e) => setHandQueueEnabled(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Проверка устройств на входе</strong>
              <span>
                Запрос доступа к камере и микрофону и превью камеры на странице входа и в
                карточке «Как вас зовут?» — чтобы разрешение не выскакивало уже внутри
                конференции. Микрофон и камера в самой конференции по-прежнему выключены при
                входе
              </span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={deviceCheckEnabled}
                onChange={(e) => setDeviceCheckEnabled(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Замена фона видео</strong>
              <span>
                Выбор фона в конференции: три готовые сцены и свои картинки (до 10 штук,
                загружаются в профиле). Работает только на компьютере — фон считает нейросеть
                на каждом кадре, и на телефоне это греет устройство и просаживает встречу
              </span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={virtualBackgroundEnabled}
                onChange={(e) => setVirtualBackgroundEnabled(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Транскрибация и суммаризация (AI)</strong>
              <span>Батч-обработка записи после конференции: расшифровка речи и саммари</span>
              {aiEnabled && !data.transcription_queue_served && (
                <span className="ai-level-reason">
                  <AlertTriangle style={{ width: 13, height: 13 }} aria-hidden="true" />
                  AI включён, но обработка очереди транскрибации недоступна — сеансы не будут обработаны
                </span>
              )}
            </div>
            <label className="switch">
              <input type="checkbox" checked={aiEnabled} onChange={(e) => setAiEnabled(e.target.checked)} />
              <span className="slider" />
            </label>
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Разрешить выбор команды при регистрации</strong>
              <span>На экране регистрации появится поле «Команда» со списком команд инстанса</span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={teamChoiceEnabled}
                onChange={(e) => setTeamChoiceEnabled(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Верификация по домену почты</strong>
              <span>Регистрация только с email эталонного домена (см. плитку «Эталон mail-домена»)</span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={domainVerificationEnabled}
                onChange={(e) => setDomainVerificationEnabled(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          {/*
            Анонс записи конференций. Чекбокс не имеет состояния и не
            участвует в сохранении формы — функция появится в одной из
            следующих версий, здесь только заглушка-анонс в общем стиле
            «Модулей».
          */}
          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Возможность записи конференций</strong>
              <span>Функция появится в ближайших версиях</span>
            </div>
            <label className="switch">
              <input type="checkbox" checked={false} disabled readOnly />
              <span className="slider" />
            </label>
          </div>
        </div>
      </section>

      <div className="settings-stack">
        <section className="settings-card">
          <h2>Уровень AI</h2>
          <p className="desc">Качество распознавания и суммаризации — определяет размер моделей и требования к железу.</p>

          <div className="settings-card-body">
            <div className="ai-level-list">
              {data.ai_levels.map((levelStatus) => (
                <label
                  key={levelStatus.level}
                  className={`ai-level-option${!levelStatus.available ? ' is-disabled' : ''}`}
                >
                  <input
                    type="radio"
                    name="ai-level"
                    checked={aiLevel === levelStatus.level}
                    disabled={!levelStatus.available || !aiEnabled}
                    onChange={() => setAiLevel(levelStatus.level)}
                  />
                  <div>
                    <strong>{AI_LEVEL_LABEL[levelStatus.level]}</strong>
                    {!levelStatus.available && levelStatus.reason && (
                      <span className="ai-level-reason">
                        <AlertTriangle style={{ width: 13, height: 13 }} aria-hidden="true" />
                        {levelStatus.reason}
                      </span>
                    )}
                  </div>
                </label>
              ))}
            </div>
          </div>
        </section>

        <section className="settings-card">
          <h2>Эталон mail-домена</h2>
          <p className="desc">Домены, с любым из которых сверяется email при регистрации, если включена верификация в «Модулях».</p>

          <div className="settings-card-body">
            {emailDomains.length > 0 && (
              <div className="participants-chips">
                {emailDomains.map((domain) => (
                  <span className="participant-chip" key={domain}>
                    {domain}
                    <button
                      type="button"
                      className="participant-chip-remove"
                      aria-label={`Убрать домен: ${domain}`}
                      onClick={() => removeDomain(domain)}
                      disabled={!domainVerificationEnabled}
                    >
                      <X style={{ width: 12, height: 12 }} aria-hidden="true" />
                    </button>
                  </span>
                ))}
              </div>
            )}
            <div className="field" style={{ marginBottom: 0 }}>
              <label htmlFor="settings-email-domain">Домен корпоративной почты</label>
              <div style={{ display: 'flex', gap: 'var(--space-2)' }}>
                <input
                  id="settings-email-domain"
                  type="text"
                  placeholder="company.ru"
                  value={newDomainInput}
                  disabled={!domainVerificationEnabled}
                  onChange={(e) => setNewDomainInput(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault()
                      addDomain()
                    }
                  }}
                />
                <button
                  type="button"
                  className="btn btn-secondary"
                  disabled={!domainVerificationEnabled || !newDomainInput.trim()}
                  onClick={addDomain}
                >
                  Добавить
                </button>
              </div>
            </div>
          </div>
        </section>
      </div>

      <section className="settings-card">
        <h2>Рассылка саммари</h2>
        <p className="desc">Кому по умолчанию отправляется письмо с саммари после конференции (переопределяется в карточке конференции).</p>

        <div className="settings-card-body settings-card-body--center">
          <div className="field" style={{ marginBottom: 0 }}>
            <label id="settings-recipients-label" htmlFor="settings-recipients">
              Получатели по умолчанию
            </label>
            <Select
              id="settings-recipients"
              aria-labelledby="settings-recipients-label"
              value={recipients}
              onChange={(v) => setRecipients(v as SummaryRecipientsMode)}
              options={SUMMARY_RECIPIENTS_OPTIONS}
            />
          </div>
        </div>
      </section>

      <section className="settings-card">
        <h2>Часовой пояс отображения</h2>
        <p className="desc">IANA-таймзона для времени в письмах и .ics-приглашениях (в БД время всегда хранится в UTC).</p>

        <div className="settings-card-body settings-card-body--center">
          <div className="field" style={{ marginBottom: 0 }}>
            <label htmlFor="settings-timezone">Таймзона</label>
            <input
              id="settings-timezone"
              type="text"
              list="timezone-options"
              placeholder="Europe/Moscow"
              value={timezone}
              onChange={(e) => setTimezone(e.target.value)}
            />
            <datalist id="timezone-options">
              <option value="Europe/Moscow" />
              <option value="Europe/Kaliningrad" />
              <option value="Europe/Samara" />
              <option value="Asia/Yekaterinburg" />
              <option value="Asia/Novosibirsk" />
              <option value="Asia/Krasnoyarsk" />
              <option value="Asia/Irkutsk" />
              <option value="Asia/Vladivostok" />
              <option value="UTC" />
            </datalist>
          </div>
        </div>
      </section>

      <section className="settings-card">
        <h2>Нагрузка</h2>
        <p className="desc">
          Рычаги для инстансов на слабом канале/железе — режут исходящий трафик и нагрузку на
          устройство участника. Дефолты сохраняют прежнее поведение (без ограничений).
        </p>

        <div className="settings-card-body settings-card-body--spread">
          <div className="field" style={{ marginBottom: 0 }}>
            <label id="settings-quality-cap-label" htmlFor="settings-quality-cap">
              Потолок качества публикации видео
            </label>
            <Select
              id="settings-quality-cap"
              aria-labelledby="settings-quality-cap-label"
              value={publishQualityCap}
              onChange={(v) => setPublishQualityCap(v as PublishQualityCap)}
              options={PUBLISH_QUALITY_CAP_OPTIONS}
            />
            <p className="field-hint">
              Ограничивает битрейт исходящего видео публикующего — снижает нагрузку на его канал и
              устройство, независимо от размера плитки у смотрящих (adaptiveStream режет с их
              стороны отдельно)
            </p>
          </div>

          <div className="field" style={{ marginBottom: 0 }}>
            <label id="settings-max-tiles-label" htmlFor="settings-max-tiles">
              Максимум плиток на экране
            </label>
            <Select
              id="settings-max-tiles"
              aria-labelledby="settings-max-tiles-label"
              value={String(stageMaxTiles)}
              onChange={(v) => setStageMaxTiles(Number(v))}
              options={STAGE_MAX_TILES_OPTIONS}
            />
            <p className="field-hint">
              Сверх лимита участники уходят на следующую страницу сетки вместо подписки — меньше
              одновременных видеопотоков на канал и экран участника
            </p>
          </div>
        </div>
      </section>

      <section className="settings-card">
        <h2>Контактный адрес</h2>
        <p className="desc">
          Адрес для ответов на письма от инстанса (уходят от no-reply — этот адрес подставляется
          в заголовок «Reply-To»).
        </p>

        <div className="settings-card-body">
          <div className="toggle-row" style={{ borderTop: 'none', paddingTop: 0 }}>
            <div className="toggle-copy">
              <strong>Контактный адрес включён</strong>
              <span>Подставляется в Reply-To подтверждения регистрации, приглашений и саммари</span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={contactEmailEnabled}
                onChange={(e) => setContactEmailEnabled(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          <div className="field" style={{ marginBottom: 0, marginTop: 'var(--space-4)' }}>
            <label htmlFor="settings-contact-email">Email</label>
            <input
              id="settings-contact-email"
              type="email"
              placeholder="contact@vidconf.ru"
              value={contactEmail}
              disabled={!contactEmailEnabled}
              onChange={(e) => setContactEmail(e.target.value)}
            />
          </div>
        </div>
      </section>

      <section className="settings-card">
        <h2>Согласие на обработку персональных данных</h2>
        <p className="desc">
          Галочка на форме регистрации со ссылкой на регламент (страница{' '}
          <code>/legal/personal-data-consent</code>). Факт согласия хранится в БД вместе с
          номером редакции текста и датой.
        </p>

        <div className="settings-card-body">
          <div className="toggle-row" style={{ borderTop: 'none', paddingTop: 0 }}>
            <div className="toggle-copy">
              <strong>Требовать согласие при регистрации</strong>
              <span>Без отмеченной галочки кнопка регистрации неактивна, сервер тоже откажет</span>
            </div>
            <label className="switch">
              <input
                type="checkbox"
                checked={consentRequired}
                onChange={(e) => setConsentRequired(e.target.checked)}
              />
              <span className="slider" />
            </label>
          </div>

          <div className="field" style={{ marginBottom: 0, marginTop: 'var(--space-4)' }}>
            <label htmlFor="settings-consent-text">
              Текст регламента — редакция №{data.consent_policy_version}
            </label>
            <p className="field-hint" style={{ color: 'var(--color-danger)' }}>
              <AlertTriangle style={{ width: 13, height: 13 }} aria-hidden="true" /> Дефолтный
              текст — типовой образец, не проходил проверку юриста. Замените плейсхолдеры в
              квадратных скобках (наименование оператора, адрес, контакты, цели и срок
              обработки) под свою организацию, прежде чем включать требование согласия.
            </p>
            <textarea
              id="settings-consent-text"
              rows={12}
              value={consentPolicyText}
              onChange={(e) => setConsentPolicyText(e.target.value)}
              style={{ width: '100%', fontFamily: 'inherit', resize: 'vertical' }}
            />
            <p className="field-hint">
              Сохранение изменённого текста автоматически увеличивает номер редакции — это
              значение фиксируется у каждого пользователя вместе с датой согласия.
            </p>
          </div>
        </div>
      </section>

      <section className="settings-card">
        <h2>Тестовое письмо</h2>
        <p className="desc">Отправить проверочное письмо синхронно, чтобы сразу увидеть результат почтовой конфигурации.</p>

        <div className="settings-card-body">
          <div className="field">
            <label htmlFor="settings-test-email-to">Получатель</label>
            <input
              id="settings-test-email-to"
              type="email"
              placeholder={user?.email ?? 'you@example.com'}
              value={testEmailTo}
              onChange={(e) => setTestEmailTo(e.target.value)}
            />
          </div>

          <button
            type="button"
            className="btn btn-secondary"
            disabled={testEmailMutation.isPending}
            onClick={() => testEmailMutation.mutate()}
          >
            {testEmailMutation.isPending ? 'Отправляем…' : 'Отправить тестовое письмо'}
          </button>

          {testEmailResult && (
            <p
              className="field-hint"
              style={{ color: testEmailResult.success ? 'var(--color-success)' : 'var(--color-danger)' }}
            >
              {testEmailResult.message}
              {testEmailResult.smtp_host && ` (${testEmailResult.smtp_host}:${testEmailResult.smtp_port})`}
            </p>
          )}
        </div>
      </section>

      <div className="settings-actions">
        <button type="button" className="btn btn-primary" disabled={mutation.isPending} onClick={handleSave}>
          {mutation.isPending ? 'Сохраняем…' : 'Сохранить настройки'}
        </button>
      </div>
    </div>
  )
}
