'use client';

import Link from 'next/link';
import Image from 'next/image';
import { useRouter, useSearchParams } from 'next/navigation';
import { AnimatePresence, motion } from 'framer-motion';
import {
  ArrowUpRight,
  Copy,
  Download,
  Filter,
  FolderOpen,
  Grid3X3,
  List,
  Lock,
  MoreVertical,
  Plus,
  QrCode,
  Search,
  Settings,
  Star,
} from 'lucide-react';
import QRCode from 'qrcode';
import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
import ApiErrorAlert from '@/app/components/ApiErrorAlert';
import QRCodeModal from '@/app/components/QRCodeModal';
import CreateLinkDialog from '@/app/components/profile/CreateLinkDialog';
import { UniversalDropdown, UniversalDropdownOption } from '@/app/components/profile/UniversalDropdown';
import type { ProfileFolder, ProfileLinkItem, ProfileTag } from '@/app/components/profile/types';
import { useToast } from '@/app/components/ToastProvider';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';
import type { PlanFeatures } from '@/lib/plans/types';

type SortBy = 'newest' | 'oldest' | 'most-clicked';
type ViewMode = 'grid' | 'list';
type QuickFilter = 'all' | 'favorites' | 'password';

type PlanState = {
  features?: PlanFeatures;
  [key: string]: unknown;
} | null;

type ProfileQRCodesTabProps = {
  folderId: string | null;
  isFavorite: boolean;
  tagIds: string[];
  searchQuery: string;
  sortBy: SortBy;
  folders: ProfileFolder[];
  tags: ProfileTag[];
  totalLinks: number;
  favoriteCount: number;
  planState: PlanState;
  onDataChanged?: () => Promise<void> | void;
  onGoToLinks: () => void;
};

const DEFAULT_PLAN_FEATURES: PlanFeatures = {
  customSlug: false,
  password: false,
  expiresAt: false,
  clickLimit: false,
  telegramClickNotifications: false,
  bulkActions: false,
  csvExport: false,
  pdfExport: false,
  manualOgEditing: false,
};

const PAGE_SIZE = 18;

function isUnauthorizedResponse(response: Response) {
  return response.status === 401;
}

function isAbortError(error: unknown) {
  return error instanceof DOMException && error.name === 'AbortError';
}

function formatDate(value: string) {
  return new Date(value).toLocaleDateString('ru-RU', {
    day: '2-digit',
    month: 'short',
    year: 'numeric',
  });
}

function FavoriteGradientStar({ className }: { className?: string }) {
  const gradientId = useId();

  return (
    <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
      <defs>
        <linearGradient id={gradientId} x1="0%" y1="0%" x2="100%" y2="100%">
          <stop offset="0%" stopColor="#c084fc">
            <animate
              attributeName="stop-color"
              values="#c084fc;#a78bfa;#e879f9;#c084fc"
              dur="3.2s"
              repeatCount="indefinite"
            />
          </stop>
          <stop offset="100%" stopColor="#8b5cf6">
            <animate
              attributeName="stop-color"
              values="#8b5cf6;#d946ef;#a855f7;#8b5cf6"
              dur="3.2s"
              repeatCount="indefinite"
            />
          </stop>
        </linearGradient>
      </defs>
      <path
        d="M11.525 2.295a1 1 0 0 1 1.95 0l2.138 6.586a1 1 0 0 0 .95.69h6.925a1 1 0 0 1 .592 1.806l-5.603 4.07a1 1 0 0 0-.364 1.118l2.138 6.586a1 1 0 0 1-1.538 1.118l-5.603-4.07a1 1 0 0 0-1.176 0l-5.603 4.07a1 1 0 0 1-1.538-1.118l2.138-6.586a1 1 0 0 0-.364-1.118L.92 11.377a1 1 0 0 1 .592-1.806h6.925a1 1 0 0 0 .95-.69z"
        fill={`url(#${gradientId})`}
      />
    </svg>
  );
}

export default function ProfileQRCodesTab({
  folderId,
  isFavorite,
  tagIds,
  searchQuery,
  sortBy,
  folders,
  tags,
  totalLinks,
  favoriteCount,
  planState,
  onDataChanged,
  onGoToLinks,
}: ProfileQRCodesTabProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const toast = useToast();
  const planFeatures = planState?.features ?? DEFAULT_PLAN_FEATURES;

  const [links, setLinks] = useState<ProfileLinkItem[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isLoadingMore, setIsLoadingMore] = useState(false);
  const [hasMore, setHasMore] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [loadError, setLoadError] = useState('');
  const [searchInput, setSearchInput] = useState(searchQuery);
  const [viewMode, setViewMode] = useState<ViewMode>('grid');
  const [quickFilter, setQuickFilter] = useState<QuickFilter>(isFavorite ? 'favorites' : 'all');
  const [showFolderMenu, setShowFolderMenu] = useState(false);
  const [showTagMenu, setShowTagMenu] = useState(false);
  const [showSortMenu, setShowSortMenu] = useState(false);
  const [qrModal, setQrModal] = useState<{ isOpen: boolean; url: string; title: string | null }>({
    isOpen: false,
    url: '',
    title: null,
  });
  const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
  const [qrPreviewMap, setQrPreviewMap] = useState<Record<string, string>>({});

  const abortRef = useRef<AbortController | null>(null);
  const requestIdRef = useRef(0);
  const previewGenerationRef = useRef(0);

  const selectedTags = useMemo(() => tags.filter((tag) => tagIds.includes(tag.id)), [tagIds, tags]);
  const activeTagLabel = useMemo(() => {
    if (tagIds.length === 0) return 'Теги';
    if (tagIds.length === 1) {
      return tags.find((tag) => tag.id === tagIds[0])?.name || 'Теги';
    }
    return `Теги (${tagIds.length})`;
  }, [tagIds, tags]);
  const passwordCount = useMemo(() => links.filter((link) => link.hasPassword).length, [links]);

  const visibleLinks = useMemo(() => {
    if (quickFilter === 'password') {
      return links.filter((link) => link.hasPassword);
    }
    return links;
  }, [links, quickFilter]);

  const updateParams = useCallback((mutate: (params: URLSearchParams) => void) => {
    const params = new URLSearchParams(searchParams.toString());
    mutate(params);
    router.replace(params.toString() ? `/profile?${params.toString()}` : '/profile', { scroll: false });
  }, [router, searchParams]);

  const fetchLinks = useCallback(async (page = 1, append = false) => {
    const requestId = ++requestIdRef.current;
    const controller = new AbortController();

    if (!append) {
      abortRef.current?.abort();
      abortRef.current = controller;
      setIsLoading(true);
      setLoadError('');
    } else {
      setIsLoadingMore(true);
    }

    try {
      const params = new URLSearchParams();
      if (folderId) params.set('folderId', folderId);
      if (isFavorite) params.set('isFavorite', 'true');
      tagIds.forEach((id) => params.append('tagIds', id));
      if (searchQuery) params.set('search', searchQuery);
      params.set('sort', sortBy);
      params.set('page', String(page));
      params.set('limit', String(PAGE_SIZE));

      const response = await fetch(`/api/links?${params.toString()}`, {
        signal: controller.signal,
      });

      if (!response.ok) {
        if (isUnauthorizedResponse(response)) {
          router.push('/login', { scroll: false });
          return;
        }
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Не удалось загрузить QR-коды'));
      }

      const data = await response.json() as { links?: ProfileLinkItem[]; meta?: { hasMore?: boolean } };
      if (requestId !== requestIdRef.current) return;

      const nextLinks = data.links || [];
      setLinks((prev) => (append ? [...prev, ...nextLinks] : nextLinks));
      setCurrentPage(page);
      setHasMore(Boolean(data.meta?.hasMore));
    } catch (error) {
      if (isAbortError(error)) return;
      const message = error instanceof Error ? error.message : 'Не удалось загрузить QR-коды';
      setLoadError(message);
    } finally {
      if (!append) {
        if (requestId === requestIdRef.current) {
          setIsLoading(false);
        }
      } else {
        setIsLoadingMore(false);
      }
    }
  }, [folderId, isFavorite, searchQuery, sortBy, tagIds, router]);

  useEffect(() => {
    void fetchLinks(1, false);
  }, [fetchLinks]);

  useEffect(() => {
    setSearchInput(searchQuery);
  }, [searchQuery]);

  useEffect(() => {
    if (isFavorite) {
      setQuickFilter('favorites');
      return;
    }
    setQuickFilter((current) => (current === 'favorites' ? 'all' : current));
  }, [isFavorite]);

  useEffect(() => () => {
    abortRef.current?.abort();
  }, []);

  useEffect(() => {
    const timer = setTimeout(() => {
      const normalized = searchInput.trim();
      if (normalized === (searchQuery || '')) return;
      updateParams((params) => {
        if (normalized) {
          params.set('search', normalized);
        } else {
          params.delete('search');
        }
      });
    }, 280);

    return () => clearTimeout(timer);
  }, [searchInput, searchQuery, updateParams]);

  useEffect(() => {
    if (!(showFolderMenu || showTagMenu || showSortMenu)) {
      return;
    }

    const close = () => {
      setShowFolderMenu(false);
      setShowTagMenu(false);
      setShowSortMenu(false);
    };

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        close();
      }
    };

    window.addEventListener('click', close);
    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('click', close);
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [showFolderMenu, showSortMenu, showTagMenu]);

  useEffect(() => {
    const generationId = ++previewGenerationRef.current;
    let cancelled = false;

    if (links.length === 0) {
      setQrPreviewMap({});
      return () => {
        cancelled = true;
      };
    }

    const generatePreviews = async () => {
      const previews = await Promise.all(
        links.map(async (link) => {
          try {
            const previewUrl = await QRCode.toDataURL(link.shortUrl, {
              width: 256,
              margin: 1,
              color: {
                dark: '#0f172a',
                light: '#ffffff',
              },
            });
            return { id: link.id, previewUrl };
          } catch {
            return { id: link.id, previewUrl: '' };
          }
        })
      );

      if (cancelled || generationId !== previewGenerationRef.current) return;

      setQrPreviewMap(() => {
        const nextMap: Record<string, string> = {};
        previews.forEach((entry) => {
          if (entry.previewUrl) {
            nextMap[entry.id] = entry.previewUrl;
          }
        });
        return nextMap;
      });
    };

    void generatePreviews();

    return () => {
      cancelled = true;
    };
  }, [links]);

  const handleCopy = useCallback(async (value: string) => {
    try {
      await navigator.clipboard.writeText(value);
      toast.success('Ссылка скопирована');
    } catch {
      toast.error('Не удалось скопировать ссылку');
    }
  }, [toast]);

  const handleDownloadPreview = useCallback((link: ProfileLinkItem) => {
    const preview = qrPreviewMap[link.id];
    if (!preview) {
      toast.info('QR-код еще подготавливается, попробуйте через пару секунд');
      return;
    }

    const anchor = document.createElement('a');
    const safeName = (link.slug || link.id).replace(/[^a-zA-Z0-9-_]+/g, '-').replace(/-+/g, '-');
    anchor.href = preview;
    anchor.download = `${safeName || 'qrcode'}.png`;
    anchor.click();
  }, [qrPreviewMap, toast]);

  const handleSelectQuickFilter = useCallback((filter: QuickFilter) => {
    setQuickFilter(filter);
    if (filter === 'favorites') {
      updateParams((params) => params.set('isFavorite', 'true'));
      return;
    }

    updateParams((params) => params.delete('isFavorite'));
  }, [updateParams]);

  const handleLinksChanged = useCallback(async () => {
    await fetchLinks(1, false);
    if (onDataChanged) {
      await onDataChanged();
    }
  }, [fetchLinks, onDataChanged]);

  return (
    <motion.section
      key="qrcodes"
      initial={{ opacity: 0, y: 14 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
      transition={{ duration: 0.24, ease: 'easeOut' }}
      className="mx-auto max-w-6xl space-y-4"
    >
      <div className="relative overflow-hidden rounded-2xl border border-white/10 bg-white/[0.03] p-6 backdrop-blur-xl">
        <div className="pointer-events-none absolute -right-20 -top-20 h-64 w-64 rounded-full bg-violet-500/15 blur-3xl" />
        <div className="relative z-10 flex flex-col gap-4 md:flex-row md:items-end md:justify-between">
          <div>
            <h1 className="mb-2 text-2xl font-bold tracking-tight text-white md:text-3xl">Настраиваемые QR-коды</h1>
            <p className="text-sm text-gray-400">
              Генерация, скачивание и быстрый доступ к QR-кодам ваших ссылок в одном разделе.
            </p>
          </div>

          <button
            type="button"
            onClick={() => setIsCreateDialogOpen(true)}
            className="inline-flex items-center justify-center gap-2 rounded-lg bg-[#2AABEE] px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-[#229ED9] shadow-[0_0_20px_rgba(42,171,238,0.25)]"
          >
            <Plus className="h-4 w-4" />
            Создать QR-код
          </button>
        </div>
      </div>

      <div className="rounded-2xl border border-white/10 bg-black/35 p-4 backdrop-blur-md">
        <div className="flex flex-col gap-3">
          <div className="flex flex-wrap items-center gap-2">
            <button
              type="button"
              onClick={() => handleSelectQuickFilter('all')}
              className={`rounded-lg border px-3 py-1.5 text-sm transition-colors ${
                quickFilter === 'all'
                  ? 'border-white/20 bg-white/10 text-white'
                  : 'border-white/10 text-gray-400 hover:bg-white/[0.05] hover:text-white'
              }`}
            >
              Все QR-коды
              <span className="ml-2 text-xs text-gray-500">{totalLinks}</span>
            </button>

            <button
              type="button"
              onClick={() => handleSelectQuickFilter('favorites')}
              className={`inline-flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm transition-colors ${
                quickFilter === 'favorites'
                  ? 'border-violet-500/35 bg-violet-500/10 text-violet-100'
                  : 'border-white/10 text-gray-400 hover:bg-white/[0.05] hover:text-white'
              }`}
            >
              {quickFilter === 'favorites' ? (
                <FavoriteGradientStar className="h-3.5 w-3.5" />
              ) : (
                <Star className="h-3.5 w-3.5" />
              )}
              Избранные
              <span className="text-xs text-gray-500">{favoriteCount}</span>
            </button>

            <button
              type="button"
              onClick={() => handleSelectQuickFilter('password')}
              className={`inline-flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm transition-colors ${
                quickFilter === 'password'
                  ? 'border-cyan-500/25 bg-cyan-500/10 text-cyan-200'
                  : 'border-white/10 text-gray-400 hover:bg-white/[0.05] hover:text-white'
              }`}
            >
              <Lock className="h-3.5 w-3.5" />
              С паролем
              <span className="text-xs text-gray-500">{passwordCount}</span>
            </button>

            <UniversalDropdown
              open={showFolderMenu}
              onOpenChange={(nextOpen) => {
                setShowFolderMenu(nextOpen);
                if (nextOpen) {
                  setShowTagMenu(false);
                  setShowSortMenu(false);
                }
              }}
              label={folderId ? folders.find((folder) => folder.id === folderId)?.name || 'Все папки' : 'Все папки'}
              leadingIcon={<FolderOpen className="h-3.5 w-3.5" />}
              active={showFolderMenu || Boolean(folderId)}
              widthClassName="w-56"
              menuPaddingClassName="p-1.5"
            >
              <div className="space-y-1">
                <UniversalDropdownOption
                  onSelect={() => {
                    updateParams((params) => params.delete('folderId'));
                    setShowFolderMenu(false);
                  }}
                  selected={!folderId}
                  label="Все папки"
                />
                {folders.map((folder) => (
                  <UniversalDropdownOption
                    key={folder.id}
                    onSelect={() => {
                      updateParams((params) => params.set('folderId', folder.id));
                      setShowFolderMenu(false);
                    }}
                    selected={folderId === folder.id}
                    label={folder.name}
                  />
                ))}
              </div>
            </UniversalDropdown>

            <UniversalDropdown
              open={showTagMenu}
              onOpenChange={(nextOpen) => {
                setShowTagMenu(nextOpen);
                if (nextOpen) {
                  setShowFolderMenu(false);
                  setShowSortMenu(false);
                }
              }}
              label={activeTagLabel}
              leadingIcon={<Filter className="h-3.5 w-3.5" />}
              active={showTagMenu || tagIds.length > 0}
              widthClassName="w-60"
            >
              <div className="space-y-1">
                {tags.length > 0 ? (
                  tags.map((tag) => {
                    const active = tagIds.includes(tag.id);
                    return (
                      <UniversalDropdownOption
                        key={tag.id}
                        onSelect={() => {
                          updateParams((params) => {
                            const current = params.getAll('tagIds');
                            params.delete('tagIds');
                            const next = current.includes(tag.id)
                              ? current.filter((id) => id !== tag.id)
                              : [...current, tag.id];
                            next.forEach((id) => params.append('tagIds', id));
                          });
                        }}
                        selected={active}
                        leftSlot={<span className="h-2 w-2 rounded-full" style={{ backgroundColor: tag.color }} />}
                        rightSlot={(
                          <span className="rounded border border-white/10 bg-black/40 px-1.5 py-0.5 text-[10px] text-gray-500">
                            {tag._count?.links ?? 0}
                          </span>
                        )}
                        label={tag.name}
                      />
                    );
                  })
                ) : (
                  <p className="px-3 py-2 text-sm text-gray-500">Нет тегов</p>
                )}
              </div>
            </UniversalDropdown>

            <UniversalDropdown
              open={showSortMenu}
              onOpenChange={(nextOpen) => {
                setShowSortMenu(nextOpen);
                if (nextOpen) {
                  setShowFolderMenu(false);
                  setShowTagMenu(false);
                }
              }}
              label={sortBy === 'newest' ? 'Сначала новые' : sortBy === 'oldest' ? 'Сначала старые' : 'По кликам'}
              active={showSortMenu || sortBy !== 'newest'}
              align="right"
              widthClassName="w-48"
              menuPaddingClassName="p-1.5"
            >
              <div className="space-y-1">
                {(['newest', 'oldest', 'most-clicked'] as SortBy[]).map((sort) => (
                  <UniversalDropdownOption
                    key={sort}
                    onSelect={() => {
                      updateParams((params) => {
                        if (sort === 'newest') {
                          params.delete('sort');
                        } else {
                          params.set('sort', sort);
                        }
                      });
                      setShowSortMenu(false);
                    }}
                    selected={sortBy === sort}
                    label={sort === 'newest' ? 'Сначала новые' : sort === 'oldest' ? 'Сначала старые' : 'По кликам'}
                  />
                ))}
              </div>
            </UniversalDropdown>
          </div>

          <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
            <div className="relative w-full sm:max-w-sm">
              <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-500" />
              <input
                type="text"
                value={searchInput}
                onChange={(event) => setSearchInput(event.target.value)}
                placeholder="Поиск по названию или ссылке..."
                className="w-full rounded-lg border border-white/10 bg-white/[0.03] py-2 pl-10 pr-3 text-sm text-white outline-none transition-all placeholder:text-gray-500 focus:border-violet-500/50 focus:bg-white/[0.05]"
              />
            </div>

            <div className="inline-flex items-center gap-1 rounded-lg border border-white/10 bg-black/40 p-1">
              <button
                type="button"
                onClick={() => setViewMode('grid')}
                className={`inline-flex items-center gap-1 rounded-md px-2 py-1.5 text-xs transition-colors ${
                  viewMode === 'grid' ? 'bg-white/10 text-white' : 'text-gray-400 hover:text-white'
                }`}
              >
                <Grid3X3 className="h-3.5 w-3.5" />
                Сетка
              </button>
              <button
                type="button"
                onClick={() => setViewMode('list')}
                className={`inline-flex items-center gap-1 rounded-md px-2 py-1.5 text-xs transition-colors ${
                  viewMode === 'list' ? 'bg-white/10 text-white' : 'text-gray-400 hover:text-white'
                }`}
              >
                <List className="h-3.5 w-3.5" />
                Список
              </button>
            </div>
          </div>

          {selectedTags.length > 0 ? (
            <div className="flex flex-wrap items-center gap-1.5">
              {selectedTags.map((tag) => (
                <span
                  key={tag.id}
                  className="rounded-md border px-2 py-0.5 text-[11px]"
                  style={{
                    borderColor: `${tag.color}55`,
                    backgroundColor: `${tag.color}1a`,
                    color: tag.color,
                  }}
                >
                  #{tag.name}
                </span>
              ))}
            </div>
          ) : null}
        </div>
      </div>

      <ApiErrorAlert message={loadError} />

      {isLoading ? (
        <div className={`grid gap-4 ${viewMode === 'grid' ? 'grid-cols-1 md:grid-cols-2 xl:grid-cols-3' : 'grid-cols-1'}`}>
          {Array.from({ length: viewMode === 'grid' ? 6 : 4 }).map((_, index) => (
            <div key={`qr-skeleton-${index}`} className="h-64 animate-pulse rounded-2xl border border-white/10 bg-white/[0.02]" />
          ))}
        </div>
      ) : visibleLinks.length === 0 ? (
        <div className="rounded-2xl border border-white/10 bg-black/35 p-8 text-center backdrop-blur-md">
          <p className="mb-1 text-sm text-gray-300">QR-коды не найдены</p>
          <p className="text-xs text-gray-500">Измените фильтры, выполните поиск или создайте новую ссылку для генерации QR.</p>
          <div className="mt-4 inline-flex items-center gap-2">
            <button
              type="button"
              onClick={() => setIsCreateDialogOpen(true)}
              className="rounded-lg bg-gradient-to-r from-fuchsia-500 to-violet-600 px-4 py-2 text-sm font-medium text-white transition-all hover:opacity-95"
            >
              Создать ссылку
            </button>
            <button
              type="button"
              onClick={onGoToLinks}
              className="rounded-lg border border-white/10 bg-white/[0.03] px-4 py-2 text-sm text-gray-300 transition-colors hover:bg-white/[0.06] hover:text-white"
            >
              Перейти в ссылки
            </button>
          </div>
        </div>
      ) : viewMode === 'grid' ? (
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
          {visibleLinks.map((link, index) => {
            const preview = qrPreviewMap[link.id];
            return (
              <motion.article
                key={link.id}
                initial={{ opacity: 0, scale: 0.96, y: 10 }}
                animate={{ opacity: 1, scale: 1, y: 0 }}
                transition={{ duration: 0.24, delay: index * 0.03 }}
                whileHover={{ y: -2 }}
                className="group relative overflow-hidden rounded-[1.5rem] border border-white/10 bg-black/40 p-4 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.04]"
              >
                <div className="pointer-events-none absolute right-0 top-0 h-32 w-32 bg-gradient-to-bl from-white/[0.05] to-transparent" />

                <div className="mb-4 flex items-start justify-between gap-3">
                  <div className="h-[86px] w-[86px] shrink-0 overflow-hidden rounded-xl border border-white/20 bg-white p-1.5 shadow-sm">
                    {preview ? (
                      <Image src={preview} alt="QR preview" width={72} height={72} className="h-full w-full rounded-md object-cover" unoptimized />
                    ) : (
                      <div className="flex h-full w-full items-center justify-center rounded-md bg-slate-100">
                        <QrCode className="h-6 w-6 text-slate-600" />
                      </div>
                    )}
                  </div>
                  <div className="flex items-center gap-1">
                    {link.isFavorite ? (
                      <span className="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-amber-500/20 bg-amber-500/10 text-amber-300">
                        <Star className="h-3.5 w-3.5 fill-current" />
                      </span>
                    ) : null}
                    {link.hasPassword ? (
                      <span className="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-cyan-500/20 bg-cyan-500/10 text-cyan-300">
                        <Lock className="h-3.5 w-3.5" />
                      </span>
                    ) : null}
                    <button
                      type="button"
                      className="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-400 opacity-0 transition-all duration-200 hover:bg-white/[0.08] hover:text-white group-hover:opacity-100"
                      title="Дополнительно"
                    >
                      <MoreVertical className="h-3.5 w-3.5" />
                    </button>
                  </div>
                </div>

                <div className="mb-4 min-w-0">
                  <p className="truncate text-sm font-semibold text-white">{link.title || link.slug}</p>
                  <p className="truncate font-mono text-[11px] text-violet-300">{link.shortUrl}</p>
                </div>

                <div className="mb-3 flex items-center justify-between gap-2 border-t border-white/5 pt-3">
                  <div className="flex flex-col">
                    <span className="text-[10px] uppercase tracking-wider text-gray-500">Сканирований</span>
                    <span className="font-mono text-lg font-semibold tracking-tight text-white">{link.clicks.toLocaleString('ru-RU')}</span>
                  </div>
                  <div className="inline-flex items-center gap-1.5">
                    <Link
                      href={`/profile/links/${link.id}`}
                      scroll={false}
                      className="group/settings inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:border-violet-500/30 hover:bg-white/[0.1] hover:text-violet-300"
                      title="Настройки"
                    >
                      <Settings className="h-3.5 w-3.5 transition-transform duration-200 group-hover/settings:rotate-45" />
                    </Link>
                    <button
                      type="button"
                      onClick={() => handleDownloadPreview(link)}
                      className="group/download inline-flex items-center gap-1.5 rounded-lg border border-white/10 bg-white/[0.03] px-2.5 py-1.5 text-xs font-medium text-gray-100 transition-colors hover:bg-white/[0.1] hover:text-white"
                    >
                      <Download className="h-3.5 w-3.5 transition-transform duration-200 group-hover/download:-translate-y-0.5" />
                      Скачать
                    </button>
                  </div>
                </div>

                <div className="flex items-center justify-between gap-2">
                  <span className="text-[11px] text-gray-500">{formatDate(link.createdAt)}</span>
                  <div className="inline-flex items-center gap-1">
                    <button
                      type="button"
                      onClick={() => void handleCopy(link.shortUrl)}
                      className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
                      title="Копировать ссылку"
                    >
                      <Copy className="h-3.5 w-3.5" />
                    </button>
                    <button
                      type="button"
                      onClick={() => setQrModal({ isOpen: true, url: link.shortUrl, title: link.title })}
                      className="group/qr inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:border-violet-500/30 hover:bg-white/[0.08] hover:text-violet-300"
                      title="Открыть QR"
                    >
                      <QrCode className="h-3.5 w-3.5 transition-transform duration-200 group-hover/qr:scale-110" />
                    </button>
                    <Link
                      href={`/profile/links/${link.id}`}
                      scroll={false}
                      className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
                      title="Статистика"
                    >
                      <ArrowUpRight className="h-3.5 w-3.5" />
                    </Link>
                  </div>
                </div>
              </motion.article>
            );
          })}
        </div>
      ) : (
        <div className="overflow-hidden rounded-2xl border border-white/10 bg-black/35 backdrop-blur-md">
          <div className="divide-y divide-white/5">
            {visibleLinks.map((link, index) => {
              const preview = qrPreviewMap[link.id];
              return (
                <motion.div
                  key={link.id}
                  initial={{ opacity: 0, y: 8 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{ duration: 0.22, delay: index * 0.02 }}
                  whileHover={{ y: -1 }}
                  className="group/list grid grid-cols-1 items-center gap-3 px-4 py-3 transition-colors hover:bg-white/[0.03] md:grid-cols-[92px_1fr_auto]"
                >
                  <div className="h-[72px] w-[72px] overflow-hidden rounded-lg border border-white/15 bg-white p-1.5 shadow-sm">
                    {preview ? (
                      <Image src={preview} alt="QR preview" width={56} height={56} className="h-full w-full rounded object-cover" unoptimized />
                    ) : (
                      <div className="flex h-full w-full items-center justify-center rounded bg-slate-100">
                        <QrCode className="h-5 w-5 text-slate-600" />
                      </div>
                    )}
                  </div>

                  <div className="min-w-0">
                    <div className="mb-1 flex flex-wrap items-center gap-1.5">
                      <p className="truncate text-sm font-medium text-white">{link.title || link.slug}</p>
                      {link.isFavorite ? (
                        <span className="inline-flex items-center gap-1 rounded-md border border-amber-500/20 bg-amber-500/10 px-1.5 py-0.5 text-[10px] text-amber-200">
                          <Star className="h-3 w-3 fill-current" />
                          Избранная
                        </span>
                      ) : null}
                      {link.hasPassword ? (
                        <span className="inline-flex items-center gap-1 rounded-md border border-cyan-500/20 bg-cyan-500/10 px-1.5 py-0.5 text-[10px] text-cyan-200">
                          <Lock className="h-3 w-3" />
                          Пароль
                        </span>
                      ) : null}
                    </div>
                    <p className="truncate font-mono text-xs text-violet-300">{link.shortUrl}</p>
                    <p className="mt-1 text-[11px] text-gray-500">
                      {link.clicks.toLocaleString('ru-RU')} сканирований • {formatDate(link.createdAt)}
                    </p>
                  </div>

                  <div className="inline-flex items-center gap-1 md:justify-self-end">
                    <button
                      type="button"
                      onClick={() => void handleCopy(link.shortUrl)}
                      className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
                      title="Копировать"
                    >
                      <Copy className="h-3.5 w-3.5 transition-transform duration-200 group-hover/list:scale-105" />
                    </button>
                    <button
                      type="button"
                      onClick={() => setQrModal({ isOpen: true, url: link.shortUrl, title: link.title })}
                      className="group/qr inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:border-violet-500/30 hover:bg-white/[0.08] hover:text-violet-300"
                      title="QR"
                    >
                      <QrCode className="h-3.5 w-3.5 transition-transform duration-200 group-hover/qr:scale-110" />
                    </button>
                    <a
                      href={link.shortUrl}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
                      title="Открыть ссылку"
                    >
                      <ArrowUpRight className="h-3.5 w-3.5" />
                    </a>
                    <Link
                      href={`/profile/links/${link.id}`}
                      scroll={false}
                      className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-white/10 bg-white/[0.03] text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
                      title="Статистика"
                    >
                      <ArrowUpRight className="h-3.5 w-3.5" />
                    </Link>
                  </div>
                </motion.div>
              );
            })}
          </div>
        </div>
      )}

      {hasMore ? (
        <div className="flex justify-center">
          <button
            type="button"
            disabled={isLoadingMore}
            onClick={() => void fetchLinks(currentPage + 1, true)}
            className="rounded-lg border border-white/10 bg-white/[0.02] px-4 py-2 text-sm text-gray-300 transition-colors hover:bg-white/[0.06] hover:text-white disabled:opacity-60"
          >
            {isLoadingMore ? 'Загрузка...' : 'Показать еще'}
          </button>
        </div>
      ) : null}

      <div className="rounded-2xl border border-cyan-500/20 bg-cyan-500/10 p-4">
        <p className="text-xs text-cyan-100">
          QR-коды привязаны к вашим ссылкам: любая новая ссылка сразу доступна для генерации QR, а статистика сканов
          совпадает с кликами по short URL.
        </p>
      </div>

      <QRCodeModal
        isOpen={qrModal.isOpen}
        onClose={() => setQrModal({ isOpen: false, url: '', title: null })}
        url={qrModal.url}
        title={qrModal.title}
      />

      <CreateLinkDialog
        isOpen={isCreateDialogOpen}
        onClose={() => setIsCreateDialogOpen(false)}
        onCreated={handleLinksChanged}
        planFeatures={planFeatures}
        initialFolderId={folderId}
      />
    </motion.section>
  );
}
