'use client';

import { AnimatePresence, motion } from 'framer-motion';
import { Bell, Check, Loader2, ShieldCheck, Sparkles, X } from 'lucide-react';
import { signOutToPath } from '@/lib/auth-client';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import OGEditor from '@/app/components/OGEditor';
import ApiErrorAlert from '@/app/components/ApiErrorAlert';
import { useToast } from '@/app/components/ToastProvider';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';
import { datetimeLocalToIso, formatForDatetimeLocalInput } from '@/lib/datetime-local';
import { getRuntimeClientConfig } from '@/lib/runtime-client-config';
import type { PlanFeatures } from '@/lib/plans/types';
import type { ProfileLinkItem } from '@/app/components/profile/types';

type EditLinkDialogProps = {
  isOpen: boolean;
  link: ProfileLinkItem | null;
  planFeatures: PlanFeatures;
  onClose: () => void;
  onSaved: () => Promise<void> | void;
};

type TelegramClickNotificationsStatus = {
  hasBotToken: boolean;
  featureAvailableByPlan: boolean;
  canSendToUserNow: boolean;
};

const EMPTY_OG = {
  ogTitle: '',
  ogDescription: '',
  ogImage: '',
};

const EMPTY_TELEGRAM_CLICK_STATUS: TelegramClickNotificationsStatus = {
  hasBotToken: false,
  featureAvailableByPlan: false,
  canSendToUserNow: false,
};

function isUnauthorizedResponse(response: Response) {
  return response.status === 401;
}

function hasAdvancedAccess(features: PlanFeatures) {
  return features.password || features.expiresAt || features.clickLimit || features.manualOgEditing;
}

export default function EditLinkDialog({
  isOpen,
  link,
  planFeatures,
  onClose,
  onSaved,
}: EditLinkDialogProps) {
  const toast = useToast();
  const closeTimerRef = useRef<number | null>(null);

  const [title, setTitle] = useState('');
  const [description, setDescription] = useState('');
  const [isActive, setIsActive] = useState(true);
  const [expiresAtInput, setExpiresAtInput] = useState('');
  const [hasInvalidExpiresAt, setHasInvalidExpiresAt] = useState(false);
  const [clickLimitInput, setClickLimitInput] = useState('');
  const [passwordInput, setPasswordInput] = useState('');
  const [clearPassword, setClearPassword] = useState(false);
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [telegramClickNotificationsEnabled, setTelegramClickNotificationsEnabled] = useState(false);
  const [telegramClickStatus, setTelegramClickStatus] = useState<TelegramClickNotificationsStatus>({
    ...EMPTY_TELEGRAM_CLICK_STATUS,
    featureAvailableByPlan: planFeatures.telegramClickNotifications,
  });
  const [isTelegramStatusLoading, setIsTelegramStatusLoading] = useState(false);

  const [ogEditorData, setOgEditorData] = useState(EMPTY_OG);
  const [ogMode, setOgMode] = useState<'source' | 'custom'>('source');
  const [isOgUploading, setIsOgUploading] = useState(false);

  const [isSaving, setIsSaving] = useState(false);
  const [isSuccess, setIsSuccess] = useState(false);
  const [formError, setFormError] = useState('');

  useEffect(() => {
    return () => {
      if (closeTimerRef.current !== null) {
        window.clearTimeout(closeTimerRef.current);
      }
    };
  }, []);

  const projectTimeZone = useMemo(() => getRuntimeClientConfig().timeZone, []);

  const resetFromLink = useCallback(() => {
    if (!link) return;

    setTitle(link.title || '');
    setDescription(link.description || '');
    setIsActive(link.isActive);
    const normalizedExpiresAt = formatForDatetimeLocalInput(link.expiresAt, projectTimeZone);
    setExpiresAtInput(normalizedExpiresAt);
    setHasInvalidExpiresAt(Boolean(link.expiresAt) && !normalizedExpiresAt);
    setClickLimitInput(link.clickLimit ? String(link.clickLimit) : '');
    setPasswordInput('');
    setClearPassword(false);
    setShowAdvanced(false);
    setTelegramClickNotificationsEnabled(Boolean(link.telegramClickNotificationsEnabled));
    setTelegramClickStatus({
      ...EMPTY_TELEGRAM_CLICK_STATUS,
      featureAvailableByPlan: planFeatures.telegramClickNotifications,
    });
    setIsTelegramStatusLoading(false);

    const hasCustomOg = Boolean(link.ogTitle || link.ogDescription || link.ogImage);
    setOgMode(hasCustomOg ? 'custom' : 'source');
    setOgEditorData({
      ogTitle: link.ogTitle || '',
      ogDescription: link.ogDescription || '',
      ogImage: link.ogImage || '',
    });
    setIsOgUploading(false);

    setIsSaving(false);
    setIsSuccess(false);
    setFormError('');
  }, [link, planFeatures.telegramClickNotifications, projectTimeZone]);

  useEffect(() => {
    if (isOpen && link) {
      resetFromLink();
    }
  }, [isOpen, link, resetFromLink]);

  useEffect(() => {
    if (!planFeatures.manualOgEditing) {
      setOgMode('source');
      setOgEditorData(EMPTY_OG);
    }
  }, [planFeatures.manualOgEditing]);

  useEffect(() => {
    if (!isOpen) {
      return;
    }

    let isCancelled = false;

    const loadTelegramStatus = async () => {
      setIsTelegramStatusLoading(true);

      try {
        const response = await fetch('/api/profile/telegram', { cache: 'no-store' });

        if (!response.ok) {
          if (!isCancelled) {
            setTelegramClickStatus({
              ...EMPTY_TELEGRAM_CLICK_STATUS,
              featureAvailableByPlan: planFeatures.telegramClickNotifications,
            });
          }
          return;
        }

        const data = await response.json() as {
          clickNotifications?: Partial<TelegramClickNotificationsStatus>;
        };

        if (isCancelled) {
          return;
        }

        setTelegramClickStatus({
          hasBotToken: Boolean(data.clickNotifications?.hasBotToken),
          featureAvailableByPlan: Boolean(data.clickNotifications?.featureAvailableByPlan),
          canSendToUserNow: Boolean(data.clickNotifications?.canSendToUserNow),
        });
      } catch {
        if (!isCancelled) {
          setTelegramClickStatus({
            ...EMPTY_TELEGRAM_CLICK_STATUS,
            featureAvailableByPlan: planFeatures.telegramClickNotifications,
          });
        }
      } finally {
        if (!isCancelled) {
          setIsTelegramStatusLoading(false);
        }
      }
    };

    void loadTelegramStatus();

    return () => {
      isCancelled = true;
    };
  }, [isOpen, planFeatures.telegramClickNotifications]);

  const handleToggleTelegramNotifications = useCallback((nextValue: boolean) => {
    if (!nextValue) {
      setTelegramClickNotificationsEnabled(false);
      setFormError('');
      return;
    }

    if (!telegramClickStatus.featureAvailableByPlan) {
      setFormError('Telegram-уведомления о кликах доступны на тарифе Lite и выше.');
      return;
    }

    if (isTelegramStatusLoading) {
      setFormError('Проверяем настройки Telegram. Попробуйте ещё раз через пару секунд.');
      return;
    }

    if (!telegramClickStatus.hasBotToken) {
      setFormError('Токен Telegram-бота не настроен. Добавьте его в настройках профиля.');
      return;
    }

    setFormError('');
    setTelegramClickNotificationsEnabled(true);
  }, [isTelegramStatusLoading, telegramClickStatus.featureAvailableByPlan, telegramClickStatus.hasBotToken]);

  const isTelegramToggleDisabled = isTelegramStatusLoading
    || (!telegramClickStatus.featureAvailableByPlan && !telegramClickNotificationsEnabled);

  const handleSubmit = useCallback(async (event: React.FormEvent) => {
    event.preventDefault();
    if (!link || isSaving || isOgUploading) return;

    setIsSaving(true);
    setFormError('');

    try {
      const payload: Record<string, unknown> = {
        title: title.trim() || null,
        description: description.trim() || null,
        isActive,
        telegramClickNotificationsEnabled,
      };

      if (planFeatures.expiresAt) {
        if (hasInvalidExpiresAt && !expiresAtInput.trim()) {
          throw new Error('Текущий срок действия ссылки некорректен. Укажите дату заново.');
        }
        payload.expiresAt = datetimeLocalToIso(expiresAtInput, projectTimeZone);
      }

      if (planFeatures.clickLimit) {
        payload.clickLimit = clickLimitInput ? Number(clickLimitInput) : null;
      }

      if (planFeatures.password) {
        if (clearPassword) {
          payload.password = null;
        } else if (passwordInput.trim()) {
          payload.password = passwordInput;
        }
      }

      if (planFeatures.manualOgEditing) {
        if (ogMode === 'custom') {
          payload.ogTitle = ogEditorData.ogTitle || null;
          payload.ogDescription = ogEditorData.ogDescription || null;
          payload.ogImage = ogEditorData.ogImage || null;
        } else {
          payload.ogTitle = null;
          payload.ogDescription = null;
          payload.ogImage = null;
        }
      }

      const response = await fetch(`/api/links/${link.id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      if (!response.ok) {
        if (isUnauthorizedResponse(response)) {
          await signOutToPath('/login');
          return;
        }
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Не удалось сохранить изменения'));
      }

      await onSaved();

      setIsSuccess(true);
      toast.success('Ссылка обновлена');
      closeTimerRef.current = window.setTimeout(() => {
        onClose();
      }, 380);
    } catch (error) {
      setFormError(error instanceof Error ? error.message : 'Не удалось сохранить изменения');
    } finally {
      setIsSaving(false);
    }
  }, [
    clearPassword,
    clickLimitInput,
    description,
    expiresAtInput,
    hasInvalidExpiresAt,
    isActive,
    isOgUploading,
    isSaving,
    link,
    ogEditorData.ogDescription,
    ogEditorData.ogImage,
    ogEditorData.ogTitle,
    ogMode,
    onClose,
    onSaved,
    passwordInput,
    planFeatures.clickLimit,
    planFeatures.expiresAt,
    planFeatures.manualOgEditing,
    planFeatures.password,
    projectTimeZone,
    telegramClickNotificationsEnabled,
    title,
    toast,
  ]);

  if (!isOpen || !link) return null;

  const dialogContent = (
    <AnimatePresence>
      <motion.div
        className="fixed inset-0 z-[90] flex items-center justify-center p-4"
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
      >
        <motion.button
          type="button"
          aria-label="Закрыть окно редактирования"
          onClick={onClose}
          className="absolute inset-0 bg-black/70 backdrop-blur-sm"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
        />
        <motion.div
          initial={{ opacity: 0, y: 20, scale: 0.98 }}
          animate={{ opacity: 1, y: 0, scale: 1 }}
          exit={{ opacity: 0, y: 12, scale: 0.98 }}
          transition={{ duration: 0.2 }}
          className="relative w-full max-w-3xl max-h-[90vh] overflow-y-auto rounded-2xl border border-white/10 bg-[#0A0A0A]/95 backdrop-blur-xl shadow-[0_0_32px_rgba(139,92,246,0.1)]"
        >
          <div className="sticky top-0 z-10 px-5 py-4 border-b border-white/10 bg-[#0A0A0A]/95 backdrop-blur-xl flex items-center justify-between">
            <div className="min-w-0">
              <h3 className="text-lg font-semibold text-white truncate">Редактировать ссылку</h3>
            </div>
            <button
              type="button"
              onClick={onClose}
              className="w-9 h-9 rounded-xl border border-white/10 bg-white/[0.03] text-gray-400 hover:text-white hover:bg-white/[0.08] transition-colors inline-flex items-center justify-center"
              aria-label="Закрыть"
            >
              <X className="w-4 h-4" />
            </button>
          </div>

          <form onSubmit={handleSubmit} className="p-5 space-y-4">
            <div className="rounded-xl border border-white/10 bg-white/[0.02] p-4">
              <p className="text-sm text-gray-300 mb-3 flex items-center gap-2">
                <Sparkles className="w-4 h-4 text-violet-300" />
                Основные поля
              </p>
              <div className="grid grid-cols-1 gap-3">
                <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                  <div>
                    <label className="block text-xs text-gray-400 mb-1.5">Заголовок</label>
                    <input
                      value={title}
                      onChange={(event) => setTitle(event.target.value)}
                      placeholder="Название ссылки"
                      className="w-full h-11 px-3 rounded-lg border border-white/10 bg-black/40 text-sm text-gray-100 placeholder:text-gray-500 outline-none focus:border-violet-500/40"
                    />
                  </div>

                  <div>
                    <label className="block text-xs text-gray-400 mb-1.5">Статус</label>
                    <button
                      type="button"
                      onClick={() => setIsActive((prev) => !prev)}
                      className={`w-full h-11 px-3 rounded-lg border text-sm inline-flex items-center justify-center gap-2 transition-colors ${
                        isActive
                          ? 'border-emerald-500/30 bg-emerald-500/15 text-emerald-200'
                          : 'border-amber-500/30 bg-amber-500/15 text-amber-200'
                      }`}
                    >
                      <ShieldCheck className="w-4 h-4" />
                      {isActive ? 'Активна' : 'Отключена'}
                    </button>
                  </div>
                </div>

                <div>
                  <label className="block text-xs text-gray-400 mb-1.5">Описание</label>
                  <textarea
                    value={description}
                    onChange={(event) => setDescription(event.target.value)}
                    rows={2}
                    placeholder="Необязательно"
                    className="w-full px-3 py-2.5 rounded-lg border border-white/10 bg-black/40 text-sm text-gray-100 placeholder:text-gray-500 outline-none focus:border-violet-500/40 resize-none"
                  />
                </div>
              </div>
            </div>

            <div className="rounded-xl border border-white/10 bg-white/[0.02] p-4">
              <div className="flex items-start justify-between gap-4">
                <div className="space-y-1">
                  <p className="text-sm text-gray-200 flex items-center gap-2">
                    <Bell className="w-4 h-4 text-[#2AABEE]" />
                    Уведомления о кликах в Telegram
                  </p>
                  <p className="text-xs text-gray-500">
                    Управляет отправкой уведомлений о новых засчитанных кликах по этой ссылке.
                  </p>
                  {!telegramClickStatus.featureAvailableByPlan ? (
                    <p className="text-xs text-amber-300">Доступно на тарифе Lite и выше.</p>
                  ) : isTelegramStatusLoading ? (
                    <p className="text-xs text-gray-400">Проверяем настройки Telegram...</p>
                  ) : telegramClickStatus.hasBotToken ? (
                    <p className="text-xs text-emerald-300">Токен бота настроен.</p>
                  ) : (
                    <p className="text-xs text-amber-300">
                      Токен бота не настроен. Добавьте токен в настройках профиля.
                    </p>
                  )}
                </div>

                <button
                  type="button"
                  aria-label="Переключить Telegram-уведомления о кликах"
                  aria-pressed={telegramClickNotificationsEnabled}
                  onClick={() => handleToggleTelegramNotifications(!telegramClickNotificationsEnabled)}
                  disabled={isTelegramToggleDisabled}
                  className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition-all duration-300 ${
                    telegramClickNotificationsEnabled
                      ? 'border-violet-400/60 bg-violet-500/30'
                      : 'border-white/10 bg-white/5'
                  } ${isTelegramToggleDisabled ? 'cursor-not-allowed opacity-50' : ''}`}
                >
                  <span
                    className={`inline-block h-5 w-5 transform rounded-full bg-white shadow-[0_0_14px_rgba(255,255,255,0.25)] transition-transform duration-300 ${
                      telegramClickNotificationsEnabled ? 'translate-x-[20px]' : 'translate-x-[2px]'
                    }`}
                  />
                </button>
              </div>
            </div>

            <div className="rounded-xl border border-white/10 bg-white/[0.02] p-4">
              <button
                type="button"
                onClick={() => setShowAdvanced((prev) => !prev)}
                className="w-full inline-flex items-center justify-between text-left"
              >
                <span className="text-sm text-gray-200 font-medium">Расширенные настройки</span>
                <span className="text-xs text-gray-500">{showAdvanced ? 'Скрыть' : 'Открыть'}</span>
              </button>

              {showAdvanced ? (
                <div className="mt-3 space-y-3">
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                    {planFeatures.expiresAt ? (
                      <div>
                        <label className="block text-xs text-gray-400 mb-1.5">Срок действия</label>
                        <input
                          type="datetime-local"
                          value={expiresAtInput}
                          onChange={(event) => {
                            setExpiresAtInput(event.target.value);
                            setHasInvalidExpiresAt(false);
                          }}
                          max="9999-12-31T23:59"
                          className="w-full h-10 px-3 rounded-lg border border-white/10 bg-black/40 text-sm text-gray-100 outline-none focus:border-violet-500/40"
                        />
                        {hasInvalidExpiresAt ? (
                          <p className="mt-1 text-[11px] text-amber-300">
                            Найдена некорректная дата срока действия. Укажите её заново.
                          </p>
                        ) : (
                          <p className="mt-1 text-[11px] text-gray-500">
                            Время указывается в таймзоне проекта: {projectTimeZone}
                          </p>
                        )}
                      </div>
                    ) : null}

                    {planFeatures.clickLimit ? (
                      <div>
                        <label className="block text-xs text-gray-400 mb-1.5">Лимит кликов</label>
                        <input
                          type="number"
                          min={1}
                          value={clickLimitInput}
                          onChange={(event) => setClickLimitInput(event.target.value)}
                          placeholder="Например 1000"
                          className="w-full h-10 px-3 rounded-lg border border-white/10 bg-black/40 text-sm text-gray-100 placeholder:text-gray-500 outline-none focus:border-violet-500/40"
                        />
                      </div>
                    ) : null}
                  </div>

                  {planFeatures.password ? (
                    <div className="space-y-2">
                      <div>
                        <label className="block text-xs text-gray-400 mb-1.5">Пароль на ссылку</label>
                        <input
                          type="password"
                          minLength={4}
                          value={passwordInput}
                          onChange={(event) => {
                            setPasswordInput(event.target.value);
                            if (event.target.value) {
                              setClearPassword(false);
                            }
                          }}
                          placeholder={link.hasPassword ? 'Новый пароль или оставьте пустым' : 'Установить пароль'}
                          className="w-full h-10 px-3 rounded-lg border border-white/10 bg-black/40 text-sm text-gray-100 placeholder:text-gray-500 outline-none focus:border-violet-500/40"
                        />
                      </div>

                      {link.hasPassword ? (
                        <label className="inline-flex items-center gap-2 text-xs text-gray-300">
                          <input
                            type="checkbox"
                            checked={clearPassword}
                            onChange={(event) => {
                              setClearPassword(event.target.checked);
                              if (event.target.checked) {
                                setPasswordInput('');
                              }
                            }}
                            className="w-4 h-4 rounded border-white/20 bg-black/30 text-violet-500 focus:ring-violet-500/40"
                          />
                          Удалить текущий пароль
                        </label>
                      ) : null}
                    </div>
                  ) : null}

                  {planFeatures.manualOgEditing ? (
                    <OGEditor
                      ogTitle={ogEditorData.ogTitle}
                      ogDescription={ogEditorData.ogDescription}
                      ogImage={ogEditorData.ogImage}
                      shortUrl={link.shortUrl}
                      mode={ogMode}
                      onModeChange={setOgMode}
                      onUploadStateChange={setIsOgUploading}
                      onChange={(data) => setOgEditorData((prev) => ({ ...prev, ...data }))}
                    />
                  ) : null}

                  {!hasAdvancedAccess(planFeatures) ? (
                    <p className="text-xs text-amber-300">Недоступно на текущем тарифе.</p>
                  ) : null}
                </div>
              ) : null}
            </div>

            <ApiErrorAlert message={formError} />

            <div className="sticky bottom-0 pb-1 pt-2 bg-gradient-to-t from-[#0A0A0A] to-transparent">
              <button
                type="submit"
                disabled={isSaving || isOgUploading}
                className={`w-full h-11 rounded-xl text-sm font-semibold transition-all duration-200 inline-flex items-center justify-center gap-2 ${
                  isSuccess && !isSaving && !isOgUploading
                    ? 'bg-emerald-500/90 text-white'
                    : 'bg-gradient-to-r from-fuchsia-500 to-violet-600 text-white hover:opacity-95 disabled:opacity-65'
                }`}
              >
                {isSaving || isOgUploading ? (
                  <>
                    <Loader2 className="w-4 h-4 animate-spin" />
                    {isOgUploading ? 'Загрузка OG изображения...' : 'Сохранение изменений...'}
                  </>
                ) : isSuccess ? (
                  <>
                    <Check className="w-4 h-4" />
                    Готово
                  </>
                ) : (
                  'Сохранить изменения'
                )}
              </button>
            </div>
          </form>
        </motion.div>
      </motion.div>
    </AnimatePresence>
  );

  if (typeof document === 'undefined') {
    return dialogContent;
  }

  return createPortal(dialogContent, document.body);
}
