﻿'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
import { AnimatePresence, motion } from 'framer-motion';
import ReactCountryFlag from 'react-country-flag';
import {
  Activity,
  ArrowLeft,
  Bot,
  CalendarDays,
  Clock,
  Compass,
  Globe,
  Laptop,
  Monitor,
  Send,
  ShieldAlert,
  Smartphone,
  Tablet,
  TrendingUp,
  Users,
  type LucideIcon,
} from 'lucide-react';
import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';
import ApiErrorAlert from '@/app/components/ApiErrorAlert';
import ExportButton from '@/app/components/ExportButton';
import ExportHtmlButton from '@/app/components/ExportHtmlButton';
import SafeResponsiveChart from '@/app/components/SafeResponsiveChart';
import { useToast } from '@/app/components/ToastProvider';
import { getResponseErrorTextWithRequestId } from '@/lib/api-client';
import { formatCountry } from '@/lib/stats-format';
import { formatDateMoscow, formatTimeMoscow } from '@/lib/time';
import type { PlanFeatures } from '@/lib/plans/types';
import { usePersistedState } from '@/lib/use-persisted-state';

interface LinkStats {
  id: string;
  shortUrl: string;
  longUrl: string;
  customAlias: string | null;
  title: string | null;
  description: string | null;
  ogDescription: string | null;
  clicks: number;
  isActive: boolean;
  expiresAt: string | null;
  clickLimit: number | null;
  createdAt: string;
  updatedAt: string;
  hasPassword?: boolean;
}

interface Stats {
  totalClicks: number;
  uniqueClicks: number;
  filteredClicks: number;
  botClicks: number;
  percentChange: number;
  clicksByDay: { date: string; clicks: number }[];
  clicksByHour: { hour: number; clicks: number }[];
  countries: { name: string; countryCode: string | null; count: number }[];
  devices: { device: string; count: number }[];
  browsers: { name: string; count: number }[];
  referers: { name: string; count: number }[];
  filterReasons: { reason: string; count: number }[];
  topSuspiciousReferers: { referer: string; count: number }[];
  topSuspiciousBrowsers: { browser: string; count: number }[];
  filteredRecentClicks: {
    id: string;
    filterReason: string;
    browser: string | null;
    referer: string | null;
    ipAddress: string | null;
    userAgent: string | null;
    createdAt: string;
  }[];
  recentClicks: {
    id: string;
    country: string | null;
    city: string | null;
    device: string | null;
    browser: string | null;
    os: string | null;
    referer: string | null;
    ipAddress: string | null;
    createdAt: string;
  }[];
}

type NamedCountLike = {
  name?: string;
  country?: string;
  countryCode?: string | null;
  browser?: string;
  referer?: string;
  count?: number;
};

type StatsApiResponse = {
  link: LinkStats;
  stats: Partial<Stats> & {
    countries?: NamedCountLike[];
    browsers?: NamedCountLike[];
    referers?: NamedCountLike[];
  };
};

type StatsPeriodOption = 7 | 30 | 90 | 180 | 365;

const DEVICE_COLORS = ['#d946ef', '#8b5cf6', '#2AABEE', '#10b981', '#f59e0b'];
const BROWSER_COLORS = ['#10b981', '#2AABEE', '#8b5cf6', '#f97316', '#ef4444'];
const SOURCE_COLORS = ['#2AABEE', '#E1306C', '#8b5cf6', '#FF0000', '#6b7280'];

const cn = (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(' ');

const getBlockReasonText = (reason: string) => {
  if (reason === 'head_request') return 'Технический запрос без перехода';
  if (reason === 'missing_user_agent') return 'Нет данных о браузере';
  if (reason === 'bot_user_agent') return 'Бот определен по данным браузера';
  if (reason === 'prefetch_request') return 'Предзагрузка страницы';
  if (reason === 'unknown') return 'Другая причина';
  return reason;
};



const getLinkDescription = (link: Pick<LinkStats, 'description' | 'ogDescription'>) => {
  const description = link.description?.trim();
  if (description) return description;

  const ogDescription = link.ogDescription?.trim();
  if (ogDescription) return ogDescription;

  return null;
};

const formatChartDate = (value: string) => {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleDateString('ru-RU', { day: '2-digit', month: 'short' }).replace('.', '');
};

const formatRecentClickTime = (value: string) => {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString('ru-RU', {
    day: '2-digit',
    month: 'short',
    hour: '2-digit',
    minute: '2-digit',
  });
};

const formatLinkMetaDateTime = (value: string | null | undefined) => {
  if (!value) return '—';

  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '—';

  const datePart = formatDateMoscow(date, { day: '2-digit', month: 'short' }).replace('.', '');
  const timePart = formatTimeMoscow(date, { hour: '2-digit', minute: '2-digit' });
  return `${datePart}, ${timePart} МСК`;
};

const pluralizeDays = (days: number) => {
  const abs = Math.abs(days);
  const mod10 = abs % 10;
  const mod100 = abs % 100;

  if (mod10 === 1 && mod100 !== 11) return 'день';
  if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return 'дня';
  return 'дней';
};

const toPercent = (count: number, total: number) => {
  if (total <= 0 || count <= 0) return 0;
  const value = Math.round((count / total) * 100);
  return value === 0 ? 1 : value;
};

const normalizeCountryCode = (code: string | null | undefined) => {
  const value = (code || '').trim().toUpperCase();
  if (!/^[A-Z]{2}$/.test(value)) return null;
  return value;
};

function getDeviceIcon(value: string): LucideIcon {
  const normalized = value.toLowerCase();
  if (normalized.includes('план') || normalized.includes('tablet')) return Tablet;
  if (normalized.includes('моб') || normalized.includes('mobile')) return Smartphone;
  if (normalized.includes('комп') || normalized.includes('desktop')) return Monitor;
  return Laptop;
}

function getBrowserIcon(value: string): LucideIcon {
  const normalized = value.toLowerCase();
  if (normalized.includes('telegram')) return Send;
  if (normalized.includes('safari')) return Compass;
  return Globe;
}

function renderDeviceValue(value: string) {
  const Icon = getDeviceIcon(value);
  return (
    <span className="inline-flex min-w-0 items-center gap-2">
      <Icon className="h-3.5 w-3.5 shrink-0 text-violet-300" />
      <span className="truncate">{value}</span>
    </span>
  );
}

function renderBrowserValue(value: string) {
  const Icon = getBrowserIcon(value);
  return (
    <span className="inline-flex min-w-0 items-center gap-2">
      <Icon className="h-3.5 w-3.5 shrink-0 text-violet-300" />
      <span className="truncate">{value}</span>
    </span>
  );
}

const formatHourLabel = (hour: number) => `${String(hour).padStart(2, '0')}:00`;

const STATS_CACHE_TTL_MS = 45_000;
const statsCache = new Map<string, { payload: StatsApiResponse; updatedAt: number }>();
const statsRequests = new Map<string, Promise<StatsApiResponse>>();
const STATS_PERIOD_OPTIONS: StatsPeriodOption[] = [7, 30, 90, 180, 365];
const STATS_PERIOD_OPTION_SET = new Set<StatsPeriodOption>(STATS_PERIOD_OPTIONS);
const DEFAULT_PLAN_FEATURES: PlanFeatures = {
  customSlug: false,
  password: false,
  expiresAt: false,
  clickLimit: false,
  telegramClickNotifications: false,
  bulkActions: false,
  csvExport: false,
  pdfExport: false,
  manualOgEditing: false,
};

const normalizeAvailablePeriods = (periods?: number[]): StatsPeriodOption[] => {
  if (!Array.isArray(periods) || periods.length === 0) {
    return [7] as StatsPeriodOption[];
  }

  const normalized = Array.from(
    new Set(
      periods
        .map((value) => Number(value))
        .filter((value): value is StatsPeriodOption => STATS_PERIOD_OPTION_SET.has(value as StatsPeriodOption))
    )
  ) as StatsPeriodOption[];

  return normalized.length > 0 ? normalized : [7];
};

const normalizeStatsPayload = (data: StatsApiResponse) => {
  const sourceLink = data.link;
  const sourceStats = data.stats ?? {};
  const rawCountries = (Array.isArray(sourceStats.countries) ? sourceStats.countries : []) as NamedCountLike[];
  const rawBrowsers = (Array.isArray(sourceStats.browsers) ? sourceStats.browsers : []) as NamedCountLike[];
  const rawReferers = (Array.isArray(sourceStats.referers) ? sourceStats.referers : []) as NamedCountLike[];

  const normalizedStats: Stats = {
    totalClicks: sourceStats.totalClicks ?? 0,
    uniqueClicks: sourceStats.uniqueClicks ?? 0,
    filteredClicks: sourceStats.filteredClicks ?? 0,
    botClicks: sourceStats.botClicks ?? 0,
    percentChange: sourceStats.percentChange ?? 0,
    clicksByDay: Array.isArray(sourceStats.clicksByDay) ? sourceStats.clicksByDay : [],
    clicksByHour: Array.isArray(sourceStats.clicksByHour) ? sourceStats.clicksByHour : [],
    countries: rawCountries.map((item) => ({
      name: item.name ?? item.country ?? 'Неизвестно',
      countryCode: item.countryCode ?? null,
      count: item.count ?? 0,
    })),
    devices: Array.isArray(sourceStats.devices) ? sourceStats.devices : [],
    browsers: rawBrowsers.map((item) => ({
      name: item.name ?? item.browser ?? 'Неизвестно',
      count: item.count ?? 0,
    })),
    referers: rawReferers.map((item) => ({
      name: item.name ?? item.referer ?? 'Прямой переход',
      count: item.count ?? 0,
    })),
    filterReasons: Array.isArray(sourceStats.filterReasons) ? sourceStats.filterReasons : [],
    topSuspiciousReferers: Array.isArray(sourceStats.topSuspiciousReferers) ? sourceStats.topSuspiciousReferers : [],
    topSuspiciousBrowsers: Array.isArray(sourceStats.topSuspiciousBrowsers) ? sourceStats.topSuspiciousBrowsers : [],
    filteredRecentClicks: Array.isArray(sourceStats.filteredRecentClicks) ? sourceStats.filteredRecentClicks : [],
    recentClicks: Array.isArray(sourceStats.recentClicks) ? sourceStats.recentClicks : [],
  };

  return {
    link: {
      id: sourceLink.id,
      shortUrl: sourceLink.shortUrl,
      longUrl: sourceLink.longUrl,
      customAlias: sourceLink.customAlias ?? null,
      title: sourceLink.title ?? null,
      description: sourceLink.description ?? null,
      ogDescription: sourceLink.ogDescription ?? null,
      clicks: sourceLink.clicks ?? 0,
      isActive: sourceLink.isActive ?? false,
      expiresAt: sourceLink.expiresAt ?? null,
      clickLimit: sourceLink.clickLimit ?? null,
      createdAt: sourceLink.createdAt ?? new Date(0).toISOString(),
      updatedAt: sourceLink.updatedAt ?? new Date(0).toISOString(),
      hasPassword: Boolean(sourceLink.hasPassword),
    },
    stats: normalizedStats,
  };
};

const STATS_REQUEST_TIMEOUT_MS = 15_000;

async function requestLinkStats(
  cacheKey: string,
  linkId: string,
  period: StatsPeriodOption,
  force: boolean
): Promise<StatsApiResponse> {
  if (!force) {
    const inFlightRequest = statsRequests.get(cacheKey);
    if (inFlightRequest) return inFlightRequest;
  }

  // AbortController + timeout защищают от подвисшего fetch (network drop,
  // Railway cold start). Без этого подвисший promise оставался в statsRequests
  // навсегда — все последующие клики на ту же статистику получали stale
  // pending-promise и спиннер крутился вечно.
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), STATS_REQUEST_TIMEOUT_MS);

  const performFetch = async (): Promise<StatsApiResponse> => {
    try {
      const response = await fetch(`/api/links/${linkId}/stats?period=${period}`, {
        signal: controller.signal,
        cache: 'no-store',
      });

      if (!response.ok) {
        throw new Error(await getResponseErrorTextWithRequestId(response, 'Не удалось загрузить статистику'));
      }

      return (await response.json()) as StatsApiResponse;
    } catch (error) {
      if (error instanceof DOMException && error.name === 'AbortError') {
        throw new Error('Сервер долго не отвечает. Попробуйте обновить страницу.');
      }
      throw error;
    }
  };

  const request = performFetch();
  statsRequests.set(cacheKey, request);

  // Гарантированно чистим map и таймер независимо от исхода (success / fail /
  // abort) — следующий клик не получит зависший promise.
  request.finally(() => {
    clearTimeout(timeoutId);
    if (statsRequests.get(cacheKey) === request) {
      statsRequests.delete(cacheKey);
    }
  });

  return request;
}

type DistributionListItem = {
  name: string;
  value: number;
  color: string;
  countryCode?: string | null;
};

function DistributionList({
  items,
  emptyText,
  distributionType,
}: {
  items: DistributionListItem[];
  emptyText: string;
  distributionType?: 'device' | 'browser';
}) {
  if (items.length === 0) {
    return <p className="text-xs text-gray-500">{emptyText}</p>;
  }

  return (
    <div className="space-y-2.5">
      {items.map((item, index) => (
        <motion.div
          key={`${item.name}-${index}`}
          layout
          initial={{ opacity: 0, y: 8 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.2, delay: index * 0.04 }}
        >
          <div className="mb-1.5 flex items-center justify-between gap-3 text-xs">
            <div className="flex min-w-0 items-center gap-2 text-gray-300">
              {distributionType === 'device' ? (
                renderDeviceValue(item.name)
              ) : distributionType === 'browser' ? (
                renderBrowserValue(item.name)
              ) : item.countryCode ? (
                <span
                  className="inline-flex h-3.5 w-5 shrink-0 items-center justify-center overflow-hidden rounded-[2px] leading-none"
                  aria-hidden="true"
                >
                  <ReactCountryFlag
                    countryCode={item.countryCode}
                    svg
                    aria-label={item.name}
                    className="h-full w-full shadow-[0_0_0_1px_rgba(255,255,255,0.08)]"
                    style={{ lineHeight: 1 }}
                  />
                </span>
              ) : (
                <span className="inline-flex h-3.5 w-5 shrink-0 items-center justify-center rounded-[2px] bg-white/5">
                  <Globe className="h-3 w-3 text-gray-500" />
                </span>
              )}
              {distributionType ? null : <span className="truncate leading-none">{item.name}</span>}
            </div>
            <span className="font-mono leading-none text-gray-400">{item.value}%</span>
          </div>
          <div className="h-1.5 overflow-hidden rounded-full bg-white/5">
            <motion.div
              initial={{ width: 0 }}
              animate={{ width: `${Math.min(100, item.value)}%` }}
              transition={{ duration: 0.45, delay: 0.06 + index * 0.05, ease: 'easeOut' }}
              className="h-full rounded-full shadow-[0_0_20px_rgba(139,92,246,0.2)]"
              style={{ backgroundColor: item.color }}
            />
          </div>
        </motion.div>
      ))}
    </div>
  );
}

type ProfileLinkStatsViewProps = {
  linkId: string;
  embedded?: boolean;
  onBack?: () => void;
  availableAnalyticsPeriods?: number[];
  planFeatures?: PlanFeatures;
};

export default function ProfileLinkStatsView({
  linkId,
  embedded = false,
  onBack,
  availableAnalyticsPeriods,
  planFeatures = DEFAULT_PLAN_FEATURES,
}: ProfileLinkStatsViewProps) {
  const router = useRouter();
  const { status } = useSession();
  const toast = useToast();
  const [period, setPeriod] = usePersistedState<StatsPeriodOption>(
    'profile.link.stats.period',
    30,
    (value): value is StatsPeriodOption => typeof value === 'number' && STATS_PERIOD_OPTION_SET.has(value as StatsPeriodOption)
  );
  const [loading, setLoading] = useState(true);
  const [link, setLink] = useState<LinkStats | null>(null);
  const [stats, setStats] = useState<Stats | null>(null);
  const [pageError, setPageError] = useState<string | null>(null);
  const [isPeriodMenuOpen, setIsPeriodMenuOpen] = useState(false);
  const periodMenuRef = useRef<HTMLDivElement | null>(null);
  const exportSectionRef = useRef<HTMLElement | null>(null);
  const hasLoadedRef = useRef(false);
  const requestIdRef = useRef(0);

  const availablePeriods = useMemo(() => {
    return normalizeAvailablePeriods(availableAnalyticsPeriods);
  }, [availableAnalyticsPeriods]);
  const availablePeriodSet = useMemo(() => new Set(availablePeriods), [availablePeriods]);

  const effectivePeriod = useMemo<StatsPeriodOption>(() => {
    if (availablePeriods.includes(period)) {
      return period;
    }

    return availablePeriods[0] || 7;
  }, [availablePeriods, period]);

  const periodLabel = useMemo(() => `За последние ${effectivePeriod} ${pluralizeDays(effectivePeriod)}`, [effectivePeriod]);

  useEffect(() => {
    if (period !== effectivePeriod) {
      setPeriod(effectivePeriod);
    }
  }, [effectivePeriod, period, setPeriod]);

  useEffect(() => {
    if (!isPeriodMenuOpen) return;

    const handlePointerDown = (event: PointerEvent) => {
      if (!periodMenuRef.current) return;
      if (periodMenuRef.current.contains(event.target as Node)) return;
      setIsPeriodMenuOpen(false);
    };

    window.addEventListener('pointerdown', handlePointerDown);
    return () => window.removeEventListener('pointerdown', handlePointerDown);
  }, [isPeriodMenuOpen]);

  useEffect(() => {
    if (status === 'unauthenticated') {
      router.push('/login', { scroll: false });
    }
  }, [status, router]);

  useEffect(() => {
    hasLoadedRef.current = false;
    setLoading(true);
    setLink(null);
    setStats(null);
    setPageError(null);
  }, [linkId]);

  const applyStatsPayload = useCallback((payload: StatsApiResponse) => {
    const normalized = normalizeStatsPayload(payload);
    setLink(normalized.link);
    setStats(normalized.stats);
    setPageError(null);
    hasLoadedRef.current = true;
  }, []);

  const fetchStats = useCallback(async () => {
    if (!linkId) return;

    const requestId = ++requestIdRef.current;
    const cacheKey = `${linkId}|${effectivePeriod}`;
    const cachedEntry = statsCache.get(cacheKey);
    const isCacheFresh = Boolean(cachedEntry) && Date.now() - (cachedEntry?.updatedAt ?? 0) < STATS_CACHE_TTL_MS;

    if (cachedEntry) {
      applyStatsPayload(cachedEntry.payload);
      // Даже если cache устарел — выключаем spinner: данные для отображения
      // есть, обновление пойдёт фоном. Без этого после смены linkId spinner
      // «залипал» при наличии stale cache.
      setLoading(false);
      if (isCacheFresh) {
        return;
      }
    }

    const shouldShowLoader = !cachedEntry && !hasLoadedRef.current;
    if (shouldShowLoader) {
      setLoading(true);
    }

    try {
      const payload = await requestLinkStats(cacheKey, linkId, effectivePeriod, false);
      statsCache.set(cacheKey, { payload, updatedAt: Date.now() });

      if (requestId !== requestIdRef.current) {
        return;
      }

      applyStatsPayload(payload);
    } catch (error: unknown) {
      if (requestId !== requestIdRef.current) {
        return;
      }

      const message = error instanceof Error ? error.message : 'Не удалось загрузить статистику';
      console.error('Error fetching stats:', error);
      setPageError(message);
    } finally {
      if (shouldShowLoader && requestId === requestIdRef.current) {
        setLoading(false);
      }
    }
  }, [applyStatsPayload, effectivePeriod, linkId]);

  useEffect(() => {
    if (status === 'authenticated' && linkId) {
      void fetchStats();
    }
  }, [status, linkId, fetchStats]);

  const overviewChartData = useMemo(() => {
    if (!stats) return [] as Array<{ name: string; clicks: number }>;

    return [...stats.clicksByDay]
      .sort((left, right) => new Date(left.date).getTime() - new Date(right.date).getTime())
      .map((entry) => ({
        name: formatChartDate(entry.date),
        clicks: entry.clicks,
      }));
  }, [stats]);

  const hourlyChartData = useMemo(() => {
    if (!stats) return [] as Array<{ name: string; clicks: number }>;

    return [...stats.clicksByHour]
      .sort((left, right) => left.hour - right.hour)
      .map((entry) => ({
        name: formatHourLabel(entry.hour),
        clicks: entry.clicks,
      }));
  }, [stats]);

  const devicesData = useMemo(() => {
    if (!stats) return [] as Array<{ name: string; value: number; color: string }>;

    const total = stats.devices.reduce((sum, item) => sum + item.count, 0);

    const mapped = stats.devices
      .filter((item) => item.count > 0)
      .map((item, index) => ({
        name: item.device || 'Неизвестно',
        value: toPercent(item.count, total),
        color: DEVICE_COLORS[index % DEVICE_COLORS.length],
      }));

    if (mapped.length === 0) {
      return [{ name: 'Неизвестно', value: 100, color: DEVICE_COLORS[0] }];
    }

    return mapped;
  }, [stats]);

  const browsersData = useMemo(() => {
    if (!stats) return [] as Array<{ name: string; value: number; color: string }>;

    const total = stats.browsers.reduce((sum, item) => sum + item.count, 0);

    const mapped = stats.browsers
      .filter((item) => item.count > 0)
      .map((item, index) => ({
        name: item.name || 'Неизвестно',
        value: toPercent(item.count, total),
        color: BROWSER_COLORS[index % BROWSER_COLORS.length],
      }));

    if (mapped.length === 0) {
      return [{ name: 'Неизвестно', value: 100, color: BROWSER_COLORS[0] }];
    }

    return mapped;
  }, [stats]);

  const sourcesData = useMemo(() => {
    if (!stats) return [] as Array<{ name: string; value: number; color: string }>;

    const total = stats.referers.reduce((sum, item) => sum + item.count, 0);

    return stats.referers
      .filter((item) => item.count > 0)
      .slice(0, 5)
      .map((item, index) => ({
        name: item.name || 'Прямой переход',
        value: toPercent(item.count, total),
        color: SOURCE_COLORS[index % SOURCE_COLORS.length],
      }));
  }, [stats]);

  const locationsData = useMemo(() => {
    if (!stats) return [] as Array<{ name: string; value: number; countryCode: string | null }>;

    const total = stats.countries.reduce((sum, item) => sum + item.count, 0);

    const mapped = stats.countries
      .filter((item) => item.count > 0)
      .slice(0, 5)
      .map((item) => ({
        name: formatCountry(item.name),
        value: toPercent(item.count, total),
        countryCode: normalizeCountryCode(item.countryCode),
      }));

    if (mapped.length === 0) {
      return [{ name: 'Неизвестно', value: 100, countryCode: null }];
    }

    return mapped;
  }, [stats]);

  const locationDistributionData = useMemo(
    () =>
      locationsData.map((entry, index) => ({
        ...entry,
        color: DEVICE_COLORS[index % DEVICE_COLORS.length],
      })),
    [locationsData]
  );

  const recentClicksData = useMemo(() => {
    if (!stats) {
      return [] as Array<{
        time: string;
        country: string;
        ip: string;
        device: string;
        browser: string;
        source: string;
      }>;
    }

    return stats.recentClicks.map((entry) => ({
      time: formatRecentClickTime(entry.createdAt),
      country: formatCountry(entry.country),
      ip: entry.ipAddress || '—',
      device: entry.device || 'Неизвестно',
      browser: entry.browser || 'Неизвестно',
      source: entry.referer || '—',
    }));
  }, [stats]);

  const handleBack = useCallback(() => {
    if (onBack) {
      onBack();
      return;
    }

    router.push('/profile/links', { scroll: false });
  }, [onBack, router]);

  if (loading) {
    return (
      <div className={cn(
        'flex items-center justify-center',
        embedded ? 'min-h-[50vh] py-8' : 'min-h-screen bg-[#050505]'
      )}>
        <div className="text-center">
          <div className="mx-auto mb-3 h-8 w-8 animate-spin rounded-full border-2 border-violet-400 border-t-transparent" />
          <p className="text-sm text-gray-400">Загрузка статистики...</p>
        </div>
      </div>
    );
  }

  if (!link || !stats) {
    return (
      <div className={cn(
        'flex items-center justify-center px-4',
        embedded ? 'min-h-[50vh] py-8' : 'min-h-screen bg-[#050505]'
      )}>
        <div className="w-full max-w-xl rounded-2xl border border-white/10 bg-black/40 p-6 text-center backdrop-blur-xl">
          <p className="text-sm text-gray-300">Ошибка загрузки статистики</p>
          <ApiErrorAlert message={pageError} className="mt-3" />
          <button
            type="button"
            onClick={handleBack}
            className="mt-3 inline-flex rounded-lg border border-white/10 bg-white/[0.03] px-3 py-1.5 text-xs text-gray-300 transition-colors hover:bg-white/[0.08] hover:text-white"
          >
            Вернуться к ссылкам
          </button>
        </div>
      </div>
    );
  }

  const isExpired = Boolean(link.expiresAt) && new Date(link.expiresAt as string) <= new Date();
  const isLimitReached = typeof link.clickLimit === 'number' && link.clickLimit > 0 && link.clicks >= link.clickLimit;
  const isAvailable = link.isActive && !isExpired && !isLimitReached;
  const linkDescription = getLinkDescription(link);

  const totalTrendClass = stats.percentChange >= 0 ? 'text-green-400' : 'text-red-400';
  const uniqueShare = stats.totalClicks > 0 ? Math.round((stats.uniqueClicks / stats.totalClicks) * 100) : 0;
  const chartOverviewData = overviewChartData.length > 0 ? overviewChartData : [{ name: '—', clicks: 0 }];
  const chartHourlyData = hourlyChartData.length > 0 ? hourlyChartData : [{ name: '00:00', clicks: 0 }];
  const suspiciousTraffic = stats.filteredClicks + stats.botClicks;
  const periodShortLabel = `${effectivePeriod} дн`;
  const createdAtLabel = formatLinkMetaDateTime(link.createdAt);
  const expiresAtLabel = link.expiresAt ? formatLinkMetaDateTime(link.expiresAt) : 'Бессрочно';
  const clickLimitLabel = typeof link.clickLimit === 'number' && link.clickLimit > 0
    ? `${link.clickLimit.toLocaleString('ru-RU')} кликов`
    : 'Без лимита';
  const customAliasLabel = link.customAlias ? `/${link.customAlias}` : null;
  const passwordLabel = link.hasPassword ? 'Пароль включен' : 'Без пароля';

  return (
    <div
      className={cn(
        'relative text-white',
        embedded ? '' : 'min-h-screen overflow-hidden bg-[#050505]'
      )}
    >
      {!embedded ? (
        <>
          <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_top_right,_rgba(139,92,246,0.14),_transparent_58%)]" />
          <div className="pointer-events-none absolute -top-20 right-0 h-80 w-80 rounded-full bg-fuchsia-500/10 blur-3xl" />
          <div className="pointer-events-none absolute bottom-0 left-0 h-96 w-96 rounded-full bg-blue-500/10 blur-3xl" />
        </>
      ) : null}

      <motion.section
        ref={exportSectionRef}
        key={`link-stats-${linkId}`}
        initial={{ opacity: 0, y: 14 }}
        animate={{ opacity: 1, y: 0 }}
        exit={{ opacity: 0, y: -10 }}
        transition={{ duration: 0.24, ease: 'easeOut' }}
        className={cn(
          'relative z-10 space-y-5 px-4 py-8 md:px-6 lg:px-8',
          embedded ? 'mx-auto max-w-6xl' : 'mx-auto max-w-6xl'
        )}
      >
        {pageError ? <ApiErrorAlert message={pageError} /> : null}

        <div className="relative z-[120] overflow-visible rounded-2xl border border-white/10 bg-black/35 p-6 backdrop-blur-xl">
          <div className="pointer-events-none absolute -top-20 -right-20 h-48 w-48 rounded-full bg-violet-500/7 blur-2xl" />
          <div className="pointer-events-none absolute -bottom-20 left-0 h-40 w-40 rounded-full bg-blue-500/6 blur-2xl" />

          <div className="relative flex flex-col gap-5 xl:flex-row xl:items-start xl:justify-between">
            <div className="min-w-0 space-y-3">
              <button
                type="button"
                onClick={handleBack}
                data-export-exclude="true"
                className="inline-flex items-center gap-2 rounded-lg border border-white/10 bg-white/[0.02] px-3 py-1.5 text-sm text-gray-300 transition-all duration-300 hover:border-white/20 hover:bg-white/[0.06] hover:text-white"
              >
                <ArrowLeft className="h-4 w-4" />
                Вернуться к ссылкам
              </button>

              <div>
                <h1
                  className={cn(
                    'max-w-full text-2xl font-bold tracking-tight text-white sm:text-3xl',
                    link.title ? 'break-words' : 'break-all [overflow-wrap:anywhere]'
                  )}
                >
                  {link.title || link.shortUrl}
                </h1>
                <p className="mt-1 text-sm text-gray-400">
                  Персональная аналитика переходов по ссылке: динамика кликов, география и качество трафика.
                </p>
              </div>

              {linkDescription ? (
                <p className="max-w-2xl break-words text-sm text-gray-400 [overflow-wrap:anywhere]">
                  {linkDescription}
                </p>
              ) : null}

              <div className="flex flex-wrap items-center gap-2">
                <span
                  className={cn(
                    'rounded-full border px-2.5 py-1 text-[10px] font-medium uppercase tracking-wide',
                    isAvailable
                      ? 'border-green-500/25 bg-green-500/10 text-green-300'
                      : 'border-red-500/25 bg-red-500/10 text-red-300'
                  )}
                >
                  {isAvailable ? 'Активна' : 'Недоступна'}
                </span>
                <span className="rounded-full border border-white/10 bg-white/[0.03] px-2.5 py-1 text-[10px] text-gray-300">
                  Создана: {createdAtLabel}
                </span>
                {link.expiresAt ? (
                  <span className="rounded-full border border-white/10 bg-white/[0.03] px-2.5 py-1 text-[10px] text-gray-300">
                    Срок: {expiresAtLabel}
                  </span>
                ) : null}
                {typeof link.clickLimit === 'number' && link.clickLimit > 0 ? (
                  <span className="rounded-full border border-white/10 bg-white/[0.03] px-2.5 py-1 text-[10px] text-gray-300">
                    Лимит: {clickLimitLabel}
                  </span>
                ) : null}
                {link.hasPassword ? (
                  <span className="rounded-full border border-white/10 bg-white/[0.03] px-2.5 py-1 text-[10px] text-gray-300">
                    {passwordLabel}
                  </span>
                ) : null}
                {customAliasLabel ? (
                  <span className="max-w-full break-all rounded-full border border-violet-500/25 bg-violet-500/10 px-2.5 py-1 font-mono text-[10px] text-violet-300 [overflow-wrap:anywhere]">
                    Псевдоним: {customAliasLabel}
                  </span>
                ) : null}
              </div>
            </div>

            <div ref={periodMenuRef} data-export-exclude="true" className="relative z-[180] space-y-2 xl:shrink-0">
              <button
                type="button"
                onClick={() => setIsPeriodMenuOpen((current) => !current)}
                className="inline-flex min-h-[42px] items-center gap-2.5 rounded-xl border border-white/15 bg-white/[0.03] px-4 py-2.5 text-sm font-medium text-gray-200 transition-all duration-300 hover:border-white/30 hover:bg-white/[0.08] hover:text-white"
              >
                <CalendarDays className="h-4 w-4" />
                {periodLabel}
              </button>

              <div className="flex flex-wrap items-center gap-2">
                <ExportButton
                  linkId={link.id}
                  period={String(effectivePeriod)}
                  disabled={!planFeatures.csvExport}
                  disabledReason="CSV-экспорт доступен начиная с тарифа Lite."
                />
                <ExportHtmlButton
                  linkId={link.id}
                  period={String(effectivePeriod)}
                  linkData={{
                    shortUrl: link.shortUrl,
                    longUrl: link.longUrl,
                    title: link.title,
                  }}
                  getExportNode={() => exportSectionRef.current}
                  disabled={!planFeatures.pdfExport}
                  disabledReason="HTML-экспорт доступен начиная с тарифа Pro."
                />
              </div>

              <AnimatePresence>
                {isPeriodMenuOpen ? (
                  <motion.div
                    initial={{ opacity: 0, y: 8, scale: 0.98 }}
                    animate={{ opacity: 1, y: 0, scale: 1 }}
                    exit={{ opacity: 0, y: 8, scale: 0.98 }}
                    transition={{ duration: 0.15 }}
                    className="absolute right-0 top-[calc(100%+6px)] z-[220] mt-1 w-64 rounded-xl border border-white/10 bg-[#0E0E0E]/95 p-2 shadow-[0_14px_44px_rgba(0,0,0,0.55)] backdrop-blur-md"
                  >
                    {STATS_PERIOD_OPTIONS.map((value) => {
                      const menuLabel = `За последние ${value} ${pluralizeDays(value)}`;
                      const isAllowed = availablePeriodSet.has(value);
                      const active = value === effectivePeriod;

                      return (
                        <button
                          key={value}
                          type="button"
                          onClick={() => {
                            if (!isAllowed) {
                              toast.info('На вашем тарифе этот период недоступен');
                              setIsPeriodMenuOpen(false);
                              return;
                            }
                            setPeriod(value);
                            setIsPeriodMenuOpen(false);
                          }}
                          className={cn(
                            'inline-flex w-full items-center justify-between rounded-lg px-3 py-2.5 text-left text-sm transition-colors',
                            active
                              ? 'bg-violet-500/18 text-violet-100'
                              : isAllowed
                                ? 'text-gray-300 hover:bg-white/5 hover:text-white'
                                : 'text-gray-500'
                          )}
                        >
                          <span>{menuLabel}</span>
                          {!isAllowed ? <span className="text-[11px] text-gray-500">Недоступно</span> : null}
                        </button>
                      );
                    })}
                  </motion.div>
                ) : null}
              </AnimatePresence>
            </div>
          </div>
        </div>

        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2 }}
            whileHover={{ y: -2 }}
            className="rounded-2xl border border-white/10 bg-black/40 p-5 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.03]"
          >
            <div className="mb-3 flex items-center justify-between">
              <span className="inline-flex h-9 w-9 items-center justify-center rounded-xl border border-violet-500/20 bg-violet-500/20 text-violet-300">
                <TrendingUp className="h-5 w-5" />
              </span>
              <span className={cn('text-xs font-mono', totalTrendClass)}>
                {stats.percentChange > 0 ? '+' : ''}
                {stats.percentChange}%
              </span>
            </div>
            <p className="mb-1 text-xs text-gray-500">Клики за период</p>
            <p className="text-2xl font-mono tracking-tight text-white sm:text-3xl">{stats.totalClicks.toLocaleString('ru-RU')}</p>
          </motion.div>

          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.04 }}
            whileHover={{ y: -2 }}
            className="rounded-2xl border border-white/10 bg-black/40 p-5 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.03]"
          >
            <div className="mb-3 flex items-center justify-between">
              <span className="inline-flex h-9 w-9 items-center justify-center rounded-xl border border-blue-500/20 bg-blue-500/20 text-blue-300">
                <Users className="h-5 w-5" />
              </span>
              <span className="text-xs text-gray-500">{periodShortLabel}</span>
            </div>
            <p className="mb-1 text-xs text-gray-500">Уникальные клики</p>
            <p className="text-2xl font-mono tracking-tight text-white sm:text-3xl">{stats.uniqueClicks.toLocaleString('ru-RU')}</p>
            <p className="mt-1 text-xs text-green-400">{uniqueShare}% от всех кликов</p>
          </motion.div>

          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.08 }}
            whileHover={{ y: -2 }}
            className="rounded-2xl border border-white/10 bg-black/40 p-5 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.03]"
          >
            <div className="mb-3 flex items-center justify-between">
              <span className="inline-flex h-9 w-9 items-center justify-center rounded-xl border border-yellow-500/20 bg-yellow-500/20 text-yellow-300">
                <ShieldAlert className="h-5 w-5" />
              </span>
              <span className="text-xs text-gray-500">Фильтры</span>
            </div>
            <p className="mb-1 text-xs text-gray-500">Отфильтрованные</p>
            <p className="text-2xl font-mono tracking-tight text-white sm:text-3xl">{stats.filteredClicks.toLocaleString('ru-RU')}</p>
          </motion.div>

          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.12 }}
            whileHover={{ y: -2 }}
            className="rounded-2xl border border-white/10 bg-black/40 p-5 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.03]"
          >
            <div className="mb-3 flex items-center justify-between">
              <span className="inline-flex h-9 w-9 items-center justify-center rounded-xl border border-fuchsia-500/20 bg-fuchsia-500/20 text-fuchsia-300">
                <Bot className="h-5 w-5" />
              </span>
              <span className="text-xs text-gray-500">Анти-бот</span>
            </div>
            <p className="mb-1 text-xs text-gray-500">Подозрительный трафик</p>
            <p className="text-2xl font-mono tracking-tight text-white sm:text-3xl">{suspiciousTraffic.toLocaleString('ru-RU')}</p>
          </motion.div>
        </div>

        <div className="grid grid-cols-1 gap-4 xl:grid-cols-2">
          <motion.div
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.16 }}
            className="rounded-2xl border border-white/10 bg-black/35 p-5 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.03]"
          >
            <div className="mb-4 flex items-center gap-2">
              <CalendarDays className="h-4 w-4 text-violet-300" />
              <p className="text-sm text-gray-200">Клики по дням</p>
            </div>
            {overviewChartData.length > 0 ? (
              <div className="h-64 min-w-0">
                <SafeResponsiveChart>
                  <AreaChart data={chartOverviewData} margin={{ top: 10, right: 8, left: -20, bottom: 0 }}>
                    <defs>
                      <linearGradient id="linkStatsClicksGradient" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stopColor="#8b5cf6" stopOpacity={0.35} />
                        <stop offset="100%" stopColor="#8b5cf6" stopOpacity={0.02} />
                      </linearGradient>
                    </defs>
                    <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.06)" />
                    <XAxis dataKey="name" tick={{ fill: '#94a3b8', fontSize: 12 }} axisLine={false} tickLine={false} />
                    <YAxis tick={{ fill: '#94a3b8', fontSize: 12 }} axisLine={false} tickLine={false} allowDecimals={false} />
                    <Tooltip
                      cursor={{ stroke: 'rgba(255,255,255,0.18)' }}
                      contentStyle={{
                        background: 'rgba(8,8,8,0.95)',
                        border: '1px solid rgba(255,255,255,0.12)',
                        borderRadius: 10,
                        color: '#fff',
                      }}
                    />
                    <Area type="monotone" dataKey="clicks" name="Клики" stroke="#8b5cf6" strokeWidth={2.5} fillOpacity={1} fill="url(#linkStatsClicksGradient)" />
                  </AreaChart>
                </SafeResponsiveChart>
              </div>
            ) : (
              <div className="flex h-64 items-center justify-center rounded-xl border border-white/10 bg-white/[0.02]">
                <p className="text-sm text-gray-500">Нет данных по дням</p>
              </div>
            )}
          </motion.div>

          <motion.div
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.2 }}
            className="rounded-2xl border border-white/10 bg-black/35 p-5 backdrop-blur-md transition-all duration-300 hover:border-white/20 hover:bg-white/[0.03]"
          >
            <div className="mb-4 flex items-center gap-2">
              <Clock className="h-4 w-4 text-cyan-300" />
              <p className="text-sm text-gray-200">Клики по часам (24ч)</p>
            </div>
            {hourlyChartData.length > 0 ? (
              <div className="h-64 min-w-0">
                <SafeResponsiveChart>
                  <BarChart data={chartHourlyData} margin={{ top: 10, right: 0, left: -20, bottom: 0 }}>
                    <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.06)" />
                    <XAxis dataKey="name" tick={{ fill: '#94a3b8', fontSize: 11 }} axisLine={false} tickLine={false} minTickGap={18} />
                    <YAxis tick={{ fill: '#94a3b8', fontSize: 12 }} axisLine={false} tickLine={false} allowDecimals={false} />
                    <Tooltip
                      cursor={{ fill: 'rgba(255,255,255,0.05)' }}
                      contentStyle={{
                        background: 'rgba(8,8,8,0.95)',
                        border: '1px solid rgba(255,255,255,0.12)',
                        borderRadius: 10,
                        color: '#fff',
                      }}
                    />
                    <Bar dataKey="clicks" name="Клики" fill="#2AABEE" radius={[4, 4, 0, 0]} />
                  </BarChart>
                </SafeResponsiveChart>
              </div>
            ) : (
              <div className="flex h-64 items-center justify-center rounded-xl border border-white/10 bg-white/[0.02]">
                <p className="text-sm text-gray-500">Почасовая статистика пока недоступна</p>
              </div>
            )}
          </motion.div>
        </div>

        <div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.24 }}
            className="rounded-2xl border border-white/10 bg-black/35 p-4 backdrop-blur-md transition-all duration-300 hover:bg-white/[0.03]"
          >
            <p className="mb-3 flex items-center gap-2 text-sm text-gray-300">
              <Smartphone className="h-4 w-4 text-violet-300" />
              Устройства
            </p>
            <DistributionList
              items={devicesData.map((entry) => ({
                name: entry.name,
                value: entry.value,
                color: entry.color,
              }))}
              emptyText="Нет данных по устройствам"
              distributionType="device"
            />
          </motion.div>

          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.28 }}
            className="rounded-2xl border border-white/10 bg-black/35 p-4 backdrop-blur-md transition-all duration-300 hover:bg-white/[0.03]"
          >
            <p className="mb-3 flex items-center gap-2 text-sm text-gray-300">
              <Laptop className="h-4 w-4 text-violet-300" />
              Браузеры
            </p>
            <DistributionList
              items={browsersData.map((entry) => ({
                name: entry.name,
                value: entry.value,
                color: entry.color,
              }))}
              emptyText="Нет данных по браузерам"
              distributionType="browser"
            />
          </motion.div>

          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.32 }}
            className="rounded-2xl border border-white/10 bg-black/35 p-4 backdrop-blur-md transition-all duration-300 hover:bg-white/[0.03]"
          >
            <p className="mb-3 flex items-center gap-2 text-sm text-gray-300">
              <Activity className="h-4 w-4 text-violet-300" />
              Источники
            </p>
            <DistributionList
              items={sourcesData.map((entry) => ({
                name: entry.name,
                value: entry.value,
                color: entry.color,
              }))}
              emptyText="Источники появятся после переходов"
            />
          </motion.div>

          <motion.div
            layout
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.2, delay: 0.36 }}
            className="rounded-2xl border border-white/10 bg-black/35 p-4 backdrop-blur-md transition-all duration-300 hover:bg-white/[0.03]"
          >
            <p className="mb-3 flex items-center gap-2 text-sm text-gray-300">
              <Globe className="h-4 w-4 text-violet-300" />
              География
            </p>
            <DistributionList items={locationDistributionData} emptyText="Геоданные пока недоступны" />
          </motion.div>
        </div>

        <motion.div
          initial={{ opacity: 0, y: 10 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.2, delay: 0.4 }}
          className="overflow-hidden rounded-2xl border border-white/10 bg-black/35 backdrop-blur-md"
        >
          <div className="flex items-center justify-between border-b border-white/10 p-5">
            <h3 className="flex items-center gap-2 text-lg font-semibold text-white">
              <Activity className="h-5 w-5 text-green-400" />
              Последние клики
            </h3>
            <span className="text-xs text-gray-500">Показано {recentClicksData.length}</span>
          </div>
          <div className="overflow-x-auto">
            <table className="min-w-[760px] w-full text-left text-sm">
              <thead className="bg-white/[0.02] text-xs uppercase text-gray-500">
                <tr>
                  <th className="px-6 py-4 font-medium">Время</th>
                  <th className="px-6 py-4 font-medium">Страна</th>
                  <th className="px-6 py-4 font-medium">IP</th>
                  <th className="px-6 py-4 font-medium">Устройство</th>
                  <th className="px-6 py-4 font-medium">Браузер</th>
                  <th className="px-6 py-4 font-medium">Источник</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-white/5">
                {recentClicksData.length === 0 ? (
                  <tr>
                    <td colSpan={6} className="px-6 py-6 text-center text-sm text-gray-500">Нет данных</td>
                  </tr>
                ) : (
                  recentClicksData.map((entry, index) => (
                    <tr key={`${entry.ip}-${entry.time}-${index}`} className="transition-colors hover:bg-white/[0.03]">
                      <td className="whitespace-nowrap px-6 py-4 text-gray-300">{entry.time}</td>
                      <td className="whitespace-nowrap px-6 py-4 text-gray-300">{entry.country}</td>
                      <td className="whitespace-nowrap px-6 py-4 font-mono text-gray-400">{entry.ip}</td>
                      <td className="whitespace-nowrap px-6 py-4 text-gray-300">{renderDeviceValue(entry.device)}</td>
                      <td className="whitespace-nowrap px-6 py-4 text-gray-300">{renderBrowserValue(entry.browser)}</td>
                      <td className="whitespace-nowrap px-6 py-4 text-gray-500">{entry.source}</td>
                    </tr>
                  ))
                )}
              </tbody>
            </table>
          </div>
        </motion.div>

        <motion.div
          initial={{ opacity: 0, y: 10 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.2, delay: 0.44 }}
          className="overflow-hidden rounded-2xl border border-white/10 bg-black/35 backdrop-blur-md"
        >
          <div className="border-b border-white/10 bg-white/[0.02] p-5">
            <h3 className="flex items-center gap-2 text-lg font-semibold text-white">
              <Bot className="h-5 w-5 text-amber-300" />
              Проверка подозрительных переходов
            </h3>
          </div>

          <div className="grid grid-cols-1 gap-5 p-5 md:grid-cols-2">
            <div className="rounded-xl border border-white/10 bg-black/25 p-4">
              <p className="text-xs text-gray-400">Переходы от ботов</p>
              <p className="mt-2 text-2xl font-mono font-semibold text-white sm:text-3xl">{stats.botClicks.toLocaleString('ru-RU')}</p>
            </div>
            <div className="rounded-xl border border-white/10 bg-black/25 p-4">
              <p className="text-xs text-gray-400">Основная причина блокировки</p>
              <p className="mt-2 text-sm text-gray-200">
                {stats.filterReasons[0] ? getBlockReasonText(stats.filterReasons[0].reason) : 'Нет данных'}
              </p>
            </div>

            <div className="md:col-span-2">
              <h4 className="mb-3 text-sm font-medium text-white">Последние заблокированные переходы</h4>

              {stats.filteredRecentClicks.length === 0 ? (
                <div className="rounded-xl border border-white/10 bg-black/25 p-4 text-center text-sm text-gray-500">
                  За выбранный период блокировок не было
                </div>
              ) : (
                <div className="overflow-x-auto rounded-xl border border-white/10">
                  <table className="min-w-[760px] w-full text-left text-sm text-gray-300">
                    <thead className="bg-black/20 text-xs uppercase text-gray-500">
                      <tr>
                        <th className="px-4 py-3">Время</th>
                        <th className="px-4 py-3">Причина</th>
                        <th className="px-4 py-3">Браузер</th>
                        <th className="px-4 py-3">Источник</th>
                        <th className="px-4 py-3">IP</th>
                      </tr>
                    </thead>
                    <tbody className="divide-y divide-white/5">
                      {stats.filteredRecentClicks.map((entry) => (
                        <tr key={entry.id} className="transition-colors hover:bg-white/[0.02]">
                          <td className="whitespace-nowrap px-4 py-3 text-gray-300">{formatRecentClickTime(entry.createdAt)}</td>
                          <td className="px-4 py-3 text-gray-300">{getBlockReasonText(entry.filterReason)}</td>
                          <td className="px-4 py-3 text-gray-300">{entry.browser || '—'}</td>
                          <td className="px-4 py-3 text-gray-300">{entry.referer || '—'}</td>
                          <td className="px-4 py-3 font-mono text-xs text-gray-400">{entry.ipAddress || '—'}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          </div>
        </motion.div>
      </motion.section>
    </div>
  );
}
