import { useEffect, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Check, Clock, Lock, Mail, Pencil, Play, Repeat, Search, Send, Trash2, X } from 'lucide-react'
import {
  deleteAdminConference,
  listAdminConferences,
  sendConferenceInvitations,
  updateAdminConference,
  type AdminConferenceOut,
  type AdminConferenceUpdatePayload,
} from '@/api/admin'
import type { ConferenceStatus, SummaryRecipientsMode } from '@/api/conferences'
import { ApiError } from '@/api/client'
import { useToast } from '@/components/ui/ToastProvider'
import { formatLocalDateTime, localDateTimeToIso, toLocalDateTimeParts } from '@/lib/localTime'
import { formatRecurrenceSummary } from '@/lib/recurrenceFormat'

const PAGE_SIZE = 10

const STATUS_FILTERS: { value: ConferenceStatus | 'all'; label: string }[] = [
  { value: 'scheduled', label: 'Запланированные' },
  { value: 'active', label: 'Активные' },
  { value: 'ended', label: 'Завершённые' },
  { value: 'all', label: 'Все' },
]

function StatusBadge({ conference }: { conference: AdminConferenceOut }) {
  if (conference.status === 'active') {
    return (
      <span className="badge badge-free">
        <Play style={{ width: 12, height: 12 }} aria-hidden="true" />
        Идёт сейчас
      </span>
    )
  }
  if (conference.status === 'ended') {
    return (
      <span className="badge badge-locked">
        <Check style={{ width: 12, height: 12 }} aria-hidden="true" />
        Завершена
      </span>
    )
  }
  return (
    <span className="badge badge-booked">
      <Clock style={{ width: 12, height: 12 }} aria-hidden="true" />
      Запланирована
    </span>
  )
}

/** Форма быстрого редактирования конференции из админки (title/время/пароль/рассылка). */
function EditConferenceModal({
  conference,
  onClose,
  onDelete,
  deleting,
}: {
  conference: AdminConferenceOut
  onClose: () => void
  /** Удаление конференции — та же мутация, что и у корзины в строке таблицы (см. AdminConferencesTab). */
  onDelete: () => void
  deleting: boolean
}) {
  const queryClient = useQueryClient()
  const toast = useToast()
  const initialSlot = conference.scheduled_at ? toLocalDateTimeParts(conference.scheduled_at) : { date: '', time: '' }

  const [title, setTitle] = useState(conference.title ?? '')
  const [dateStr, setDateStr] = useState(initialSlot.date)
  const [timeStr, setTimeStr] = useState(initialSlot.time)
  const [durationMinutes, setDurationMinutes] = useState(conference.duration_minutes ?? 30)
  const [isClosed, setIsClosed] = useState(conference.is_closed)
  const [password, setPassword] = useState('')
  const [summaryRecipients, setSummaryRecipients] = useState<'' | SummaryRecipientsMode>(
    conference.summary_recipients ?? '',
  )
  const [confirmDelete, setConfirmDelete] = useState(false)

  const mutation = useMutation({
    mutationFn: (payload: AdminConferenceUpdatePayload) => updateAdminConference(conference.id, payload),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'conferences'] })
      toast.show('Изменения сохранены', 'success')
      onClose()
    },
    onError: () => toast.show('Не удалось сохранить изменения', 'error'),
  })

  function handleSubmit() {
    const payload: AdminConferenceUpdatePayload = {
      title: title.trim(),
      duration_minutes: durationMinutes,
      is_closed: isClosed,
      summary_recipients: summaryRecipients === '' ? null : summaryRecipients,
    }
    if (dateStr && timeStr) payload.scheduled_at = localDateTimeToIso(dateStr, timeStr)
    if (isClosed && password) payload.password = password
    mutation.mutate(payload)
  }

  return (
    <div className="modal-overlay" role="dialog" aria-modal="true" onClick={onClose}>
      <div className="modal-panel is-wide" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h2>Редактирование конференции</h2>
          <button type="button" className="modal-close" aria-label="Закрыть" onClick={onClose}>
            <X style={{ width: 16, height: 16 }} aria-hidden="true" />
          </button>
        </div>

        {conference.is_pinned && conference.recurrence && (
          <p className="field-hint" style={{ marginBottom: 'var(--space-4)' }}>
            <Repeat style={{ width: 14, height: 14, verticalAlign: '-2px' }} aria-hidden="true" /> Закреплена:{' '}
            {formatRecurrenceSummary(conference.recurrence)} — повторение редактируется владельцем в календаре.
          </p>
        )}

        <form
          onSubmit={(e) => {
            e.preventDefault()
            handleSubmit()
          }}
        >
          <div className="field">
            <label htmlFor="admin-conf-title">Название</label>
            <input id="admin-conf-title" type="text" value={title} onChange={(e) => setTitle(e.target.value)} maxLength={255} />
          </div>

          {!conference.is_pinned && (
            <div className="field-row">
              <div className="field">
                <label htmlFor="admin-conf-date">Дата</label>
                <input id="admin-conf-date" type="date" value={dateStr} onChange={(e) => setDateStr(e.target.value)} />
              </div>
              <div className="field">
                <label htmlFor="admin-conf-time">Время</label>
                <input id="admin-conf-time" type="time" value={timeStr} onChange={(e) => setTimeStr(e.target.value)} />
              </div>
            </div>
          )}

          <div className="field">
            <label htmlFor="admin-conf-duration">Длительность, мин</label>
            <input
              id="admin-conf-duration"
              type="number"
              min={5}
              step={5}
              value={durationMinutes}
              onChange={(e) => setDurationMinutes(Number(e.target.value) || 0)}
            />
          </div>

          <div className="toggle-row">
            <div className="toggle-copy">
              <strong>Закрытая по паролю</strong>
              <span>Вход только по паролю, включая гостей</span>
            </div>
            <label className="switch">
              <input type="checkbox" checked={isClosed} onChange={(e) => setIsClosed(e.target.checked)} />
              <span className="slider" />
            </label>
          </div>
          {isClosed && (
            <div className="field">
              <label htmlFor="admin-conf-password">
                <Lock style={{ width: 14, height: 14 }} aria-hidden="true" />
                Новый пароль (оставьте пустым, чтобы не менять)
              </label>
              <input
                id="admin-conf-password"
                type="password"
                placeholder="Минимум 4 символа"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
              />
            </div>
          )}

          <div className="field">
            <label htmlFor="admin-conf-recipients">Рассылка саммари</label>
            <select
              id="admin-conf-recipients"
              value={summaryRecipients}
              onChange={(e) => setSummaryRecipients(e.target.value as '' | SummaryRecipientsMode)}
            >
              <option value="">По умолчанию (настройки инстанса)</option>
              <option value="all">Всем участникам</option>
              <option value="owner">Только организатору</option>
            </select>
          </div>

          <div className="modal-actions modal-actions--split">
            {confirmDelete ? (
              <div className="row-actions">
                <span className="field-hint">Удалить без возможности восстановления?</span>
                <button type="button" className="btn btn-secondary" onClick={() => setConfirmDelete(false)}>
                  Нет
                </button>
                <button type="button" className="btn btn-danger" disabled={deleting} onClick={onDelete}>
                  {deleting ? 'Удаляем…' : 'Да, удалить'}
                </button>
              </div>
            ) : (
              <button type="button" className="btn btn-danger" onClick={() => setConfirmDelete(true)}>
                <Trash2 style={{ width: 16, height: 16 }} aria-hidden="true" />
                Удалить
              </button>
            )}
            <div className="modal-actions-group">
              <button type="button" className="btn btn-secondary" onClick={onClose}>
                Отмена
              </button>
              <button type="submit" className="btn btn-primary" disabled={mutation.isPending}>
                {mutation.isPending ? 'Сохраняем…' : 'Сохранить'}
              </button>
            </div>
          </div>
        </form>
      </div>
    </div>
  )
}

/** Модалка ручной рассылки .ics-приглашений по конкретной конференции. */
function InviteModal({ conference, onClose }: { conference: AdminConferenceOut; onClose: () => void }) {
  const [emailsText, setEmailsText] = useState('')
  const toast = useToast()

  const mutation = useMutation({
    mutationFn: () => {
      const emails = emailsText
        .split(/[\n,;]+/)
        .map((e) => e.trim())
        .filter(Boolean)
      return sendConferenceInvitations(conference.id, emails.length > 0 ? emails : undefined)
    },
    onSuccess: () => {
      toast.show('Рассылка приглашений поставлена в очередь', 'success')
      onClose()
    },
    onError: () => toast.show('Не удалось поставить рассылку', 'error'),
  })

  return (
    <div className="modal-overlay" role="dialog" aria-modal="true" onClick={onClose}>
      <div className="modal-panel is-wide" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h2>Рассылка приглашений</h2>
          <button type="button" className="modal-close" aria-label="Закрыть" onClick={onClose}>
            <X style={{ width: 16, height: 16 }} aria-hidden="true" />
          </button>
        </div>
        <p className="field-hint" style={{ marginBottom: 'var(--space-4)' }}>
          «{conference.title ?? conference.number}» — оставьте поле пустым, чтобы разослать по умолчанию (владельцу и
          участникам прошлых сеансов).
        </p>
        <div className="field">
          <label htmlFor="admin-invite-emails">Адреса (через запятую или с новой строки)</label>
          <textarea
            id="admin-invite-emails"
            rows={5}
            placeholder="i.sokolov@company.ru&#10;o.panina@company.ru"
            value={emailsText}
            onChange={(e) => setEmailsText(e.target.value)}
          />
        </div>
        <div className="modal-actions">
          <button type="button" className="btn btn-secondary" onClick={onClose}>
            Отмена
          </button>
          <button type="button" className="btn btn-primary" disabled={mutation.isPending} onClick={() => mutation.mutate()}>
            <Send style={{ width: 16, height: 16 }} aria-hidden="true" />
            {mutation.isPending ? 'Отправляем…' : 'Отправить'}
          </button>
        </div>
      </div>
    </div>
  )
}

/**
 * Вкладка «Конференции» админки — список запланированных/закреплённых
 * конференций с поиском, фильтром по статусу, пагинацией, редактированием,
 * удалением и ручной рассылкой приглашений (design/mockups/admin.html,
 * блок «table-card», адаптированный под сущность «конференция»).
 */
export function AdminConferencesTab() {
  const [statusFilter, setStatusFilter] = useState<ConferenceStatus | 'all'>('scheduled')
  const [searchInput, setSearchInput] = useState('')
  const [search, setSearch] = useState('')
  const [offset, setOffset] = useState(0)
  const [editingConference, setEditingConference] = useState<AdminConferenceOut | null>(null)
  const [invitingConference, setInvitingConference] = useState<AdminConferenceOut | null>(null)
  const [confirmingDeleteId, setConfirmingDeleteId] = useState<string | null>(null)
  const queryClient = useQueryClient()
  const toast = useToast()

  // Дебаунс поискового ввода — не дёргаем API на каждое нажатие клавиши.
  useEffect(() => {
    const timer = setTimeout(() => {
      setSearch(searchInput.trim())
      setOffset(0)
    }, 300)
    return () => clearTimeout(timer)
  }, [searchInput])

  const { data, isLoading } = useQuery({
    queryKey: ['admin', 'conferences', statusFilter, search, offset],
    queryFn: () =>
      listAdminConferences({
        status: statusFilter === 'all' ? undefined : statusFilter,
        q: search || undefined,
        limit: PAGE_SIZE,
        offset,
      }),
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => deleteAdminConference(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['admin', 'conferences'] })
      toast.show('Конференция удалена', 'success')
      setConfirmingDeleteId(null)
      // Удаление могло прийти и из модалки редактирования (кнопка «Удалить»
      // там дёргает эту же мутацию) — закрываем её тоже, если открыта.
      setEditingConference(null)
    },
    onError: (err: unknown) => {
      if (err instanceof ApiError && err.status === 409) {
        toast.show('Нельзя удалить — конференция сейчас идёт', 'error')
      } else {
        toast.show('Не удалось удалить конференцию', 'error')
      }
      setConfirmingDeleteId(null)
    },
  })

  const items = data?.items ?? []
  const total = data?.total ?? 0

  return (
    <>
      <div className="section-tabs-inline">
        {STATUS_FILTERS.map((f) => (
          <button
            key={f.value}
            type="button"
            className={`chip${statusFilter === f.value ? ' is-active' : ''}`}
            onClick={() => {
              setStatusFilter(f.value)
              setOffset(0)
            }}
          >
            {f.label}
          </button>
        ))}
      </div>

      <div className="toolbar-row">
        <div className="search-wrap">
          <Search className="icon" style={{ width: 16, height: 16 }} aria-hidden="true" />
          <input
            type="text"
            placeholder="Поиск по названию или номеру…"
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
          />
        </div>
        <span className="toolbar-count">
          {isLoading ? 'Загрузка…' : `Показано ${items.length ? offset + 1 : 0}–${offset + items.length} из ${total}`}
        </span>
      </div>

      <div className="table-card conferences-table">
        <table>
          <thead>
            <tr>
              <th>Конференция</th>
              <th>Владелец</th>
              <th>Статус</th>
              <th>Тип</th>
              <th>Начало</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {items.length === 0 && !isLoading && (
              <tr>
                <td colSpan={6} style={{ textAlign: 'center', color: 'var(--color-ink-500)' }}>
                  Конференции не найдены
                </td>
              </tr>
            )}
            {items.map((conf) => (
              <tr key={conf.id}>
                <td>
                  {/* На мобильном это единственный вход в редактирование строки (см. .conferences-table
                      в admin.css — остальные колонки там скрыты), на десктопе — то же самое, что кнопка
                      «Редактировать» правее, просто более крупная область клика. */}
                  <button type="button" className="conf-cell-name" onClick={() => setEditingConference(conf)}>
                    {conf.is_closed && <Lock style={{ width: 14, height: 14, marginRight: 6, verticalAlign: '-2px' }} aria-hidden="true" />}
                    {conf.title ?? 'Без названия'}
                    <span style={{ display: 'block', font: 'var(--text-caption)', color: 'var(--color-ink-500)' }}>
                      № {conf.number}
                    </span>
                  </button>
                </td>
                <td>
                  {conf.owner_name ?? '—'}
                  {conf.owner_email && (
                    <span style={{ display: 'block', font: 'var(--text-caption)', color: 'var(--color-ink-500)' }}>
                      {conf.owner_email}
                    </span>
                  )}
                </td>
                <td>
                  <StatusBadge conference={conf} />
                </td>
                <td>
                  {conf.is_pinned ? (
                    <span className="badge badge-locked">
                      <Repeat style={{ width: 12, height: 12 }} aria-hidden="true" />
                      Закреплена
                    </span>
                  ) : (
                    'Разовая'
                  )}
                </td>
                <td>{conf.next_occurrence ? formatLocalDateTime(conf.next_occurrence) : conf.scheduled_at ? formatLocalDateTime(conf.scheduled_at) : '—'}</td>
                <td>
                  {confirmingDeleteId === conf.id ? (
                    <div className="row-actions">
                      <button
                        type="button"
                        className="icon-btn danger"
                        aria-label="Подтвердить удаление"
                        disabled={deleteMutation.isPending}
                        onClick={() => deleteMutation.mutate(conf.id)}
                      >
                        <Check style={{ width: 16, height: 16 }} aria-hidden="true" />
                      </button>
                      <button type="button" className="icon-btn" aria-label="Отмена" onClick={() => setConfirmingDeleteId(null)}>
                        <X style={{ width: 16, height: 16 }} aria-hidden="true" />
                      </button>
                    </div>
                  ) : (
                    <div className="row-actions">
                      <button type="button" className="icon-btn" aria-label="Рассылка приглашений" onClick={() => setInvitingConference(conf)}>
                        <Mail style={{ width: 16, height: 16 }} aria-hidden="true" />
                      </button>
                      <button type="button" className="icon-btn" aria-label="Редактировать" onClick={() => setEditingConference(conf)}>
                        <Pencil style={{ width: 16, height: 16 }} aria-hidden="true" />
                      </button>
                      <button type="button" className="icon-btn danger" aria-label="Удалить" onClick={() => setConfirmingDeleteId(conf.id)}>
                        <Trash2 style={{ width: 16, height: 16 }} aria-hidden="true" />
                      </button>
                    </div>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {total > PAGE_SIZE && (
        <div className="pagination-row">
          <button type="button" className="btn btn-secondary" disabled={offset === 0} onClick={() => setOffset(Math.max(0, offset - PAGE_SIZE))}>
            Назад
          </button>
          <button
            type="button"
            className="btn btn-secondary"
            disabled={offset + PAGE_SIZE >= total}
            onClick={() => setOffset(offset + PAGE_SIZE)}
          >
            Далее
          </button>
        </div>
      )}

      {editingConference && (
        <EditConferenceModal
          conference={editingConference}
          onClose={() => setEditingConference(null)}
          onDelete={() => deleteMutation.mutate(editingConference.id)}
          deleting={deleteMutation.isPending}
        />
      )}
      {invitingConference && <InviteModal conference={invitingConference} onClose={() => setInvitingConference(null)} />}
    </>
  )
}
