'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { motion } from 'framer-motion';
import { Bell, CheckCircle2, Link as LinkIcon, Loader2, MessageCircle, ShieldCheck, Trash2 } from 'lucide-react';
import ApiErrorAlert from '@/app/components/ApiErrorAlert';
import {
  formatApiErrorWithRequestId,
  formatRetryAfterHuman,
  getResponseErrorDetails,
} from '@/lib/api-client';
import { formatTelegramIdentity } from '@/lib/telegram-identity';

type TelegramState = {
  telegramId: string | null;
  telegramChatId: string | null;
  telegramUsername: string | null;
  telegramLinkedAt: string | null;
};

type ClickNotificationsStatus = {
  hasBotToken: boolean;
  featureAvailableByPlan: boolean;
  canSendToUserNow: boolean;
};

type LinkStep = 'initial' | 'code' | 'loading' | 'success';

type ProfileSettingsModalProps = {
  isOpen: boolean;
  onClose: () => void;
  initialTelegramId?: string | null;
  initialTelegramUsername?: string | null;
  onLinked?: (data: { telegramId: string; telegramUsername?: string | null }) => void;
};

const SUCCESS_CLOSE_DELAY_MS = 1500;
const EMPTY_CLICK_NOTIFICATIONS: ClickNotificationsStatus = {
  hasBotToken: false,
  featureAvailableByPlan: false,
  canSendToUserNow: false,
};

function createEmptyTelegramState(
  initialTelegramId: string | null,
  initialTelegramUsername: string | null,
): TelegramState {
  return {
    telegramId: initialTelegramId,
    telegramChatId: null,
    telegramUsername: initialTelegramUsername,
    telegramLinkedAt: null,
  };
}

export default function ProfileSettingsModal({
  isOpen,
  onClose,
  initialTelegramId = null,
  initialTelegramUsername = null,
  onLinked,
}: ProfileSettingsModalProps) {
  const [telegram, setTelegram] = useState<TelegramState>(() =>
    createEmptyTelegramState(initialTelegramId, initialTelegramUsername),
  );
  const [step, setStep] = useState<LinkStep>('initial');
  const [botUrl, setBotUrl] = useState('');
  const [botStartUrl, setBotStartUrl] = useState('');
  const [challengeId, setChallengeId] = useState('');
  const [code, setCode] = useState('');
  const [error, setError] = useState('');
  const [tokenError, setTokenError] = useState('');
  const [botTokenInput, setBotTokenInput] = useState('');
  const [clickNotifications, setClickNotifications] = useState<ClickNotificationsStatus>(EMPTY_CLICK_NOTIFICATIONS);
  const [isRequestingCode, setIsRequestingCode] = useState(false);
  const [isSavingBotToken, setIsSavingBotToken] = useState(false);
  const [isClearingBotToken, setIsClearingBotToken] = useState(false);
  const closeTimeoutRef = useRef<number | null>(null);

  const canClose = step !== 'loading' && step !== 'success';

  const linkedLabel = useMemo(
    () => formatTelegramIdentity(telegram.telegramUsername, telegram.telegramId, 'Не привязан'),
    [telegram.telegramId, telegram.telegramUsername],
  );

  const clearCloseTimer = useCallback(() => {
    if (closeTimeoutRef.current) {
      window.clearTimeout(closeTimeoutRef.current);
      closeTimeoutRef.current = null;
    }
  }, []);

  const resetChallengeFlow = useCallback(() => {
    setStep('initial');
    setCode('');
    setChallengeId('');
    setBotStartUrl('');
  }, []);

  const closeModal = useCallback(() => {
    if (!canClose) return;
    clearCloseTimer();
    resetChallengeFlow();
    setError('');
    setTokenError('');
    setBotTokenInput('');
    onClose();
  }, [canClose, clearCloseTimer, onClose, resetChallengeFlow]);

  const buildApiError = useCallback(async (response: Response, fallback: string) => {
    const details = await getResponseErrorDetails(response, fallback);
    const retryAfter = formatRetryAfterHuman(details.retryAfterSec);
    const baseMessage = formatApiErrorWithRequestId(details);
    return retryAfter ? `${baseMessage}. Повторите через ${retryAfter}` : baseMessage;
  }, []);

  useEffect(() => {
    return () => clearCloseTimer();
  }, [clearCloseTimer]);

  useEffect(() => {
    if (!isOpen) {
      clearCloseTimer();
      resetChallengeFlow();
      setError('');
      setTokenError('');
      setBotTokenInput('');
      return;
    }

    let isCancelled = false;

    const loadSettings = async () => {
      try {
        const response = await fetch('/api/profile/telegram', { cache: 'no-store' });
        if (!response.ok) {
          setError(await buildApiError(response, 'Не удалось загрузить настройки Telegram.'));
          return;
        }

        const data = await response.json() as {
          telegram?: TelegramState | null;
          botUrl?: string;
          clickNotifications?: Partial<ClickNotificationsStatus>;
        };

        if (isCancelled) return;

        const nextTelegram = data.telegram ?? createEmptyTelegramState(initialTelegramId, initialTelegramUsername);
        setTelegram({
          telegramId: nextTelegram.telegramId ?? null,
          telegramChatId: nextTelegram.telegramChatId ?? null,
          telegramUsername: nextTelegram.telegramUsername ?? null,
          telegramLinkedAt: nextTelegram.telegramLinkedAt ?? null,
        });
        setBotUrl(data.botUrl || '');
        setClickNotifications({
          hasBotToken: Boolean(data.clickNotifications?.hasBotToken),
          featureAvailableByPlan: Boolean(data.clickNotifications?.featureAvailableByPlan),
          canSendToUserNow: Boolean(data.clickNotifications?.canSendToUserNow),
        });
      } catch {
        if (isCancelled) return;
        setError('Ошибка при загрузке настроек Telegram.');
        setClickNotifications(EMPTY_CLICK_NOTIFICATIONS);
      }
    };

    void loadSettings();

    return () => {
      isCancelled = true;
    };
  }, [
    buildApiError,
    clearCloseTimer,
    initialTelegramId,
    initialTelegramUsername,
    isOpen,
    resetChallengeFlow,
  ]);

  useEffect(() => {
    if (!isOpen) return;

    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';

    return () => {
      document.body.style.overflow = previousOverflow;
    };
  }, [isOpen]);

  useEffect(() => {
    if (!isOpen || !canClose) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        closeModal();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [canClose, closeModal, isOpen]);

  const handleStartLink = useCallback(async () => {
    setError('');
    setIsRequestingCode(true);

    try {
      const response = await fetch('/api/profile/telegram/link/start', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({}),
      });

      if (!response.ok) {
        setError(await buildApiError(response, 'Не удалось начать привязку Telegram.'));
        return;
      }

      const data = await response.json() as {
        challengeId?: string;
        botStartUrl?: string;
      };

      const nextChallengeId = data.challengeId || '';
      const nextBotStartUrl = data.botStartUrl || '';
      setChallengeId(nextChallengeId);
      setBotStartUrl(nextBotStartUrl);
      setCode('');
      setStep('code');
    } catch {
      setError('Ошибка при запуске перепривязки Telegram.');
    } finally {
      setIsRequestingCode(false);
    }
  }, [buildApiError]);

  const handleConfirmCode = useCallback(async () => {
    if (code.length !== 6) {
      setError('Код должен состоять из 6 цифр.');
      return;
    }

    if (!challengeId) {
      setError('Сессия привязки истекла. Получите код заново.');
      resetChallengeFlow();
      return;
    }

    setError('');
    setStep('loading');

    try {
      const response = await fetch('/api/profile/telegram/link/confirm', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          code,
          challengeId,
        }),
      });

      if (!response.ok) {
        setError(await buildApiError(response, 'Не удалось подтвердить привязку Telegram.'));
        setStep('code');
        return;
      }

      const data = await response.json() as { telegram?: TelegramState | null };
      const nextTelegram = data.telegram;
      if (!nextTelegram?.telegramId) {
        setError('Сервис вернул неполный ответ. Попробуйте ещё раз.');
        setStep('code');
        return;
      }

      setTelegram({
        telegramId: nextTelegram.telegramId,
        telegramChatId: nextTelegram.telegramChatId ?? null,
        telegramUsername: nextTelegram.telegramUsername ?? null,
        telegramLinkedAt: nextTelegram.telegramLinkedAt ?? null,
      });
      onLinked?.({
        telegramId: nextTelegram.telegramId,
        telegramUsername: nextTelegram.telegramUsername ?? null,
      });

      setCode('');
      setChallengeId('');
      setBotStartUrl('');
      setStep('success');

      clearCloseTimer();
      closeTimeoutRef.current = window.setTimeout(() => {
        clearCloseTimer();
        onClose();
        resetChallengeFlow();
      }, SUCCESS_CLOSE_DELAY_MS);
    } catch {
      setError('Ошибка при подтверждении кода Telegram.');
      setStep('code');
    }
  }, [buildApiError, challengeId, clearCloseTimer, code, onClose, onLinked, resetChallengeFlow]);

  const handleResetToInitial = useCallback(() => {
    if (step === 'loading') return;
    setError('');
    resetChallengeFlow();
  }, [resetChallengeFlow, step]);

  const handleSaveBotToken = useCallback(async () => {
    if (step !== 'initial' || isSavingBotToken || isClearingBotToken) {
      return;
    }

    const normalizedToken = botTokenInput.trim();
    if (!normalizedToken) {
      setTokenError('Введите токен Telegram-бота.');
      return;
    }

    setTokenError('');
    setIsSavingBotToken(true);

    try {
      const response = await fetch('/api/profile/telegram', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ botToken: normalizedToken }),
      });

      if (!response.ok) {
        setTokenError(await buildApiError(response, 'Не удалось сохранить токен Telegram-бота.'));
        return;
      }

      const data = await response.json() as {
        clickNotifications?: Partial<ClickNotificationsStatus>;
      };

      setClickNotifications({
        hasBotToken: Boolean(data.clickNotifications?.hasBotToken),
        featureAvailableByPlan: Boolean(data.clickNotifications?.featureAvailableByPlan),
        canSendToUserNow: Boolean(data.clickNotifications?.canSendToUserNow),
      });
      setBotTokenInput('');
    } catch {
      setTokenError('Ошибка при сохранении токена Telegram-бота.');
    } finally {
      setIsSavingBotToken(false);
    }
  }, [botTokenInput, buildApiError, isClearingBotToken, isSavingBotToken, step]);

  const handleClearBotToken = useCallback(async () => {
    if (step !== 'initial' || isSavingBotToken || isClearingBotToken) {
      return;
    }

    setTokenError('');
    setIsClearingBotToken(true);

    try {
      const response = await fetch('/api/profile/telegram', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ botToken: null }),
      });

      if (!response.ok) {
        setTokenError(await buildApiError(response, 'Не удалось удалить токен Telegram-бота.'));
        return;
      }

      const data = await response.json() as {
        clickNotifications?: Partial<ClickNotificationsStatus>;
      };

      setClickNotifications({
        hasBotToken: Boolean(data.clickNotifications?.hasBotToken),
        featureAvailableByPlan: Boolean(data.clickNotifications?.featureAvailableByPlan),
        canSendToUserNow: Boolean(data.clickNotifications?.canSendToUserNow),
      });
      setBotTokenInput('');
    } catch {
      setTokenError('Ошибка при удалении токена Telegram-бота.');
    } finally {
      setIsClearingBotToken(false);
    }
  }, [buildApiError, isClearingBotToken, isSavingBotToken, step]);

  if (!isOpen) return null;

  const content = (
    <div className="fixed inset-0 z-[100] flex items-center justify-center overflow-hidden p-4">
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        onClick={canClose ? closeModal : undefined}
        className="absolute inset-0 bg-black/60 backdrop-blur-sm"
      />

      <motion.div
        initial={{ opacity: 0, scale: 0.95, y: 10 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        exit={{ opacity: 0, scale: 0.95, y: 10 }}
        className="relative z-10 flex max-h-[calc(100vh-2rem)] w-full max-w-[460px] flex-col items-center overflow-hidden rounded-3xl border border-white/10 bg-[#0A0A0A]/95 shadow-[0_0_60px_rgba(109,40,217,0.15)] backdrop-blur-xl"
      >
        <div className="pointer-events-none absolute right-[-50%] top-[-50%] h-[320px] w-[320px] rounded-full bg-violet-500/10 blur-3xl" />
        <div className="pointer-events-none absolute bottom-[-50%] left-[-50%] h-[320px] w-[320px] rounded-full bg-[#2AABEE]/20 blur-3xl" />

        <div className="relative z-10 flex min-h-0 w-full flex-col overflow-y-auto p-6 sm:p-8">
          {step === 'success' ? (
            <motion.div
              initial={{ scale: 0.85, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              className="flex min-h-[320px] flex-col items-center justify-center py-8"
            >
              <div className="mb-6 flex h-20 w-20 items-center justify-center rounded-full border border-green-500/20 bg-green-500/10 shadow-[0_0_40px_rgba(34,197,94,0.3)]">
                <CheckCircle2 className="h-10 w-10 text-green-400" />
              </div>
              <h2 className="mb-2 text-2xl font-bold tracking-tight text-white">Telegram обновлён</h2>
              <p className="text-sm text-gray-400">Профиль синхронизирован. Закрываем окно...</p>
            </motion.div>
          ) : (
            <>
              <div className="mx-auto mb-6 mt-2 flex h-16 w-16 items-center justify-center rounded-2xl border border-white/10 bg-white/[0.03] shadow-[0_0_30px_rgba(139,92,246,0.2)]">
                <span className="inline-flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-fuchsia-500 to-violet-600 text-white shadow-[0_0_20px_rgba(139,92,246,0.24)]">
                  <LinkIcon className="h-4 w-4" strokeWidth={2.5} />
                </span>
              </div>

              <div className="mb-6 text-center">
                <h2 className="mb-2 text-2xl font-bold tracking-tight text-white">
                  {step === 'initial' ? 'Настройки профиля' : 'Подтверждение кода'}
                </h2>
                <p className="text-sm text-gray-400">
                  {step === 'initial'
                    ? 'Управление настройками аккаунта'
                    : 'Введите код из Telegram-бота для завершения перепривязки'}
                </p>
              </div>

              {step === 'initial' ? (
                <>
                  <div className="mb-4 rounded-2xl border border-white/10 bg-white/5 p-5">
                    <div className="mb-3 flex items-center gap-2 text-sm text-gray-300">
                      <ShieldCheck className="h-4 w-4 text-violet-300" />
                      Текущий аккаунт
                    </div>
                    <p className="mb-1 break-all text-sm font-medium text-white">{linkedLabel}</p>
                    <p className="text-xs text-gray-500">
                      {telegram.telegramLinkedAt
                        ? 'Telegram привязан и используется для входа в аккаунт.'
                        : 'Telegram ещё не привязан. Привяжите аккаунт для безопасного входа.'}
                    </p>
                  </div>

                  <div className="mb-6 w-full rounded-2xl border border-white/10 bg-white/5 p-5 text-left">
                    <div className="mb-3 flex items-center gap-2 text-sm font-semibold text-white">
                      <Bell className="h-4 w-4 text-[#2AABEE]" />
                      Уведомления о кликах
                    </div>

                    <p className="mb-3 text-xs leading-relaxed text-gray-400">
                      Добавьте токен своего Telegram-бота, чтобы получать уведомления о засчитанных кликах. Перед
                      сохранением отправьте вашему боту команду <code>/start</code>.
                    </p>

                    <div className="mb-3 rounded-xl border border-white/10 bg-black/30 p-3 text-xs">
                      {!clickNotifications.featureAvailableByPlan ? (
                        <span className="text-amber-300">Недоступно на тарифе Free. Функция открывается с тарифа Lite.</span>
                      ) : clickNotifications.canSendToUserNow ? (
                        <span className="text-emerald-300">Статус: настроено, уведомления могут отправляться.</span>
                      ) : clickNotifications.hasBotToken ? (
                        <span className="text-emerald-300">Статус: токен сохранён.</span>
                      ) : (
                        <span className="text-amber-300">Статус: не настроено. Сначала сохраните токен.</span>
                      )}
                    </div>

                    <div className="mb-3">
                      <label className="mb-1.5 block text-xs text-gray-400">Токен Telegram-бота</label>
                      <input
                        type="password"
                        value={botTokenInput}
                        onChange={(event) => {
                          setBotTokenInput(event.target.value);
                          setTokenError('');
                        }}
                        placeholder="123456789:AA..."
                        disabled={!clickNotifications.featureAvailableByPlan || isSavingBotToken || isClearingBotToken}
                        className="h-10 w-full rounded-lg border border-white/10 bg-black/40 px-3 text-sm text-gray-100 placeholder:text-gray-500 outline-none transition-colors focus:border-violet-500/40 disabled:cursor-not-allowed disabled:opacity-60"
                      />
                    </div>

                    <div className="flex flex-wrap gap-2">
                      <button
                        type="button"
                        onClick={handleSaveBotToken}
                        disabled={!clickNotifications.featureAvailableByPlan || isSavingBotToken || isClearingBotToken}
                        className="inline-flex items-center justify-center rounded-lg bg-gradient-to-r from-fuchsia-500 to-violet-600 px-3 py-2 text-xs font-semibold text-white transition-all hover:opacity-95 disabled:cursor-not-allowed disabled:opacity-55"
                      >
                        {isSavingBotToken ? (
                          <>
                            <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
                            Сохраняем...
                          </>
                        ) : clickNotifications.hasBotToken ? (
                          'Обновить токен'
                        ) : (
                          'Сохранить токен'
                        )}
                      </button>

                      <button
                        type="button"
                        onClick={handleClearBotToken}
                        disabled={isSavingBotToken || isClearingBotToken || (!clickNotifications.hasBotToken && !botTokenInput.trim())}
                        className="inline-flex items-center justify-center rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-xs font-semibold text-gray-300 transition-colors hover:bg-white/10 hover:text-white disabled:cursor-not-allowed disabled:opacity-50"
                      >
                        {isClearingBotToken ? (
                          <>
                            <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
                            Очищаем...
                          </>
                        ) : (
                          <>
                            <Trash2 className="mr-1 h-3.5 w-3.5" />
                            Очистить токен
                          </>
                        )}
                      </button>
                    </div>

                    <ApiErrorAlert message={tokenError} compact className="mt-3" />
                  </div>

                  <button
                    type="button"
                    onClick={handleStartLink}
                    disabled={isRequestingCode || isSavingBotToken || isClearingBotToken}
                    className="mb-4 flex w-full items-center justify-center gap-2 rounded-xl bg-[#2AABEE] px-4 py-3.5 font-medium text-white shadow-[0_0_20px_rgba(42,171,238,0.3)] transition-all hover:bg-[#229ED9] disabled:cursor-not-allowed disabled:bg-[#2AABEE]/60"
                  >
                    {isRequestingCode ? (
                      <>
                        <Loader2 className="h-5 w-5 animate-spin" />
                        Получаем код...
                      </>
                    ) : (
                      telegram.telegramId ? 'Перепривязать Telegram' : 'Привязать Telegram'
                    )}
                  </button>
                </>
              ) : (
                <motion.div
                  initial={{ opacity: 0, y: 10 }}
                  animate={{ opacity: 1, y: 0 }}
                  className="w-full"
                >
                  <a
                    href={botStartUrl || botUrl || '#'}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="mb-6 flex w-full items-center justify-center gap-2 rounded-xl border border-white/10 bg-white/5 py-3 text-sm font-medium text-white transition-colors hover:bg-white/10"
                  >
                    <MessageCircle className="h-4 w-4 text-[#2AABEE]" />
                    Открыть бота в Telegram
                  </a>

                  <div className="relative mb-6">
                    <input
                      type="text"
                      inputMode="numeric"
                      placeholder="X X X X X X"
                      value={code}
                      onChange={(event) => {
                        setCode(event.target.value.replace(/\D/g, '').slice(0, 6));
                        setError('');
                      }}
                      maxLength={6}
                      disabled={step === 'loading'}
                      className={`w-full rounded-xl border bg-black/40 py-4 text-center font-mono text-2xl tracking-[0.5em] text-white placeholder-gray-600 outline-none transition-all ${
                        error
                          ? 'border-red-500/50 focus:border-red-500 focus:bg-red-500/5'
                          : 'border-white/10 focus:border-violet-500/50 focus:bg-white/5'
                      } ${step === 'loading' ? 'opacity-60' : ''}`}
                    />
                  </div>

                  <button
                    type="button"
                    onClick={handleConfirmCode}
                    disabled={step === 'loading' || code.length !== 6}
                    className="mb-3 flex w-full items-center justify-center gap-2 rounded-xl bg-[#2AABEE] px-4 py-3.5 font-medium text-white shadow-[0_0_20px_rgba(42,171,238,0.3)] transition-all hover:bg-[#229ED9] disabled:cursor-not-allowed disabled:bg-[#2AABEE]/50 disabled:text-white/70"
                  >
                    {step === 'loading' ? (
                      <>
                        <Loader2 className="h-5 w-5 animate-spin" />
                        Проверка кода...
                      </>
                    ) : (
                      'Подтвердить код'
                    )}
                  </button>

                  <button
                    type="button"
                    onClick={handleResetToInitial}
                    disabled={step === 'loading'}
                    className="w-full rounded-xl border border-white/10 bg-white/5 px-4 py-3 text-sm font-medium text-gray-300 transition-colors hover:bg-white/10 hover:text-white disabled:opacity-50"
                  >
                    Назад
                  </button>
                </motion.div>
              )}

              <ApiErrorAlert message={error} compact className="mb-2 mt-1" />

              <button
                type="button"
                onClick={closeModal}
                disabled={!canClose}
                className="self-center px-4 py-2 text-sm font-medium text-gray-500 transition-colors hover:text-white disabled:opacity-30 disabled:hover:text-gray-500"
              >
                Закрыть
              </button>
            </>
          )}
        </div>
      </motion.div>
    </div>
  );

  if (typeof document === 'undefined') {
    return content;
  }

  return createPortal(content, document.body);
}
