import { useEffect, useRef, useState, type FormEvent } from 'react'
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import { AlertCircle, ArrowRight, CheckCircle2, Eye, EyeOff, Hash, Link2, Lock, Mail, User, Video } from 'lucide-react'
import {
  guestJoinConference,
  joinConference,
  resolveConference,
  type ConferenceJoinData,
} from '@/api/conferences'
import { ApiError, errorDetail } from '@/api/client'
import { useAuth } from '@/auth/useAuth'
import { AppFooter } from '@/components/layout/AppFooter'
import { LogoMark } from '@/components/ui/LogoMark'
import { ThemeToggle } from '@/components/ui/ThemeToggle'
import { parseJoinQuery } from '@/lib/parseJoinQuery'
import '@/styles/join.css'

type Step = 'input' | 'guest-info' | 'password' | 'connecting' | 'ended'

interface ResolvedTarget {
  id: string
  title: string | null
  isClosed: boolean
  requiresPassword: boolean
  /** Нормализованный запрос пользователя (slug/номер) — используется как параметр `/room/:slug`. */
  query: string
}

/**
 * Подключение к конференции (см. design/mockups/join.html) — три состояния
 * одного флоу: (а) ввод ссылки/номера, (б) «представиться» для гостя,
 * (в) пароль закрытой конференции. Экран публичный — доступен без сессии
 * (гость входит без аккаунта), поэтому не завёрнут в `RequireAuth`.
 *
 * Маршруты: `/join` (ручной ввод, опционально `?q=` — например, после
 * редиректа из RoomPage при потере join-состояния) и `/j/:slug` (прямая
 * ссылка-приглашение — резолвится автоматически при заходе).
 *
 * Авторизованный пользователь пропускает «представиться»: после резолва либо
 * сразу входит (если конференция открыта), либо сразу видит экран пароля
 * (если закрыта). Гость всегда проходит «представиться»; если конференция
 * закрыта, экран пароля показывается вторым шагом, после чего оба поля
 * (имя/email + пароль) уходят одним запросом `guest-join`.
 */
export function JoinPage() {
  const navigate = useNavigate()
  const { slug: slugParam } = useParams<{ slug?: string }>()
  const [searchParams] = useSearchParams()
  const { status } = useAuth()
  const isAuthenticated = status === 'authenticated'

  const initialQuery = slugParam ?? searchParams.get('q') ?? ''
  const [query, setQuery] = useState(initialQuery)
  const [resolving, setResolving] = useState(false)
  const [resolveError, setResolveError] = useState<string | null>(null)

  const [step, setStep] = useState<Step>('input')
  const [target, setTarget] = useState<ResolvedTarget | null>(null)

  const [guestName, setGuestName] = useState('')
  const [guestEmail, setGuestEmail] = useState('')

  const [password, setPassword] = useState('')
  const [showPassword, setShowPassword] = useState(false)
  const [invalidPassword, setInvalidPassword] = useState(false)
  const [joining, setJoining] = useState(false)

  const autoResolvedRef = useRef(false)

  // Прямая ссылка (/j/:slug) или ?q= из редиректа — резолвим сразу, не
  // дожидаясь клика по «Продолжить», но только после того как известен
  // статус сессии (нужен для выбора «гость / авторизованный» флоу).
  useEffect(() => {
    if (status === 'loading' || autoResolvedRef.current || !initialQuery) return
    autoResolvedRef.current = true
    void handleResolve(initialQuery)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [status])

  async function handleResolve(rawQuery: string) {
    const normalized = parseJoinQuery(rawQuery)
    if (!normalized) return
    setResolveError(null)
    setResolving(true)
    try {
      const info = await resolveConference(normalized)
      // Завершённая конференция (ADR-001) — backend отдаёт минимальный ответ
      // без is_closed/requires_password: сразу показываем «завершена», не
      // дожидаясь шага «представиться»/пароль и попытки join (которая всё
      // равно вернёт 410).
      if (info.status === 'ended') {
        setTarget({ id: info.id, title: info.title, isClosed: false, requiresPassword: false, query: normalized })
        setStep('ended')
        return
      }
      const nextTarget: ResolvedTarget = {
        id: info.id,
        title: info.title,
        isClosed: info.is_closed ?? false,
        requiresPassword: info.requires_password ?? false,
        query: normalized,
      }
      setTarget(nextTarget)
      if (nextTarget.requiresPassword) {
        setStep('password')
      } else if (isAuthenticated) {
        setStep('connecting')
        await performJoin(nextTarget, {})
      } else {
        setStep('guest-info')
      }
    } catch (err) {
      if (err instanceof ApiError && err.status === 404) {
        setResolveError('Конференция не найдена — проверьте ссылку или номер')
      } else {
        setResolveError('Не удалось найти конференцию. Попробуйте ещё раз')
      }
      setStep('input')
    } finally {
      setResolving(false)
    }
  }

  async function performJoin(
    resolved: ResolvedTarget,
    opts: { password?: string; guestName?: string; guestEmail?: string },
  ) {
    setJoining(true)
    setInvalidPassword(false)
    try {
      let data: ConferenceJoinData
      if (isAuthenticated) {
        data = await joinConference(resolved.id, opts.password ? { password: opts.password } : undefined)
      } else {
        data = await guestJoinConference(resolved.id, {
          display_name: opts.guestName ?? guestName.trim(),
          email: (opts.guestEmail ?? guestEmail).trim() || undefined,
          password: opts.password,
        })
      }
      navigate(`/room/${encodeURIComponent(resolved.query)}`, {
        replace: true,
        state: {
          livekitUrl: data.livekit_url,
          token: data.token,
          roomName: data.room_name,
          conferenceId: data.conference_id,
          chatEnabled: data.chat_enabled,
        },
      })
    } catch (err) {
      if (err instanceof ApiError && err.status === 403 && errorDetail(err) === 'password_required') {
        setStep('password')
      } else if (err instanceof ApiError && err.status === 403 && errorDetail(err) === 'invalid_password') {
        setInvalidPassword(true)
        setStep('password')
      } else if (err instanceof ApiError && err.status === 410) {
        setStep('ended')
      } else {
        setResolveError('Не удалось подключиться к конференции. Попробуйте ещё раз позже')
        setStep('input')
      }
    } finally {
      setJoining(false)
    }
  }

  function handleInputSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    void handleResolve(query)
  }

  function handleGuestInfoSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    if (!target || !guestName.trim()) return
    if (target.requiresPassword) {
      setStep('password')
    } else {
      void performJoin(target, {})
    }
  }

  function handlePasswordSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    if (!target || !password) return
    void performJoin(target, { password })
  }

  function resetToInput() {
    setResolveError(null)
    setInvalidPassword(false)
    setStep('input')
  }

  if (step === 'connecting') {
    return (
      <div className="app-loader" role="status" aria-live="polite">
        Подключаемся к конференции…
      </div>
    )
  }

  return (
    <div className="join-shell">
      <header className="join-topbar">
        <Link to="/lobby" className="brand-mark">
          <LogoMark /> VidConf
        </Link>
        <ThemeToggle />
      </header>

      <main className="join-main">
        {step === 'input' && (
          <section className="screen-block">
            <div className="flow-card">
              <div className="flow-icon" aria-hidden="true">
                <Link2 className="icon" aria-hidden="true" />
              </div>
              <h1>Подключиться к конференции</h1>
              <p className="flow-sub">Вставьте ссылку-приглашение или введите номер конференции</p>

              <form onSubmit={handleInputSubmit}>
                <div className={`field${resolveError ? ' has-error' : ''}`}>
                  <label htmlFor="join-input">Ссылка или номер</label>
                  <div className="input-wrap">
                    <Hash className="icon" aria-hidden="true" />
                    <input
                      id="join-input"
                      type="text"
                      placeholder="vidconf.ru/j/... или 8842 104"
                      value={query}
                      onChange={(e) => setQuery(e.target.value)}
                      autoFocus
                    />
                  </div>
                  {resolveError ? (
                    <p className="error-msg">
                      <AlertCircle style={{ width: 16, height: 16 }} aria-hidden="true" /> {resolveError}
                    </p>
                  ) : (
                    <p className="field-hint">Найдите номер или ссылку в приглашении организатора</p>
                  )}
                </div>
                <button type="submit" className="btn btn-primary" disabled={!query.trim() || resolving}>
                  {resolving ? 'Ищем конференцию…' : 'Продолжить'}
                  {!resolving && <ArrowRight style={{ width: 18, height: 18 }} aria-hidden="true" />}
                </button>
              </form>
              <Link to="/lobby" className="link-back">
                Назад в лобби
              </Link>
            </div>
          </section>
        )}

        {step === 'guest-info' && target && (
          <section className="screen-block">
            <div className="flow-card">
              <div className="target-conf">
                <span className="icon-wrap" aria-hidden="true">
                  {target.isClosed ? <Lock className="icon" aria-hidden="true" /> : <Video className="icon" aria-hidden="true" />}
                </span>
                <div>
                  <strong>{target.title ?? 'Конференция без названия'}</strong>
                  <span>№ {target.query}</span>
                </div>
              </div>

              <div className="flow-icon" aria-hidden="true">
                <User className="icon" aria-hidden="true" />
              </div>
              <h1>Как вас зовут?</h1>
              <p className="flow-sub">У вас нет аккаунта VidConf — представьтесь, чтобы войти как гость</p>

              <form onSubmit={handleGuestInfoSubmit}>
                <div className="field">
                  <label htmlFor="guest-name">
                    Имя<span className="field-optional">· обязательно</span>
                  </label>
                  <div className="input-wrap">
                    <User className="icon" aria-hidden="true" />
                    <input
                      id="guest-name"
                      type="text"
                      placeholder="Как к вам обращаться"
                      value={guestName}
                      onChange={(e) => setGuestName(e.target.value)}
                      autoFocus
                    />
                  </div>
                </div>
                <div className="field">
                  <label htmlFor="guest-email">
                    Email<span className="field-optional">· необязательно</span>
                  </label>
                  <div className="input-wrap">
                    <Mail className="icon" aria-hidden="true" />
                    <input
                      id="guest-email"
                      type="email"
                      placeholder="you@mail.ru"
                      value={guestEmail}
                      onChange={(e) => setGuestEmail(e.target.value)}
                    />
                  </div>
                  <p className="field-hint">Укажите, если хотите получить саммари конференции на почту</p>
                </div>
                <button type="submit" className="btn btn-primary" disabled={!guestName.trim() || joining}>
                  {joining ? 'Входим…' : 'Войти в конференцию'}
                  {!joining && <ArrowRight style={{ width: 18, height: 18 }} aria-hidden="true" />}
                </button>
              </form>
              <button type="button" className="link-back" onClick={resetToInput}>
                Назад
              </button>
            </div>
          </section>
        )}

        {step === 'password' && target && (
          <section className="screen-block">
            <div className="flow-card">
              <div className="target-conf">
                <span className="icon-wrap" aria-hidden="true">
                  <Lock className="icon" aria-hidden="true" />
                </span>
                <div>
                  <strong>{target.title ?? 'Конференция без названия'}</strong>
                  <span>№ {target.query} · закрытая</span>
                </div>
              </div>

              <div className="flow-icon" aria-hidden="true">
                <Lock className="icon" aria-hidden="true" />
              </div>
              <h1>Введите пароль</h1>
              <p className="flow-sub">Эта конференция закрыта — доступ только по паролю от организатора</p>

              <form onSubmit={handlePasswordSubmit}>
                <div className={`field${invalidPassword ? ' has-error' : ''}`}>
                  <label htmlFor="join-pass">Пароль конференции</label>
                  <div className="input-wrap">
                    <Lock className="icon" aria-hidden="true" />
                    <input
                      id="join-pass"
                      type={showPassword ? 'text' : 'password'}
                      placeholder="••••••••"
                      value={password}
                      onChange={(e) => {
                        setPassword(e.target.value)
                        setInvalidPassword(false)
                      }}
                      autoFocus
                    />
                    <button
                      type="button"
                      className="toggle-eye"
                      aria-label={showPassword ? 'Скрыть пароль' : 'Показать пароль'}
                      onClick={() => setShowPassword((v) => !v)}
                    >
                      {showPassword ? <EyeOff className="icon" aria-hidden="true" /> : <Eye className="icon" aria-hidden="true" />}
                    </button>
                  </div>
                  {invalidPassword && (
                    <p className="error-msg">
                      <AlertCircle style={{ width: 16, height: 16 }} aria-hidden="true" /> Неверный пароль, попробуйте ещё раз
                    </p>
                  )}
                </div>
                <button type="submit" className="btn btn-primary" disabled={!password || joining}>
                  {joining ? 'Входим…' : 'Войти'}
                  {!joining && <ArrowRight style={{ width: 18, height: 18 }} aria-hidden="true" />}
                </button>
              </form>
              <button type="button" className="link-back" onClick={resetToInput}>
                Назад
              </button>
            </div>
          </section>
        )}

        {step === 'ended' && (
          <section className="screen-block">
            <div className="flow-card">
              {target && (
                <div className="target-conf">
                  <span className="icon-wrap" aria-hidden="true">
                    <CheckCircle2 className="icon" aria-hidden="true" />
                  </span>
                  <div>
                    <strong>{target.title ?? 'Конференция без названия'}</strong>
                    <span>№ {target.query} · завершена</span>
                  </div>
                </div>
              )}

              <div className="flow-icon" aria-hidden="true">
                <CheckCircle2 className="icon" aria-hidden="true" />
              </div>
              <h1>Конференция завершена</h1>
              <p className="flow-sub">Эта конференция уже завершилась и недоступна для повторного входа</p>

              <button type="button" className="btn btn-primary" onClick={resetToInput}>
                Ввести другую ссылку или номер
              </button>
              <Link to="/lobby" className="link-back">
                Назад в лобби
              </Link>
            </div>
          </section>
        )}
      </main>
      <AppFooter />
    </div>
  )
}
