/* eslint-disable react-hooks/exhaustive-deps, @typescript-eslint/no-explicit-any,@typescript-eslint/no-non-null-assertion,no-empty */
'use client';

import {
  ChevronUp,
  Film,
  Grid2x2,
  HardDrive,
  List,
  Magnet,
  RefreshCw,
  Search,
  X,
} from 'lucide-react';
import { useRouter, useSearchParams } from 'next/navigation';
import React, {
  startTransition,
  Suspense,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';

import { getAuthInfoFromBrowserCookie } from '@/lib/auth';
import {
  addSearchHistory,
  clearSearchHistory,
  deleteSearchHistory,
  getSearchHistory,
  subscribeToDataUpdates,
} from '@/lib/db.client';
import { SearchResult } from '@/lib/types';
import { processImageUrl } from '@/lib/utils';

import AcgSearch from '@/components/AcgSearch';
import CapsuleSwitch from '@/components/CapsuleSwitch';
import ImageViewer from '@/components/ImageViewer';
import PageLayout from '@/components/PageLayout';
import PansouSearch from '@/components/PansouSearch';
import ProxyImage from '@/components/ProxyImage';
import SearchResultFilter, {
  SearchFilterCategory,
} from '@/components/SearchResultFilter';
import SearchSuggestions from '@/components/SearchSuggestions';
import VideoCard, { VideoCardHandle } from '@/components/VideoCard';
import VirtualScrollableGrid from '@/components/VirtualScrollableGrid';

function SearchPageClient() {
  // 搜索历史
  const [searchHistory, setSearchHistory] = useState<string[]>([]);
  // 返回顶部按钮显示状态
  const [showBackToTop, setShowBackToTop] = useState(false);
  // 选项卡状态: 'video' 或 'pansou' 或 'acg'
  const [activeTab, setActiveTab] = useState<'video' | 'pansou' | 'acg'>(
    'video'
  );
  // Pansou 搜索触发标志
  const [triggerPansouSearch, setTriggerPansouSearch] = useState(false);
  // ACG 搜索触发标志
  const [triggerAcgSearch, setTriggerAcgSearch] = useState(false);
  // 用户权限
  const [userRole, setUserRole] = useState<'owner' | 'admin' | 'user' | null>(
    null
  );
  // 繁体转简体转换器
  const converterRef = useRef<((text: string) => string) | null>(null);
  // 转换器是否已初始化
  const [converterReady, setConverterReady] = useState(false);

  const router = useRouter();
  const searchParams = useSearchParams();
  const submittedSearchQuery = searchParams.get('q')?.trim() || '';
  const currentQueryRef = useRef<string>('');
  const [searchQuery, setSearchQuery] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [showResults, setShowResults] = useState(false);
  const [searchResults, setSearchResults] = useState<SearchResult[]>([]);
  const [showSuggestions, setShowSuggestions] = useState(false);
  const eventSourceRef = useRef<EventSource | null>(null);
  const [totalSources, setTotalSources] = useState(0);
  const [completedSources, setCompletedSources] = useState(0);
  const pendingResultsRef = useRef<SearchResult[]>([]);
  const flushTimerRef = useRef<number | null>(null);
  const [useFluidSearch, setUseFluidSearch] = useState(true);
  // 聚合卡片 refs 与聚合统计缓存
  const groupRefs = useRef<Map<string, React.RefObject<VideoCardHandle>>>(
    new Map()
  );
  const groupStatsRef = useRef<
    Map<
      string,
      { douban_id?: number; episodes?: number; source_names: string[] }
    >
  >(new Map());
  // 强制刷新状态
  const [forceRefresh, setForceRefresh] = useState(false);
  // 是否使用了缓存结果
  const [isFromCache, setIsFromCache] = useState(false);
  // 精确搜索开关
  const [exactSearch, setExactSearch] = useState(true);

  // 生成缓存键
  const getCacheKey = (query: string) => {
    return `search_cache_${query.trim()}`;
  };

  // 从 sessionStorage 获取缓存的搜索结果
  const getCachedResults = (query: string): SearchResult[] | null => {
    if (typeof window === 'undefined') return null;
    try {
      const cacheKey = getCacheKey(query);
      const cached = sessionStorage.getItem(cacheKey);
      if (cached) {
        return JSON.parse(cached);
      }
    } catch (error) {
      console.error('Failed to get cached results:', error);
    }
    return null;
  };

  // 保存搜索结果到 sessionStorage
  const setCachedResults = (query: string, results: SearchResult[]) => {
    if (typeof window === 'undefined') return;
    try {
      const cacheKey = getCacheKey(query);
      sessionStorage.setItem(cacheKey, JSON.stringify(results));
    } catch (error) {
      console.error('Failed to cache results:', error);
    }
  };

  // 清除指定查询的缓存
  const clearCachedResults = (query: string) => {
    if (typeof window === 'undefined') return;
    try {
      const cacheKey = getCacheKey(query);
      sessionStorage.removeItem(cacheKey);
    } catch (error) {
      console.error('Failed to clear cached results:', error);
    }
  };

  const getGroupRef = (key: string) => {
    let ref = groupRefs.current.get(key);
    if (!ref) {
      ref = React.createRef<VideoCardHandle>();
      groupRefs.current.set(key, ref);
    }
    return ref;
  };

  const computeGroupStats = (group: SearchResult[]) => {
    const episodes = (() => {
      const countMap = new Map<number, number>();
      group.forEach((g) => {
        const len = g.episodes?.length || 0;
        if (len > 0) countMap.set(len, (countMap.get(len) || 0) + 1);
      });
      let max = 0;
      let res = 0;
      countMap.forEach((v, k) => {
        if (v > max) {
          max = v;
          res = k;
        }
      });
      return res;
    })();
    const source_names = Array.from(
      new Set(group.map((g) => g.source_name).filter(Boolean))
    ) as string[];

    const douban_id = (() => {
      const countMap = new Map<number, number>();
      group.forEach((g) => {
        if (g.douban_id && g.douban_id > 0) {
          countMap.set(g.douban_id, (countMap.get(g.douban_id) || 0) + 1);
        }
      });
      let max = 0;
      let res: number | undefined;
      countMap.forEach((v, k) => {
        if (v > max) {
          max = v;
          res = k;
        }
      });
      return res;
    })();

    return { episodes, source_names, douban_id };
  };
  // 过滤器：非聚合与聚合
  const [filterAll, setFilterAll] = useState<{
    source: string;
    title: string;
    year: string;
    yearOrder: 'none' | 'asc' | 'desc';
  }>({
    source: 'all',
    title: 'all',
    year: 'all',
    yearOrder: 'none',
  });
  const [filterAgg, setFilterAgg] = useState<{
    source: string;
    title: string;
    year: string;
    yearOrder: 'none' | 'asc' | 'desc';
  }>({
    source: 'all',
    title: 'all',
    year: 'all',
    yearOrder: 'none',
  });

  // 获取默认聚合设置：只读取用户本地设置，默认为 true
  const getDefaultAggregate = () => {
    if (typeof window !== 'undefined') {
      const userSetting = localStorage.getItem('defaultAggregateSearch');
      if (userSetting !== null) {
        return JSON.parse(userSetting);
      }
    }
    return true; // 默认启用聚合
  };

  const [viewMode, setViewMode] = useState<'agg' | 'all'>(() => {
    return getDefaultAggregate() ? 'agg' : 'all';
  });
  const [resultDisplayMode, setResultDisplayMode] = useState<'card' | 'list'>(
    () => {
      if (typeof window !== 'undefined') {
        const saved = localStorage.getItem('searchResultDisplayMode');
        if (saved === 'card' || saved === 'list') {
          return saved;
        }
      }
      return 'card';
    }
  );
  const [expandedSourceTags, setExpandedSourceTags] = useState<
    Record<string, boolean>
  >({});
  const [previewImage, setPreviewImage] = useState<{
    url: string;
    alt: string;
  } | null>(null);

  // 在“无排序”场景用于每个源批次的预排序：完全匹配标题优先，其次年份倒序，未知年份最后
  const sortBatchForNoOrder = (items: SearchResult[]) => {
    const q = currentQueryRef.current.trim();
    return items.slice().sort((a, b) => {
      const aExact = (a.title || '').trim() === q;
      const bExact = (b.title || '').trim() === q;
      if (aExact && !bExact) return -1;
      if (!aExact && bExact) return 1;

      const aNum = Number.parseInt(a.year as any, 10);
      const bNum = Number.parseInt(b.year as any, 10);
      const aValid = !Number.isNaN(aNum);
      const bValid = !Number.isNaN(bNum);
      if (aValid && !bValid) return -1;
      if (!aValid && bValid) return 1;
      if (aValid && bValid) return bNum - aNum; // 年份倒序
      return 0;
    });
  };

  // 简化的年份排序：unknown/空值始终在最后
  const compareYear = (
    aYear: string,
    bYear: string,
    order: 'none' | 'asc' | 'desc'
  ) => {
    // 如果是无排序状态，返回0（保持原顺序）
    if (order === 'none') return 0;

    // 处理空值和unknown
    const aIsEmpty = !aYear || aYear === 'unknown';
    const bIsEmpty = !bYear || bYear === 'unknown';

    if (aIsEmpty && bIsEmpty) return 0;
    if (aIsEmpty) return 1; // a 在后
    if (bIsEmpty) return -1; // b 在后

    // 都是有效年份，按数字比较
    const aNum = parseInt(aYear, 10);
    const bNum = parseInt(bYear, 10);

    return order === 'asc' ? aNum - bNum : bNum - aNum;
  };

  // 规范化标题用于聚合（去除特殊符号、括号、空格和全角空格）
  const normalizeTitle = (title: string) => {
    return title
      .replace(/[\s\u3000]/g, '') // 去除空格和全角空格
      .replace(/[()（）[\]【】{}「」『』<>《》]/g, '') // 去除各种括号
      .replace(/[^\w\u4e00-\u9fa5]/g, ''); // 去除特殊符号，保留字母、数字、下划线和中文
  };

  // 辅助函数：获取视频类型
  const getType = (item: SearchResult): 'movie' | 'tv' => {
    // 1. Emby 和 OpenList 源：使用 type_name（基于 TMDB，最可靠）
    if (
      item.source === 'emby' ||
      item.source?.startsWith('emby_') ||
      item.source === 'openlist'
    ) {
      return item.type_name === '电影' ? 'movie' : 'tv';
    }

    // 2. API 采集源：综合判断
    const typeName = item.type_name?.toLowerCase() || '';

    // 2.1 明确包含"电影"或"movie"或"片"的，判断为电影
    if (
      typeName.includes('电影') ||
      typeName.includes('movie') ||
      (typeName.endsWith('片') && !typeName.includes('动漫'))
    ) {
      return 'movie';
    }

    // 2.2 包含"剧"、"动漫"、"综艺"等关键词的，判断为剧集
    if (
      typeName.includes('剧') ||
      typeName.includes('动漫') ||
      typeName.includes('综艺') ||
      typeName.includes('anime')
    ) {
      return 'tv';
    }

    // 2.3 检查 episodes_titles：如果包含"第X集"，判断为剧集
    if (item.episodes_titles && item.episodes_titles.length > 0) {
      const firstTitle = item.episodes_titles[0] || '';
      if (/第\d+集|第\d+话|EP?\d+/i.test(firstTitle)) {
        return 'tv';
      }
    }

    // 2.4 兜底：使用 episodes.length（最不可靠）
    return item.episodes.length === 1 ? 'movie' : 'tv';
  };

  // 辅助函数：检查标题是否包含搜索词（用于精确搜索）
  const titleContainsQuery = (title: string, query: string): boolean => {
    if (!exactSearch) return true; // 如果未开启精确搜索，不过滤
    if (!query || !title) return true; // 如果没有搜索词或标题，不过滤

    const normalizedTitle = title.toLowerCase();
    const normalizedQuery = query.toLowerCase();

    return normalizedTitle.includes(normalizedQuery);
  };

  const allExactSearchResults = useMemo(() => {
    if (!exactSearch) return searchResults;

    return searchResults.filter((item) =>
      titleContainsQuery(item.title, submittedSearchQuery)
    );
  }, [searchResults, submittedSearchQuery, exactSearch]);

  // 聚合后的结果（按标题和年份分组）
  const aggregatedResults = useMemo(() => {
    //===== 阶段1：按 normalizedTitle-type 初步分组 =====
    const preliminaryMap = new Map<string, SearchResult[]>();

    allExactSearchResults.forEach((item) => {
      const normalizedTitle = normalizeTitle(item.title);
      const type = getType(item);
      const preliminaryKey = `${normalizedTitle}-${type}`;

      const arr = preliminaryMap.get(preliminaryKey) || [];
      arr.push(item);
      preliminaryMap.set(preliminaryKey, arr);
    });

    //===== 阶段2：智能年份推断和最终分组 =====
    const finalMap = new Map<string, SearchResult[]>();
    const keyOrder: string[] = [];

    preliminaryMap.forEach((group, preliminaryKey) => {
      // 分离有年份和无年份的结果
      const withYear = new Map<string, SearchResult[]>();
      const withoutYear: SearchResult[] = [];

      group.forEach((item) => {
        const year = item.year;

        // 判断是否为有效年份：必须是4位数字，且不能是空字符串或'unknown'
        if (
          year &&
          year.trim() !== '' &&
          year !== 'unknown' &&
          /^\d{4}$/.test(year)
        ) {
          // 有有效年份
          const arr = withYear.get(year) || [];
          arr.push(item);
          withYear.set(year, arr);
        } else {
          // 无年份（包括空字符串、'unknown'、null、undefined等）
          withoutYear.push(item);
        }
      });

      // 如果有有效年份组
      if (withYear.size > 0) {
        // 将无年份的结果复制到每个有年份的组中
        withYear.forEach((yearGroup, year) => {
          const finalKey = `${preliminaryKey}-${year}`;
          // 合并：有年份的 + 无年份的（复制）
          const mergedGroup = [...yearGroup, ...withoutYear];
          finalMap.set(finalKey, mergedGroup);
          keyOrder.push(finalKey);
        });
      } else if (withoutYear.length > 0) {
        // 如果完全没有年份信息，单独成组
        const finalKey = `${preliminaryKey}-unknown`;
        finalMap.set(finalKey, withoutYear);
        keyOrder.push(finalKey);
      }
    });

    // 按出现顺序返回聚合结果
    return keyOrder.map(
      (key) => [key, finalMap.get(key)!] as [string, SearchResult[]]
    );
  }, [allExactSearchResults]);

  // 当聚合结果变化时，如果某个聚合已存在，则调用其卡片 ref 的 set 方法增量更新
  useEffect(() => {
    aggregatedResults.forEach(([mapKey, group]) => {
      const stats = computeGroupStats(group);
      const prev = groupStatsRef.current.get(mapKey);
      if (!prev) {
        // 第一次出现，记录初始值，不调用 ref（由初始 props 渲染）
        groupStatsRef.current.set(mapKey, stats);
        return;
      }
      // 对比变化并调用对应的 set 方法
      const ref = groupRefs.current.get(mapKey);
      if (ref && ref.current) {
        if (prev.episodes !== stats.episodes) {
          ref.current.setEpisodes(stats.episodes);
        }
        const prevNames = (prev.source_names || []).join('|');
        const nextNames = (stats.source_names || []).join('|');
        if (prevNames !== nextNames) {
          ref.current.setSourceNames(stats.source_names);
        }
        if (prev.douban_id !== stats.douban_id) {
          ref.current.setDoubanId(stats.douban_id);
        }
        groupStatsRef.current.set(mapKey, stats);
      }
    });
  }, [aggregatedResults]);

  // 构建筛选选项
  const filterOptions = useMemo(() => {
    const exactSearchFiltered = exactSearch
      ? searchResults.filter((item) =>
          titleContainsQuery(item.title, currentQueryRef.current)
        )
      : searchResults;

    const buildSourceOptions = (
      sourceEntries: Array<{ source: string; source_name: string }>
    ) => [
      { label: '全部来源', value: 'all' },
      ...Array.from(
        new Map(
          sourceEntries
            .filter(
              (item) =>
                item.source &&
                item.source_name &&
                item.source.trim() !== '' &&
                item.source_name.trim() !== ''
            )
            .map((item) => [item.source, item.source_name])
        ).entries()
      )
        .sort((a, b) => {
          const aIsOpenList = a[0] === 'openlist';
          const bIsOpenList = b[0] === 'openlist';
          const aIsEmby = a[0] === 'emby' || a[0].startsWith('emby_');
          const bIsEmby = b[0] === 'emby' || b[0].startsWith('emby_');

          const aPriority = aIsOpenList ? 100 : aIsEmby ? 90 : 0;
          const bPriority = bIsOpenList ? 100 : bIsEmby ? 90 : 0;

          if (aPriority !== bPriority) {
            return bPriority - aPriority;
          }

          return a[1].localeCompare(b[1]);
        })
        .map(([value, label]) => ({ label, value })),
    ];

    const buildTitleOptions = (titles: string[]) => [
      { label: '全部标题', value: 'all' },
      ...Array.from(new Set(titles))
        .filter((title) => title && title.trim() !== '')
        .sort((a, b) => a.localeCompare(b))
        .map((title) => ({ label: title, value: title })),
    ];

    const buildYearOptions = (years: string[]) => {
      const yearSet = Array.from(
        new Set(years.filter((year) => year && year.trim() !== ''))
      );
      const knownYears = yearSet
        .filter((year) => year !== 'unknown')
        .sort((a, b) => parseInt(b) - parseInt(a));
      const hasUnknown = yearSet.includes('unknown');

      return [
        { label: '全部年份', value: 'all' },
        ...knownYears.map((year) => ({ label: year, value: year })),
        ...(hasUnknown ? [{ label: '未知', value: 'unknown' }] : []),
      ];
    };

    const allForSourceOptions = exactSearchFiltered.filter((item) => {
      if (filterAll.title !== 'all' && item.title !== filterAll.title)
        return false;
      if (filterAll.year !== 'all' && item.year !== filterAll.year)
        return false;
      return true;
    });

    const allForTitleOptions = exactSearchFiltered.filter((item) => {
      if (filterAll.source !== 'all' && item.source !== filterAll.source)
        return false;
      if (filterAll.year !== 'all' && item.year !== filterAll.year)
        return false;
      return true;
    });

    const allForYearOptions = exactSearchFiltered.filter((item) => {
      if (filterAll.source !== 'all' && item.source !== filterAll.source)
        return false;
      if (filterAll.title !== 'all' && item.title !== filterAll.title)
        return false;
      return true;
    });

    const aggForSourceOptions = aggregatedResults.filter(([_, group]) => {
      const gTitle = group[0]?.title ?? '';
      const gYear = group[0]?.year ?? 'unknown';
      if (filterAgg.title !== 'all' && gTitle !== filterAgg.title) return false;
      if (filterAgg.year !== 'all' && gYear !== filterAgg.year) return false;
      return true;
    });

    const aggForTitleOptions = aggregatedResults.filter(([_, group]) => {
      const gYear = group[0]?.year ?? 'unknown';
      const hasSource =
        filterAgg.source === 'all'
          ? true
          : group.some((item) => item.source === filterAgg.source);
      if (!hasSource) return false;
      if (filterAgg.year !== 'all' && gYear !== filterAgg.year) return false;
      return true;
    });

    const aggForYearOptions = aggregatedResults.filter(([_, group]) => {
      const gTitle = group[0]?.title ?? '';
      const hasSource =
        filterAgg.source === 'all'
          ? true
          : group.some((item) => item.source === filterAgg.source);
      if (!hasSource) return false;
      if (filterAgg.title !== 'all' && gTitle !== filterAgg.title) return false;
      return true;
    });

    const categoriesAll: SearchFilterCategory[] = [
      {
        key: 'source',
        label: '来源',
        options: buildSourceOptions(
          allForSourceOptions.map((item) => ({
            source: item.source,
            source_name: item.source_name,
          }))
        ),
      },
      {
        key: 'title',
        label: '标题',
        options: buildTitleOptions(
          allForTitleOptions.map((item) => item.title)
        ),
      },
      {
        key: 'year',
        label: '年份',
        options: buildYearOptions(allForYearOptions.map((item) => item.year)),
      },
    ];

    const categoriesAgg: SearchFilterCategory[] = [
      {
        key: 'source',
        label: '来源',
        options: buildSourceOptions(
          aggForSourceOptions.flatMap(([_, group]) =>
            group.map((item) => ({
              source: item.source,
              source_name: item.source_name,
            }))
          )
        ),
      },
      {
        key: 'title',
        label: '标题',
        options: buildTitleOptions(
          aggForTitleOptions.map(([_, group]) => group[0]?.title ?? '')
        ),
      },
      {
        key: 'year',
        label: '年份',
        options: buildYearOptions(
          aggForYearOptions.map(([_, group]) => group[0]?.year ?? 'unknown')
        ),
      },
    ];

    return { categoriesAll, categoriesAgg };
  }, [searchResults, aggregatedResults, exactSearch, filterAll, filterAgg]);

  // 非聚合：应用筛选与排序
  const filteredAllResults = useMemo(() => {
    const { source, title, year, yearOrder } = filterAll;

    const filtered = allExactSearchResults.filter((item) => {
      if (source !== 'all' && item.source !== source) return false;
      if (title !== 'all' && item.title !== title) return false;
      if (year !== 'all' && item.year !== year) return false;
      return true;
    });

    // 如果是无排序状态，直接返回过滤后的原始顺序
    if (yearOrder === 'none') {
      return filtered;
    }

    // 简化排序：1. 年份排序，2. 年份相同时精确匹配在前，3. 标题排序
    return filtered.sort((a, b) => {
      // 首先按年份排序
      const yearComp = compareYear(a.year, b.year, yearOrder);
      if (yearComp !== 0) return yearComp;

      // 年份相同时，精确匹配在前
      const aExactMatch = a.title === searchQuery.trim();
      const bExactMatch = b.title === searchQuery.trim();
      if (aExactMatch && !bExactMatch) return -1;
      if (!aExactMatch && bExactMatch) return 1;

      // 最后按标题排序，正序时字母序，倒序时反字母序
      return yearOrder === 'asc'
        ? a.title.localeCompare(b.title)
        : b.title.localeCompare(a.title);
    });
  }, [allExactSearchResults, filterAll, searchQuery]);

  // 聚合：应用筛选与排序
  const filteredAggResults = useMemo(() => {
    const { source, title, year, yearOrder } = filterAgg as any;
    const filtered = aggregatedResults.filter(([_, group]) => {
      const gTitle = group[0]?.title ?? '';
      const gYear = group[0]?.year ?? 'unknown';
      const hasSource =
        source === 'all' ? true : group.some((item) => item.source === source);
      if (!hasSource) return false;
      if (title !== 'all' && gTitle !== title) return false;
      if (year !== 'all' && gYear !== year) return false;
      return true;
    });

    // 如果是无排序状态，保持按关键字+年份+类型出现的原始顺序
    if (yearOrder === 'none') {
      return filtered;
    }

    // 简化排序：1. 年份排序，2. 年份相同时精确匹配在前，3. 标题排序
    return filtered.sort((a, b) => {
      // 首先按年份排序
      const aYear = a[1][0].year;
      const bYear = b[1][0].year;
      const yearComp = compareYear(aYear, bYear, yearOrder);
      if (yearComp !== 0) return yearComp;

      // 年份相同时，精确匹配在前
      const aExactMatch = a[1][0].title === searchQuery.trim();
      const bExactMatch = b[1][0].title === searchQuery.trim();
      if (aExactMatch && !bExactMatch) return -1;
      if (!aExactMatch && bExactMatch) return 1;

      // 最后按标题排序，正序时字母序，倒序时反字母序
      const aTitle = a[1][0].title;
      const bTitle = b[1][0].title;
      return yearOrder === 'asc'
        ? aTitle.localeCompare(bTitle)
        : bTitle.localeCompare(aTitle);
    });
  }, [aggregatedResults, filterAgg, searchQuery]);

  const useVirtualGrid = useMemo(() => {
    const cardCount =
      viewMode === 'agg'
        ? filteredAggResults.length
        : filteredAllResults.length;
    return resultDisplayMode === 'card' && cardCount >= 100;
  }, [
    viewMode,
    resultDisplayMode,
    filteredAggResults.length,
    filteredAllResults.length,
  ]);

  const resultCountMeta = useMemo(() => {
    const isAggregateView = viewMode === 'agg';
    const visibleCount = isAggregateView
      ? filteredAggResults.length
      : filteredAllResults.length;
    const totalCount = isAggregateView
      ? aggregatedResults.length
      : allExactSearchResults.length;

    return {
      visibleCount,
      totalCount,
      isFiltered: visibleCount !== totalCount,
      modeLabel: isAggregateView ? '聚合结果' : '搜索结果',
      unit: isAggregateView ? '组' : '条',
    };
  }, [
    viewMode,
    filteredAggResults.length,
    filteredAllResults.length,
    aggregatedResults.length,
    allExactSearchResults.length,
  ]);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem('searchResultDisplayMode', resultDisplayMode);
    }
  }, [resultDisplayMode]);

  const getSearchResultUrl = (params: {
    title: string;
    year?: string;
    type?: string;
    source?: string;
    id?: string;
    query?: string;
    isAggregate?: boolean;
  }) => {
    const yearParam =
      params.year && params.year !== 'unknown' ? `&year=${params.year}` : '';
    const queryParam = params.query
      ? `&stitle=${encodeURIComponent(params.query.trim())}`
      : '';
    const typeParam = params.type ? `&stype=${params.type}` : '';
    const preferParam = params.isAggregate ? '&prefer=true' : '';

    if (params.isAggregate || !params.source || !params.id) {
      return `/play?title=${encodeURIComponent(
        params.title.trim()
      )}${yearParam}${typeParam}${preferParam}${queryParam}`;
    }

    return `/play?source=${params.source}&id=${
      params.id
    }&title=${encodeURIComponent(
      params.title.trim()
    )}${yearParam}${preferParam}${queryParam}${typeParam}`;
  };

  const renderTag = (label: string, className: string) => (
    <span
      className={`inline-flex items-center rounded-full px-2 py-1 text-[11px] font-medium ${className}`}
    >
      {label}
    </span>
  );

  const renderListItem = (item: {
    key: string;
    title: string;
    poster: string;
    year?: string;
    type: 'movie' | 'tv';
    episodes?: number;
    sourceName?: string;
    sourceNames?: string[];
    doubanId?: number;
    desc?: string;
    vodRemarks?: string;
    isAggregate?: boolean;
    source?: string;
    id?: string;
    query?: string;
  }) => {
    const yearText = item.year && item.year !== 'unknown' ? item.year : '';
    const sourceTags = item.isAggregate
      ? Array.from(new Set(item.sourceNames || []))
      : item.sourceName
      ? [item.sourceName]
      : [];
    const isExpanded = !!expandedSourceTags[item.key];
    const maxVisibleSourceTags = 3;
    const visibleSourceTags = isExpanded
      ? sourceTags
      : sourceTags.slice(0, maxVisibleSourceTags);
    const hiddenSourceCount = Math.max(
      0,
      sourceTags.length - visibleSourceTags.length
    );
    const description = (item.desc || '').trim();
    const itemUrl = getSearchResultUrl({
      title: item.title,
      year: item.year,
      type: item.type,
      source: item.source,
      id: item.id,
      query: item.query,
      isAggregate: item.isAggregate,
    });

    return (
      <button
        key={item.key}
        type='button'
        onClick={() => router.push(itemUrl)}
        className='group w-full rounded-2xl border border-gray-200/80 bg-white/90 p-3 text-left shadow-sm transition-all hover:border-green-300 hover:shadow-md dark:border-gray-700 dark:bg-gray-900/70 dark:hover:border-green-700'
      >
        <div className='flex items-start gap-4'>
          <div className='relative h-32 w-24 shrink-0 overflow-hidden rounded-xl bg-gray-100 dark:bg-gray-800'>
            <ProxyImage
              originalSrc={item.poster}
              alt={item.title}
              className='h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.04]'
              loading='lazy'
              onClick={(e) => {
                e.stopPropagation();
                setPreviewImage({
                  url: processImageUrl(item.poster),
                  alt: item.title,
                });
              }}
            />
          </div>

          <div className='min-w-0 flex-1'>
            <div className='flex items-start justify-between gap-3'>
              <div className='min-w-0'>
                <h3 className='line-clamp-2 text-base font-semibold text-gray-900 dark:text-gray-100'>
                  {item.title}
                </h3>
                <div className='mt-2 flex flex-wrap gap-2'>
                  {renderTag(
                    item.type === 'movie' ? '电影' : '剧集',
                    'bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-300'
                  )}
                  {yearText &&
                    renderTag(
                      yearText,
                      'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300'
                    )}
                  {item.episodes &&
                    item.episodes > 0 &&
                    renderTag(
                      `${item.episodes}集`,
                      'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300'
                    )}
                  {item.vodRemarks &&
                    renderTag(
                      item.vodRemarks,
                      'bg-amber-50 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300'
                    )}
                  {item.doubanId &&
                    item.doubanId > 0 &&
                    renderTag(
                      '豆瓣',
                      'bg-emerald-50 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300'
                    )}
                </div>
              </div>
            </div>

            {description && (
              <p className='mt-3 line-clamp-3 text-sm leading-6 text-gray-600 dark:text-gray-400'>
                {description}
              </p>
            )}
          </div>
        </div>

        {sourceTags.length > 0 && (
          <div
            className={`mt-3 flex gap-2 ${
              isExpanded ? 'flex-wrap' : 'flex-nowrap overflow-hidden'
            }`}
          >
            {visibleSourceTags.map((sourceName) => (
              <span
                key={`${item.key}-${sourceName}`}
                className='inline-flex max-w-full shrink-0 items-center truncate rounded-full border border-gray-200 bg-gray-50 px-2.5 py-1 text-xs text-gray-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300'
                title={sourceName}
              >
                {sourceName}
              </span>
            ))}
            {hiddenSourceCount > 0 && (
              <button
                type='button'
                onClick={(e) => {
                  e.stopPropagation();
                  setExpandedSourceTags((prev) => ({
                    ...prev,
                    [item.key]: true,
                  }));
                }}
                className='inline-flex shrink-0 items-center rounded-full border border-green-200 bg-green-50 px-2.5 py-1 text-xs font-medium text-green-700 transition-colors hover:bg-green-100 dark:border-green-800 dark:bg-green-900/30 dark:text-green-300 dark:hover:bg-green-900/50'
                aria-label={`展开剩余${hiddenSourceCount}个来源`}
              >
                +{hiddenSourceCount}
              </button>
            )}
          </div>
        )}
      </button>
    );
  };

  // 监听选项卡切换，自动执行搜索
  useEffect(() => {
    // 如果切换到网盘搜索选项卡，且有搜索关键词，且已显示结果，则触发搜索
    if (activeTab === 'pansou' && searchQuery.trim() && showResults) {
      setTriggerPansouSearch((prev) => !prev);
    }
    // 如果切换到 ACG 磁力搜索选项卡，且有搜索关键词，且已显示结果，则触发搜索
    if (activeTab === 'acg' && searchQuery.trim() && showResults) {
      setTriggerAcgSearch((prev) => !prev);
    }
  }, [activeTab]);

  useEffect(() => {
    // 从 URL 读取搜索类型参数
    const typeParam = searchParams.get('type');
    const query = searchParams.get('q');

    if (typeParam === 'pansou' || typeParam === 'acg') {
      setActiveTab(typeParam);

      // 如果有搜索关键词且显示结果，触发对应的搜索
      if (query && query.trim()) {
        setSearchQuery(query);
        setShowResults(true);

        // 延迟触发搜索，确保组件已经切换到正确的标签页
        setTimeout(() => {
          if (typeParam === 'pansou') {
            setTriggerPansouSearch((prev) => !prev);
          } else if (typeParam === 'acg') {
            setTriggerAcgSearch((prev) => !prev);
          }
        }, 100);
      }
    } else if (typeParam === 'video') {
      setActiveTab('video');
    } else if (!typeParam && query) {
      // 如果没有 type 参数但有查询，默认为 video
      setActiveTab('video');
    }

    // 无搜索参数时聚焦搜索框
    !searchParams.get('q') && document.getElementById('searchInput')?.focus();

    // 获取用户权限
    const authInfo = getAuthInfoFromBrowserCookie();
    setUserRole(authInfo?.role || null);

    // 初始化繁体转简体转换器
    if (typeof window !== 'undefined') {
      import('opencc-js')
        .then((module) => {
          try {
            const OpenCC = module.default || module;
            const converter = OpenCC.Converter({ from: 'hk', to: 'cn' });
            converterRef.current = converter;
            setConverterReady(true);
          } catch (error) {
            console.error('初始化繁体转简体转换器失败:', error);
            setConverterReady(true); // 即使失败也设置为 true，避免阻塞
          }
        })
        .catch((error) => {
          console.error('加载 opencc-js 失败:', error);
          setConverterReady(true); // 即使失败也设置为 true，避免阻塞
        });
    } else {
      setConverterReady(true);
    }

    // 初始加载搜索历史
    getSearchHistory().then(setSearchHistory);

    // 读取流式搜索设置
    if (typeof window !== 'undefined') {
      const savedFluidSearch = localStorage.getItem('fluidSearch');
      const defaultFluidSearch =
        (window as any).RUNTIME_CONFIG?.FLUID_SEARCH !== false;
      if (savedFluidSearch !== null) {
        setUseFluidSearch(JSON.parse(savedFluidSearch));
      } else if (defaultFluidSearch !== undefined) {
        setUseFluidSearch(defaultFluidSearch);
      }

      // 读取精确搜索设置
      const savedExactSearch = localStorage.getItem('exactSearch');
      if (savedExactSearch !== null) {
        setExactSearch(savedExactSearch === 'true');
      }
    }

    // 监听搜索历史更新事件
    const unsubscribe = subscribeToDataUpdates(
      'searchHistoryUpdated',
      (newHistory: string[]) => {
        setSearchHistory(newHistory);
      }
    );

    // 获取滚动位置的函数 - 专门针对 body 滚动
    const getScrollTop = () => {
      return document.body.scrollTop || 0;
    };

    // 使用 requestAnimationFrame 持续检测滚动位置
    let isRunning = false;
    const checkScrollPosition = () => {
      if (!isRunning) return;

      const scrollTop = getScrollTop();
      const shouldShow = scrollTop > 300;
      setShowBackToTop(shouldShow);

      requestAnimationFrame(checkScrollPosition);
    };

    // 启动持续检测
    isRunning = true;
    checkScrollPosition();

    // 监听 body 元素的滚动事件
    const handleScroll = () => {
      const scrollTop = getScrollTop();
      setShowBackToTop(scrollTop > 300);
    };

    document.body.addEventListener('scroll', handleScroll, { passive: true });

    return () => {
      unsubscribe();
      isRunning = false; // 停止 requestAnimationFrame 循环

      // 移除 body 滚动事件监听器
      document.body.removeEventListener('scroll', handleScroll);
    };
  }, []);

  useEffect(() => {
    // 等待转换器初始化完成
    if (!converterReady) {
      return;
    }

    // 当搜索参数变化时更新搜索状态
    let query = searchParams.get('q') || '';

    // 如果开启了繁体转简体，进行转换
    if (query && typeof window !== 'undefined') {
      const searchTraditionalToSimplified = localStorage.getItem(
        'searchTraditionalToSimplified'
      );

      if (searchTraditionalToSimplified === 'true' && converterRef.current) {
        try {
          const originalQuery = query;
          query = converterRef.current(query);

          // 如果转换后的文本与原文本不同，更新 URL
          if (originalQuery !== query) {
            const trimmedConverted = query.trim();
            // 使用 replace 而不是 push，避免在历史记录中留下繁体版本
            router.replace(
              `/search?q=${encodeURIComponent(trimmedConverted)}${
                searchParams.get('type')
                  ? `&type=${searchParams.get('type')}`
                  : ''
              }`
            );
            return; // 等待 URL 更新后重新触发此 effect
          }
        } catch (error) {
          console.error('[URL参数监听] 繁体转简体转换失败:', error);
        }
      }
    }

    currentQueryRef.current = query.trim();

    if (query) {
      setSearchQuery(query);

      const trimmed = query.trim();

      // 检查是否有缓存且不是强制刷新
      if (!forceRefresh) {
        const cachedResults = getCachedResults(trimmed);
        if (cachedResults && cachedResults.length > 0) {
          // 使用缓存的结果
          setIsLoading(false); // 先设置加载状态为 false
          setSearchResults(cachedResults);
          setShowResults(true);
          setTotalSources(1);
          setCompletedSources(1);
          setShowSuggestions(false);
          setIsFromCache(true); // 标记为缓存结果
          // 保存到搜索历史
          addSearchHistory(query);
          return;
        }
      }

      // 如果是强制刷新，清除缓存
      if (forceRefresh) {
        clearCachedResults(trimmed);
        setForceRefresh(false);
      }

      // 开始新搜索时，重置缓存标记
      setIsFromCache(false);

      // 新搜索：关闭旧连接并清空结果
      if (eventSourceRef.current) {
        try {
          eventSourceRef.current.close();
        } catch {}
        eventSourceRef.current = null;
      }
      // 先设置加载状态，再清空结果，避免短暂显示"暂无搜索结果"
      setIsLoading(true);
      setShowResults(true);
      setSearchResults([]);
      setTotalSources(0);
      setCompletedSources(0);
      // 清理缓冲
      pendingResultsRef.current = [];
      if (flushTimerRef.current) {
        clearTimeout(flushTimerRef.current);
        flushTimerRef.current = null;
      }

      // 每次搜索时重新读取设置，确保使用最新的配置
      let currentFluidSearch = useFluidSearch;
      if (typeof window !== 'undefined') {
        const savedFluidSearch = localStorage.getItem('fluidSearch');
        if (savedFluidSearch !== null) {
          currentFluidSearch = JSON.parse(savedFluidSearch);
        } else {
          const defaultFluidSearch =
            (window as any).RUNTIME_CONFIG?.FLUID_SEARCH !== false;
          currentFluidSearch = defaultFluidSearch;
        }
      }

      // 如果读取的配置与当前状态不同，更新状态
      if (currentFluidSearch !== useFluidSearch) {
        setUseFluidSearch(currentFluidSearch);
      }

      if (currentFluidSearch) {
        // 流式搜索：打开新的流式连接
        const es = new EventSource(
          `/api/search/ws?q=${encodeURIComponent(trimmed)}`
        );
        eventSourceRef.current = es;

        es.onmessage = (event) => {
          if (!event.data) return;
          try {
            const payload = JSON.parse(event.data);
            if (currentQueryRef.current !== trimmed) return;
            switch (payload.type) {
              case 'start':
                setTotalSources(payload.totalSources || 0);
                setCompletedSources(0);
                break;
              case 'source_result': {
                setCompletedSources((prev) => prev + 1);
                if (
                  Array.isArray(payload.results) &&
                  payload.results.length > 0
                ) {
                  // 缓冲新增结果，节流刷入，避免频繁重渲染导致闪烁
                  const activeYearOrder =
                    viewMode === 'agg'
                      ? filterAgg.yearOrder
                      : filterAll.yearOrder;
                  const incoming: SearchResult[] =
                    activeYearOrder === 'none'
                      ? sortBatchForNoOrder(payload.results as SearchResult[])
                      : (payload.results as SearchResult[]);
                  pendingResultsRef.current.push(...incoming);
                  if (!flushTimerRef.current) {
                    flushTimerRef.current = window.setTimeout(() => {
                      const toAppend = pendingResultsRef.current;
                      pendingResultsRef.current = [];
                      startTransition(() => {
                        setSearchResults((prev) => prev.concat(toAppend));
                      });
                      flushTimerRef.current = null;
                    }, 80);
                  }
                }
                break;
              }
              case 'source_error':
                setCompletedSources((prev) => prev + 1);
                break;
              case 'complete':
                setCompletedSources(payload.completedSources || totalSources);
                // 完成前确保将缓冲写入
                if (pendingResultsRef.current.length > 0) {
                  const toAppend = pendingResultsRef.current;
                  pendingResultsRef.current = [];
                  if (flushTimerRef.current) {
                    clearTimeout(flushTimerRef.current);
                    flushTimerRef.current = null;
                  }
                  startTransition(() => {
                    setSearchResults((prev) => {
                      const newResults = prev.concat(toAppend);
                      // 缓存完整的搜索结果
                      setCachedResults(trimmed, newResults);
                      return newResults;
                    });
                  });
                } else {
                  // 即使没有待写入的缓冲，也缓存当前结果
                  setSearchResults((prev) => {
                    setCachedResults(trimmed, prev);
                    return prev;
                  });
                }
                setIsLoading(false);
                try {
                  es.close();
                } catch {}
                if (eventSourceRef.current === es) {
                  eventSourceRef.current = null;
                }
                break;
            }
          } catch {}
        };

        es.onerror = () => {
          setIsLoading(false);
          // 错误时也清空缓冲
          if (pendingResultsRef.current.length > 0) {
            const toAppend = pendingResultsRef.current;
            pendingResultsRef.current = [];
            if (flushTimerRef.current) {
              clearTimeout(flushTimerRef.current);
              flushTimerRef.current = null;
            }
            startTransition(() => {
              setSearchResults((prev) => prev.concat(toAppend));
            });
          }
          try {
            es.close();
          } catch {}
          if (eventSourceRef.current === es) {
            eventSourceRef.current = null;
          }
        };
      } else {
        // 传统搜索：使用普通接口
        fetch(`/api/search?q=${encodeURIComponent(trimmed)}`)
          .then((response) => response.json())
          .then((data) => {
            if (currentQueryRef.current !== trimmed) return;

            if (data.results && Array.isArray(data.results)) {
              const activeYearOrder =
                viewMode === 'agg' ? filterAgg.yearOrder : filterAll.yearOrder;
              const results: SearchResult[] =
                activeYearOrder === 'none'
                  ? sortBatchForNoOrder(data.results as SearchResult[])
                  : (data.results as SearchResult[]);

              setSearchResults(results);
              // 缓存搜索结果
              setCachedResults(trimmed, results);
              setTotalSources(1);
              setCompletedSources(1);
            }
            setIsLoading(false);
          })
          .catch(() => {
            setIsLoading(false);
          });
      }
      setShowSuggestions(false);

      // 保存到搜索历史 (事件监听会自动更新界面)
      addSearchHistory(query);
    } else {
      setShowResults(false);
      setShowSuggestions(false);
    }
  }, [searchParams, forceRefresh, converterReady]);

  // 组件卸载时，关闭可能存在的连接
  useEffect(() => {
    return () => {
      if (eventSourceRef.current) {
        try {
          eventSourceRef.current.close();
        } catch {}
        eventSourceRef.current = null;
      }
      if (flushTimerRef.current) {
        clearTimeout(flushTimerRef.current);
        flushTimerRef.current = null;
      }
      pendingResultsRef.current = [];
    };
  }, []);

  // 输入框内容变化时触发，显示搜索建议
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setSearchQuery(value);

    if (value.trim()) {
      setShowSuggestions(true);
    } else {
      setShowSuggestions(false);
    }
  };

  // 搜索框聚焦时触发，显示搜索建议
  const handleInputFocus = () => {
    if (searchQuery.trim()) {
      setShowSuggestions(true);
    }
  };

  // 搜索表单提交时触发，处理搜索逻辑
  const handleSearch = (e: React.FormEvent) => {
    e.preventDefault();
    let trimmed = searchQuery.trim().replace(/\s+/g, ' ');
    if (!trimmed) return;

    // 如果开启了繁体转简体，进行转换
    if (typeof window !== 'undefined') {
      const searchTraditionalToSimplified = localStorage.getItem(
        'searchTraditionalToSimplified'
      );
      if (searchTraditionalToSimplified === 'true' && converterRef.current) {
        try {
          trimmed = converterRef.current(trimmed);
        } catch (error) {
          console.error('繁体转简体转换失败:', error);
        }
      }
    }

    // 回显搜索框
    setSearchQuery(trimmed);
    setShowResults(true);
    setShowSuggestions(false);
    // 立即设置加载状态，避免显示"未找到相关结果"
    setIsLoading(true);

    // 根据当前选项卡执行不同的搜索
    if (activeTab === 'video') {
      // 影视搜索
      router.push(`/search?q=${encodeURIComponent(trimmed)}&type=video`);
      // 其余由 searchParams 变化的 effect 处理
    } else if (activeTab === 'pansou') {
      // 网盘搜索 - 触发搜索
      router.push(`/search?q=${encodeURIComponent(trimmed)}&type=pansou`);
      setTriggerPansouSearch((prev) => !prev); // 切换状态来触发搜索
    } else if (activeTab === 'acg') {
      // ACG 磁力搜索 - 触发搜索
      router.push(`/search?q=${encodeURIComponent(trimmed)}&type=acg`);
      setTriggerAcgSearch((prev) => !prev);
    }
  };

  const handleSuggestionSelect = (suggestion: string) => {
    let processedSuggestion = suggestion;

    // 如果开启了繁体转简体，进行转换
    if (typeof window !== 'undefined') {
      const searchTraditionalToSimplified = localStorage.getItem(
        'searchTraditionalToSimplified'
      );
      if (searchTraditionalToSimplified === 'true' && converterRef.current) {
        try {
          processedSuggestion = converterRef.current(suggestion);
        } catch (error) {
          console.error('繁体转简体转换失败:', error);
        }
      }
    }

    setSearchQuery(processedSuggestion);
    setShowSuggestions(false);

    // 自动执行搜索
    setShowResults(true);
    // 立即设置加载状态，避免显示"未找到相关结果"
    setIsLoading(true);

    // 根据当前选项卡执行不同的搜索
    if (activeTab === 'video') {
      // 影视搜索
      router.push(
        `/search?q=${encodeURIComponent(processedSuggestion)}&type=video`
      );
      // 其余由 searchParams 变化的 effect 处理
    } else if (activeTab === 'pansou') {
      // 网盘搜索 - 触发搜索
      router.push(
        `/search?q=${encodeURIComponent(processedSuggestion)}&type=pansou`
      );
      setTriggerPansouSearch((prev) => !prev);
    } else if (activeTab === 'acg') {
      // ACG 磁力搜索 - 触发搜索
      router.push(
        `/search?q=${encodeURIComponent(processedSuggestion)}&type=acg`
      );
      setTriggerAcgSearch((prev) => !prev);
    }
  };

  // 返回顶部功能
  const scrollToTop = () => {
    try {
      // 根据调试结果，真正的滚动容器是 document.body
      document.body.scrollTo({
        top: 0,
        behavior: 'smooth',
      });
    } catch (error) {
      // 如果平滑滚动完全失败，使用立即滚动
      document.body.scrollTop = 0;
    }
  };

  // 处理标签切换
  const handleTabChange = (newTab: 'video' | 'pansou' | 'acg') => {
    setActiveTab(newTab);

    // 如果有搜索关键词，更新 URL
    const currentQuery = searchParams.get('q');
    if (currentQuery) {
      router.push(
        `/search?q=${encodeURIComponent(currentQuery)}&type=${newTab}`
      );
    }
  };

  return (
    <PageLayout activePath='/search'>
      <div className='px-4 sm:px-10 py-4 sm:py-8 overflow-visible mb-10'>
        {/* 搜索框 */}
        <div className='mb-8'>
          <form onSubmit={handleSearch} className='max-w-2xl mx-auto'>
            <div className='relative'>
              <Search className='absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400 dark:text-gray-500' />
              <input
                id='searchInput'
                type='text'
                value={searchQuery}
                onChange={handleInputChange}
                onFocus={handleInputFocus}
                placeholder='搜索电影、电视剧...'
                autoComplete='off'
                className='w-full h-12 rounded-lg bg-gray-50/80 py-3 pl-10 pr-12 text-sm text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-green-400 focus:bg-white border border-gray-200/50 shadow-sm dark:bg-gray-800 dark:text-gray-300 dark:placeholder-gray-500 dark:focus:bg-gray-700 dark:border-gray-700'
              />

              {/* 清除按钮 */}
              {searchQuery && (
                <button
                  type='button'
                  onClick={() => {
                    setSearchQuery('');
                    setShowSuggestions(false);
                    document.getElementById('searchInput')?.focus();
                  }}
                  className='absolute right-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors dark:text-gray-500 dark:hover:text-gray-300'
                  aria-label='清除搜索内容'
                >
                  <X className='h-5 w-5' />
                </button>
              )}

              {/* 搜索建议 */}
              <SearchSuggestions
                query={searchQuery}
                isVisible={showSuggestions}
                onSelect={handleSuggestionSelect}
                onClose={() => setShowSuggestions(false)}
                onEnterKey={() => {
                  // 当用户按回车键时，使用搜索框的实际内容进行搜索
                  const trimmed = searchQuery.trim().replace(/\s+/g, ' ');
                  if (!trimmed) return;

                  // 回显搜索框
                  setSearchQuery(trimmed);
                  setShowResults(true);
                  setShowSuggestions(false);

                  router.push(`/search?q=${encodeURIComponent(trimmed)}`);
                }}
              />
            </div>
          </form>

          {/* 选项卡 */}
          <div className='flex justify-center mt-6'>
            <CapsuleSwitch
              options={[
                {
                  label: '影视搜索',
                  value: 'video',
                  icon: <Film size={16} />,
                },
                {
                  label: '网盘搜索',
                  value: 'pansou',
                  icon: <HardDrive size={16} />,
                },
                // 仅管理员和站长显示 ACG 磁力搜索
                ...(userRole === 'admin' || userRole === 'owner'
                  ? [
                      {
                        label: '动漫磁力',
                        value: 'acg' as const,
                        icon: <Magnet size={16} />,
                      },
                    ]
                  : []),
              ]}
              active={activeTab}
              onChange={(value) =>
                handleTabChange(value as 'video' | 'pansou' | 'acg')
              }
            />
          </div>
        </div>

        {/* 搜索结果或搜索历史 */}
        <div className='max-w-[95%] mx-auto mt-12 overflow-visible'>
          {showResults ? (
            <section className='mb-12'>
              {activeTab === 'video' ? (
                <>
                  {/* 影视搜索结果 */}
                  {/* 标题 */}
                  <div className='mb-4 flex items-start justify-between gap-4'>
                    <div className='min-w-0'>
                      <h2 className='text-xl font-bold text-gray-800 dark:text-gray-200'>
                        搜索结果
                        {isFromCache ? (
                          <span className='ml-2 rounded-md bg-green-50 px-2 py-0.5 text-xs font-medium text-green-600 dark:bg-green-900/30 dark:text-green-400'>
                            缓存
                          </span>
                        ) : (
                          <>
                            {totalSources > 0 && useFluidSearch && (
                              <span className='ml-2 text-sm font-normal text-gray-500 dark:text-gray-400'>
                                源 {completedSources}/{totalSources}
                              </span>
                            )}
                            {isLoading && useFluidSearch && (
                              <span className='ml-2 inline-block align-middle'>
                                <span className='inline-block h-3 w-3 animate-spin rounded-full border-2 border-gray-300 border-t-green-500'></span>
                              </span>
                            )}
                          </>
                        )}
                      </h2>
                      <div className='mt-2 flex flex-wrap items-center gap-2 text-xs'>
                        <span className='inline-flex items-center rounded-full bg-gray-100 px-2.5 py-1 font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200'>
                          {resultCountMeta.modeLabel}{' '}
                          {resultCountMeta.visibleCount.toLocaleString()}{' '}
                          {resultCountMeta.unit}
                        </span>
                        {resultCountMeta.isFiltered && (
                          <span className='inline-flex items-center rounded-full bg-white/80 px-2.5 py-1 font-medium text-gray-500 ring-1 ring-gray-200 dark:bg-gray-900/70 dark:text-gray-400 dark:ring-gray-700'>
                            筛选前{' '}
                            {resultCountMeta.totalCount.toLocaleString()}{' '}
                            {resultCountMeta.unit}
                          </span>
                        )}
                      </div>
                    </div>
                    {searchQuery && (
                      <button
                        onClick={() => {
                          setForceRefresh(true);
                        }}
                        disabled={isLoading}
                        className='flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-gray-600 transition-colors hover:bg-green-50 hover:text-green-600 disabled:cursor-not-allowed disabled:opacity-50 dark:text-gray-400 dark:hover:bg-gray-700/50 dark:hover:text-green-400'
                        aria-label='强制刷新搜索结果'
                      >
                        <RefreshCw
                          className={`h-4 w-4 ${
                            isLoading ? 'animate-spin' : ''
                          }`}
                        />
                        <span>刷新</span>
                      </button>
                    )}
                  </div>
                  <div className='mb-4 flex items-center gap-3'>
                    <div className='min-w-0 flex-1'>
                      {viewMode === 'agg' ? (
                        <SearchResultFilter
                          categories={filterOptions.categoriesAgg}
                          values={filterAgg}
                          onChange={(v) => setFilterAgg(v as any)}
                        />
                      ) : (
                        <SearchResultFilter
                          categories={filterOptions.categoriesAll}
                          values={filterAll}
                          onChange={(v) => setFilterAll(v as any)}
                        />
                      )}
                    </div>
                    <div className='flex shrink-0 items-center justify-end self-center'>
                      <label className='flex shrink-0 cursor-pointer select-none items-center gap-2'>
                        <span className='text-xs text-gray-700 dark:text-gray-300 sm:text-sm'>
                          聚合
                        </span>
                        <div className='relative'>
                          <input
                            type='checkbox'
                            className='peer sr-only'
                            checked={viewMode === 'agg'}
                            onChange={() =>
                              setViewMode(viewMode === 'agg' ? 'all' : 'agg')
                            }
                          />
                          <div className='h-5 w-9 rounded-full bg-gray-300 transition-colors peer-checked:bg-green-500 dark:bg-gray-600'></div>
                          <div className='absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-white transition-transform peer-checked:translate-x-4'></div>
                        </div>
                      </label>
                    </div>
                  </div>
                  <div className='mb-8 flex justify-center'>
                    <div className='inline-flex items-center rounded-xl border border-gray-200 bg-white p-1 shadow-sm dark:border-gray-700 dark:bg-gray-900'>
                      <button
                        type='button'
                        onClick={() => setResultDisplayMode('card')}
                        className={`inline-flex items-center gap-1 rounded-lg px-3 py-1.5 text-sm transition-colors ${
                          resultDisplayMode === 'card'
                            ? 'bg-green-500 text-white'
                            : 'text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
                        }`}
                        aria-label='切换为卡片视图'
                      >
                        <Grid2x2 className='h-4 w-4' />
                        <span>卡片</span>
                      </button>
                      <button
                        type='button'
                        onClick={() => setResultDisplayMode('list')}
                        className={`inline-flex items-center gap-1 rounded-lg px-3 py-1.5 text-sm transition-colors ${
                          resultDisplayMode === 'list'
                            ? 'bg-green-500 text-white'
                            : 'text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
                        }`}
                        aria-label='切换为列表视图'
                      >
                        <List className='h-4 w-4' />
                        <span>列表</span>
                      </button>
                    </div>
                  </div>
                  {searchResults.length === 0 ? (
                    isLoading ? (
                      <div className='flex justify-center items-center h-40'>
                        <div className='animate-spin rounded-full h-8 w-8 border-b-2 border-green-500'></div>
                      </div>
                    ) : (
                      <div className='text-center text-gray-500 py-8 dark:text-gray-400'>
                        未找到相关结果
                      </div>
                    )
                  ) : (
                    (() => {
                      const gridClassName =
                        'justify-start grid grid-cols-3 gap-x-2 gap-y-14 px-0 sm:grid-cols-[repeat(auto-fill,_minmax(11rem,_1fr))] sm:gap-x-8 sm:gap-y-20 sm:px-2';

                      const listClassName = 'space-y-4';

                      const resultChildren =
                        viewMode === 'agg'
                          ? filteredAggResults.map(([mapKey, group]) => {
                              const title = group[0]?.title || '';
                              const poster = group[0]?.poster || '';
                              const year = group[0]?.year || 'unknown';
                              const desc =
                                group.find((entry) => entry.desc?.trim())
                                  ?.desc || '';
                              const vodRemarks =
                                group.find((entry) => entry.vod_remarks?.trim())
                                  ?.vod_remarks || '';
                              const { episodes, source_names, douban_id } =
                                computeGroupStats(group);

                              const lastDashIndex = mapKey.lastIndexOf('-');
                              const secondLastDashIndex = mapKey.lastIndexOf(
                                '-',
                                lastDashIndex - 1
                              );
                              const type =
                                secondLastDashIndex > 0
                                  ? (mapKey.substring(
                                      secondLastDashIndex + 1,
                                      lastDashIndex
                                    ) as 'movie' | 'tv')
                                  : episodes === 1
                                  ? 'movie'
                                  : 'tv';

                              if (!groupStatsRef.current.has(mapKey)) {
                                groupStatsRef.current.set(mapKey, {
                                  episodes,
                                  source_names,
                                  douban_id,
                                });
                              }

                              if (resultDisplayMode === 'list') {
                                return renderListItem({
                                  key: `agg-${mapKey}`,
                                  title,
                                  poster,
                                  year,
                                  type,
                                  episodes,
                                  sourceNames: source_names,
                                  doubanId: douban_id,
                                  desc,
                                  vodRemarks,
                                  isAggregate: true,
                                  query:
                                    searchQuery.trim() !== title
                                      ? searchQuery.trim()
                                      : '',
                                });
                              }

                              return (
                                <div key={`agg-${mapKey}`} className='w-full'>
                                  <VideoCard
                                    ref={getGroupRef(mapKey)}
                                    from='search'
                                    isAggregate={true}
                                    title={title}
                                    poster={poster}
                                    year={year}
                                    episodes={episodes}
                                    source_names={source_names}
                                    douban_id={douban_id}
                                    query={
                                      searchQuery.trim() !== title
                                        ? searchQuery.trim()
                                        : ''
                                    }
                                    type={type}
                                  />
                                </div>
                              );
                            })
                          : filteredAllResults.map((item) => {
                              const type =
                                item.episodes.length > 1 ? 'tv' : 'movie';

                              if (resultDisplayMode === 'list') {
                                return renderListItem({
                                  key: `all-${item.source}-${item.id}`,
                                  id: item.id,
                                  title: item.title,
                                  poster: item.poster,
                                  episodes: item.episodes.length,
                                  source: item.source,
                                  sourceName: item.source_name,
                                  doubanId: item.douban_id,
                                  query:
                                    searchQuery.trim() !== item.title
                                      ? searchQuery.trim()
                                      : '',
                                  year: item.year,
                                  type,
                                  desc: item.desc,
                                  vodRemarks: item.vod_remarks,
                                });
                              }

                              return (
                                <div
                                  key={`all-${item.source}-${item.id}`}
                                  className='w-full'
                                >
                                  <VideoCard
                                    id={item.id}
                                    title={item.title}
                                    poster={item.poster}
                                    episodes={item.episodes.length}
                                    source={item.source}
                                    source_name={item.source_name}
                                    douban_id={item.douban_id}
                                    query={
                                      searchQuery.trim() !== item.title
                                        ? searchQuery.trim()
                                        : ''
                                    }
                                    year={item.year}
                                    from='search'
                                    type={type}
                                  />
                                </div>
                              );
                            });

                      if (useVirtualGrid) {
                        return (
                          <VirtualScrollableGrid
                            key={`search-results-virtual-${viewMode}`}
                            gridClassName={gridClassName}
                          >
                            {resultChildren}
                          </VirtualScrollableGrid>
                        );
                      }

                      return (
                        <div
                          key={`search-results-${viewMode}-${resultDisplayMode}`}
                          className={
                            resultDisplayMode === 'list'
                              ? listClassName
                              : gridClassName
                          }
                        >
                          {resultChildren}
                        </div>
                      );
                    })()
                  )}
                </>
              ) : activeTab === 'pansou' ? (
                <>
                  {/* 网盘搜索结果 */}
                  <div className='mb-4'>
                    <h2 className='text-xl font-bold text-gray-800 dark:text-gray-200'>
                      网盘搜索结果
                    </h2>
                  </div>
                  <PansouSearch
                    keyword={searchQuery}
                    triggerSearch={triggerPansouSearch}
                  />
                </>
              ) : (
                <>
                  {/* ACG 磁力搜索结果 */}
                  <div className='mb-4'>
                    <h2 className='text-xl font-bold text-gray-800 dark:text-gray-200'>
                      动漫磁力搜索结果
                    </h2>
                  </div>
                  <AcgSearch
                    keyword={searchQuery}
                    triggerSearch={triggerAcgSearch}
                  />
                </>
              )}
            </section>
          ) : searchHistory.length > 0 ? (
            // 搜索历史
            <section className='mb-12'>
              <h2 className='mb-4 text-xl font-bold text-gray-800 text-left dark:text-gray-200'>
                搜索历史
                {searchHistory.length > 0 && (
                  <button
                    onClick={() => {
                      clearSearchHistory(); // 事件监听会自动更新界面
                    }}
                    className='ml-3 text-sm text-gray-500 hover:text-red-500 transition-colors dark:text-gray-400 dark:hover:text-red-500'
                  >
                    清空
                  </button>
                )}
              </h2>
              <div className='flex flex-wrap gap-2'>
                {searchHistory.map((item) => (
                  <div key={item} className='relative group'>
                    <button
                      onClick={() => {
                        setSearchQuery(item);
                        setShowResults(true);
                        // 立即设置加载状态，避免显示"未找到相关结果"
                        setIsLoading(true);

                        // 根据当前选项卡执行不同的搜索
                        if (activeTab === 'video') {
                          // 影视搜索
                          router.push(
                            `/search?q=${encodeURIComponent(
                              item.trim()
                            )}&type=video`
                          );
                        } else if (activeTab === 'pansou') {
                          // 网盘搜索
                          router.push(
                            `/search?q=${encodeURIComponent(
                              item.trim()
                            )}&type=pansou`
                          );
                          setTriggerPansouSearch((prev) => !prev);
                        } else if (activeTab === 'acg') {
                          // ACG 磁力搜索
                          router.push(
                            `/search?q=${encodeURIComponent(
                              item.trim()
                            )}&type=acg`
                          );
                          setTriggerAcgSearch((prev) => !prev);
                        }
                      }}
                      className='px-4 py-2 bg-gray-500/10 hover:bg-gray-300 rounded-full text-sm text-gray-700 transition-colors duration-200 dark:bg-gray-700/50 dark:hover:bg-gray-600 dark:text-gray-300'
                    >
                      {item}
                    </button>
                    {/* 删除按钮 */}
                    <button
                      aria-label='删除搜索历史'
                      onClick={(e) => {
                        e.stopPropagation();
                        e.preventDefault();
                        deleteSearchHistory(item); // 事件监听会自动更新界面
                      }}
                      className='absolute -top-1 -right-1 w-4 h-4 opacity-0 group-hover:opacity-100 bg-gray-400 hover:bg-red-500 text-white rounded-full flex items-center justify-center text-[10px] transition-colors'
                    >
                      <X className='w-3 h-3' />
                    </button>
                  </div>
                ))}
              </div>
            </section>
          ) : null}
        </div>
      </div>

      {previewImage && (
        <ImageViewer
          isOpen={!!previewImage}
          onClose={() => setPreviewImage(null)}
          imageUrl={previewImage.url}
          alt={previewImage.alt}
        />
      )}

      {/* 返回顶部悬浮按钮 */}
      <button
        onClick={scrollToTop}
        className={`fixed bottom-20 md:bottom-6 right-6 z-[500] w-12 h-12 bg-green-500/90 hover:bg-green-500 text-white rounded-full shadow-lg backdrop-blur-sm transition-all duration-300 ease-in-out flex items-center justify-center group ${
          showBackToTop
            ? 'opacity-100 translate-y-0 pointer-events-auto'
            : 'opacity-0 translate-y-4 pointer-events-none'
        }`}
        aria-label='返回顶部'
      >
        <ChevronUp className='w-6 h-6 transition-transform group-hover:scale-110' />
      </button>
    </PageLayout>
  );
}

export default function SearchPage() {
  return (
    <Suspense>
      <SearchPageClient />
    </Suspense>
  );
}
