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

import { ChevronUp, Search, X } from 'lucide-react';
import {
  Button,
  Card,
  Chip,
  EmptyState,
  Input,
  Spinner,
  Switch,
  Tooltip,
} from '@heroui/react';
import { useRouter, useSearchParams } from '@/client/router';
import React, { startTransition, Suspense, useEffect, useMemo, useRef, useState } from 'react';

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

import PageLayout from '@/components/PageLayout';
import SearchResultFilter, { SearchFilterCategory } from '@/components/SearchResultFilter';
import SearchSuggestions from '@/components/SearchSuggestions';
import VideoCard, { VideoCardHandle } from '@/components/VideoCard';

function SearchPageClient() {
  // 搜索历史
  const [searchHistory, setSearchHistory] = useState<string[]>([]);
  // 返回顶部按钮显示状态
  const [showBackToTop, setShowBackToTop] = useState(false);
  // 滚动进度状态
  const [scrollProgress, setScrollProgress] = useState(0);

  const router = useRouter();
  const searchParams = useSearchParams();
  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 | null>>>(new Map());
  const groupStatsRef = useRef<Map<string, { douban_id?: number; episodes?: number; source_names: string[] }>>(new Map());

  // 执行搜索的通用函数
  const performSearch = (query: string) => {
    const trimmed = query.trim();
    if (!trimmed) return;

    // 更新搜索查询和状态
    setSearchQuery(trimmed);
    currentQueryRef.current = trimmed;

    // 清理缓存标记，确保执行新搜索
    sessionStorage.removeItem('fromPlayPage');

    // 清空旧的搜索结果和状态
    if (eventSourceRef.current) {
      try { eventSourceRef.current.close(); } catch { }
      eventSourceRef.current = null;
    }
    setSearchResults([]);
    setTotalSources(0);
    setCompletedSources(0);
    pendingResultsRef.current = [];
    if (flushTimerRef.current) {
      clearTimeout(flushTimerRef.current);
      flushTimerRef.current = null;
    }

    // 清理聚合统计缓存和refs
    groupStatsRef.current.clear();
    groupRefs.current.clear();
    setIsLoading(true);
    setShowResults(true);

    // 读取流式搜索设置
    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 || eventSourceRef.current !== es) {
            console.warn('忽略过期的搜索响应:', payload.type, '当前查询:', 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);
                    try {
                      sessionStorage.setItem('cachedSearchQuery', trimmed);
                      sessionStorage.setItem('cachedSearchResults', JSON.stringify(newResults));
                      sessionStorage.setItem('cachedSearchState', JSON.stringify({
                        totalSources: payload.completedSources || totalSources,
                        completedSources: payload.completedSources || totalSources,
                      }));
                      sessionStorage.setItem('cachedSearchFilters', JSON.stringify({
                        filterAll,
                        filterAgg,
                      }));
                      sessionStorage.setItem('cachedViewMode', viewMode);
                    } catch (error) {
                      console.error('缓存搜索结果失败:', error);
                    }
                    return newResults;
                  });
                });
              } else {
                setTimeout(() => {
                  setSearchResults((prev) => {
                    try {
                      sessionStorage.setItem('cachedSearchQuery', trimmed);
                      sessionStorage.setItem('cachedSearchResults', JSON.stringify(prev));
                      sessionStorage.setItem('cachedSearchState', JSON.stringify({
                        totalSources: payload.completedSources || totalSources,
                        completedSources: payload.completedSources || totalSources,
                      }));
                      sessionStorage.setItem('cachedSearchFilters', JSON.stringify({
                        filterAll,
                        filterAgg,
                      }));
                      sessionStorage.setItem('cachedViewMode', viewMode);
                    } catch (error) {
                      console.error('缓存搜索结果失败:', error);
                    }
                    return prev;
                  });
                }, 100);
              }
              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) {
            console.warn('忽略过期的搜索响应 (传统):', '当前查询:', 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);
            setTotalSources(1);
            setCompletedSources(1);

            try {
              sessionStorage.setItem('cachedSearchQuery', trimmed);
              sessionStorage.setItem('cachedSearchResults', JSON.stringify(results));
              sessionStorage.setItem('cachedSearchState', JSON.stringify({
                totalSources: 1,
                completedSources: 1,
              }));
              sessionStorage.setItem('cachedSearchFilters', JSON.stringify({
                filterAll,
                filterAgg,
              }));
              sessionStorage.setItem('cachedViewMode', viewMode);
            } catch (error) {
              console.error('缓存搜索结果失败:', error);
            }
          }
          setIsLoading(false);
        })
        .catch(() => {
          setIsLoading(false);
        });
    }

    // 保存到搜索历史
    addSearchHistory(trimmed);

    // 更新URL但不触发重新渲染
    const newUrl = `/search?q=${encodeURIComponent(trimmed)}`;
    window.history.replaceState(null, '', newUrl);
  };

  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 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;
    });
  };

  // 检查搜索结果与关键字的相关性
  const isRelevantResult = (item: SearchResult, query: string) => {
    if (!query.trim()) return true;

    const searchTerms = query.trim().toLowerCase().split(/\s+/);
    const title = (item.title || '').toLowerCase();
    const typeName = (item.type_name || '').toLowerCase();

    // 至少匹配一个搜索关键字
    return searchTerms.some(term => {
      // 标题包含关键字
      if (title.includes(term)) return true;
      // 类型名包含关键字
      if (typeName.includes(term)) return true;
      // 支持年份搜索
      if (term.match(/^\d{4}$/) && item.year === term) return true;
      // 支持模糊匹配（去除空格和标点符号后的匹配）
      const cleanTitle = title.replace(/[\s\-_\.]/g, '');
      const cleanTerm = term.replace(/[\s\-_\.]/g, '');
      if (cleanTitle.includes(cleanTerm)) return true;

      return false;
    });
  };

  // 简化的年份排序：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 aggregatedResults = useMemo(() => {
    const map = new Map<string, SearchResult[]>();
    const keyOrder: string[] = []; // 记录键出现的顺序

    searchResults.forEach((item) => {
      // 使用 title + year + type 作为键，year 必然存在，但依然兜底 'unknown'
      const key = `${item.title.replaceAll(' ', '')}-${item.year || 'unknown'
        }-${item.episodes.length === 1 ? 'movie' : 'tv'}`;
      const arr = map.get(key) || [];

      // 如果是新的键，记录其顺序
      if (arr.length === 0) {
        keyOrder.push(key);
      }

      arr.push(item);
      map.set(key, arr);
    });

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

  // 当聚合结果变化时，如果某个聚合已存在，则调用其卡片 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 sourcesSet = new Map<string, string>();
    const titlesSet = new Set<string>();
    const yearsSet = new Set<string>();

    // 只考虑与搜索关键字相关的结果来构建过滤选项
    const relevantResults = searchResults.filter(item => isRelevantResult(item, searchQuery));

    relevantResults.forEach((item) => {
      if (item.source && item.source_name) {
        sourcesSet.set(item.source, item.source_name);
      }
      if (item.title) titlesSet.add(item.title);
      if (item.year) yearsSet.add(item.year);
    });

    const sourceOptions: { label: string; value: string }[] = [
      { label: '全部来源', value: 'all' },
      ...Array.from(sourcesSet.entries())
        .sort((a, b) => a[1].localeCompare(b[1]))
        .map(([value, label]) => ({ label, value })),
    ];

    const titleOptions: { label: string; value: string }[] = [
      { label: '全部标题', value: 'all' },
      ...Array.from(titlesSet.values())
        .sort((a, b) => a.localeCompare(b))
        .map((t) => ({ label: t, value: t })),
    ];

    // 年份: 将 unknown 放末尾
    const years = Array.from(yearsSet.values());
    const knownYears = years.filter((y) => y !== 'unknown').sort((a, b) => parseInt(b) - parseInt(a));
    const hasUnknown = years.includes('unknown');
    const yearOptions: { label: string; value: string }[] = [
      { label: '全部年份', value: 'all' },
      ...knownYears.map((y) => ({ label: y, value: y })),
      ...(hasUnknown ? [{ label: '未知', value: 'unknown' }] : []),
    ];

    const categoriesAll: SearchFilterCategory[] = [
      { key: 'source', label: '来源', options: sourceOptions },
      { key: 'title', label: '标题', options: titleOptions },
      { key: 'year', label: '年份', options: yearOptions },
    ];

    const categoriesAgg: SearchFilterCategory[] = [
      { key: 'source', label: '来源', options: sourceOptions },
      { key: 'title', label: '标题', options: titleOptions },
      { key: 'year', label: '年份', options: yearOptions },
    ];

    return { categoriesAll, categoriesAgg };
  }, [searchResults]);

  // 非聚合：应用筛选与排序
  const filteredAllResults = useMemo(() => {
    const { source, title, year, yearOrder } = filterAll;
    const filtered = searchResults.filter((item) => {
      // 首先检查相关性
      if (!isRelevantResult(item, searchQuery)) return false;
      // 然后应用其他过滤器
      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);
    });
  }, [searchResults, filterAll, searchQuery]);

  // 聚合：应用筛选与排序
  const filteredAggResults = useMemo(() => {
    const { source, title, year, yearOrder } = filterAgg as any;
    const filtered = aggregatedResults.filter(([_, group]) => {
      // 检查聚合组中是否至少有一个结果与搜索关键字相关
      const hasRelevantResult = group.some(item => isRelevantResult(item, searchQuery));
      if (!hasRelevantResult) return false;

      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]);

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

    // 初始加载搜索历史
    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 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);

      // 计算滚动进度
      const documentHeight = document.body.scrollHeight - document.body.clientHeight;
      const progress = documentHeight > 0 ? Math.min((scrollTop / documentHeight) * 100, 100) : 0;
      setScrollProgress(progress);

      requestAnimationFrame(checkScrollPosition);
    };

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

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

      // 计算滚动进度
      const documentHeight = document.body.scrollHeight - document.body.clientHeight;
      const progress = documentHeight > 0 ? Math.min((scrollTop / documentHeight) * 100, 100) : 0;
      setScrollProgress(progress);
    };

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

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

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

  useEffect(() => {
    // 当搜索参数变化时更新搜索状态
    const query = searchParams.get('q') || '';
    currentQueryRef.current = query.trim();

    if (query) {
      setSearchQuery(query);

      // 检查是否从播放页返回，如果是则尝试使用缓存
      const fromPlayPage = sessionStorage.getItem('fromPlayPage');
      const cachedQuery = sessionStorage.getItem('cachedSearchQuery');
      const cachedResults = sessionStorage.getItem('cachedSearchResults');
      const cachedState = sessionStorage.getItem('cachedSearchState');
      const cachedFilters = sessionStorage.getItem('cachedSearchFilters');
      const cachedViewMode = sessionStorage.getItem('cachedViewMode');

      if (fromPlayPage === 'true' && cachedQuery === query.trim() && cachedResults && cachedState) {
        // 从播放页返回且有缓存，使用缓存的搜索结果
        console.log('使用缓存的搜索结果');

        try {
          const results = JSON.parse(cachedResults);
          const state = JSON.parse(cachedState);

          // 恢复缓存的过滤器和视图状态
          if (cachedFilters) {
            const filters = JSON.parse(cachedFilters);
            if (filters.filterAll) setFilterAll(filters.filterAll);
            if (filters.filterAgg) setFilterAgg(filters.filterAgg);
          }

          if (cachedViewMode && ['agg', 'all'].includes(cachedViewMode)) {
            setViewMode(cachedViewMode as 'agg' | 'all');
          }

          // 恢复搜索结果和状态
          setSearchResults(results);
          setTotalSources(state.totalSources || 0);
          setCompletedSources(state.completedSources || 0);
          setIsLoading(false);
          setShowResults(true);

          // 清理导航标记，避免影响后续搜索
          sessionStorage.removeItem('fromPlayPage');

          return; // 直接返回，不执行新搜索
        } catch (error) {
          console.error('恢复缓存的搜索结果失败:', error);
          // 缓存损坏，清理缓存并继续正常搜索
          sessionStorage.removeItem('cachedSearchQuery');
          sessionStorage.removeItem('cachedSearchResults');
          sessionStorage.removeItem('cachedSearchState');
          sessionStorage.removeItem('cachedSearchFilters');
          sessionStorage.removeItem('cachedViewMode');
          sessionStorage.removeItem('fromPlayPage');
        }
      }

      // 执行新搜索 - 使用performSearch函数（不更新URL，因为URL已经由路由处理了）
      const trimmed = query.trim();

      // 清空旧的搜索结果和状态
      if (eventSourceRef.current) {
        try { eventSourceRef.current.close(); } catch { }
        eventSourceRef.current = null;
      }
      setSearchResults([]);
      setTotalSources(0);
      setCompletedSources(0);
      pendingResultsRef.current = [];
      if (flushTimerRef.current) {
        clearTimeout(flushTimerRef.current);
        flushTimerRef.current = null;
      }

      // 清理聚合统计缓存和refs
      groupStatsRef.current.clear();
      groupRefs.current.clear();
      setIsLoading(true);
      setShowResults(true);

      // 读取流式搜索设置
      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 || eventSourceRef.current !== es) {
              console.warn('忽略过期的搜索响应:', payload.type, '当前查询:', 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);
                      try {
                        sessionStorage.setItem('cachedSearchQuery', trimmed);
                        sessionStorage.setItem('cachedSearchResults', JSON.stringify(newResults));
                        sessionStorage.setItem('cachedSearchState', JSON.stringify({
                          totalSources: payload.completedSources || totalSources,
                          completedSources: payload.completedSources || totalSources,
                        }));
                        sessionStorage.setItem('cachedSearchFilters', JSON.stringify({
                          filterAll,
                          filterAgg,
                        }));
                        sessionStorage.setItem('cachedViewMode', viewMode);
                      } catch (error) {
                        console.error('缓存搜索结果失败:', error);
                      }
                      return newResults;
                    });
                  });
                } else {
                  setTimeout(() => {
                    setSearchResults((prev) => {
                      try {
                        sessionStorage.setItem('cachedSearchQuery', trimmed);
                        sessionStorage.setItem('cachedSearchResults', JSON.stringify(prev));
                        sessionStorage.setItem('cachedSearchState', JSON.stringify({
                          totalSources: payload.completedSources || totalSources,
                          completedSources: payload.completedSources || totalSources,
                        }));
                        sessionStorage.setItem('cachedSearchFilters', JSON.stringify({
                          filterAll,
                          filterAgg,
                        }));
                        sessionStorage.setItem('cachedViewMode', viewMode);
                      } catch (error) {
                        console.error('缓存搜索结果失败:', error);
                      }
                      return prev;
                    });
                  }, 100);
                }
                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) {
              console.warn('忽略过期的搜索响应 (传统):', '当前查询:', 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);
              setTotalSources(1);
              setCompletedSources(1);

              try {
                sessionStorage.setItem('cachedSearchQuery', trimmed);
                sessionStorage.setItem('cachedSearchResults', JSON.stringify(results));
                sessionStorage.setItem('cachedSearchState', JSON.stringify({
                  totalSources: 1,
                  completedSources: 1,
                }));
                sessionStorage.setItem('cachedSearchFilters', JSON.stringify({
                  filterAll,
                  filterAgg,
                }));
                sessionStorage.setItem('cachedViewMode', viewMode);
              } catch (error) {
                console.error('缓存搜索结果失败:', error);
              }
            }
            setIsLoading(false);
          })
          .catch(() => {
            setIsLoading(false);
          });
      }

      setShowSuggestions(false);
      // 保存到搜索历史
      addSearchHistory(trimmed);
    } else {
      setShowResults(false);
      setShowSuggestions(false);
    }
  }, [searchParams]);

  // 组件卸载时，关闭可能存在的连接并清理所有状态
  useEffect(() => {
    return () => {
      if (eventSourceRef.current) {
        try { eventSourceRef.current.close(); } catch { }
        eventSourceRef.current = null;
      }
      if (flushTimerRef.current) {
        clearTimeout(flushTimerRef.current);
        flushTimerRef.current = null;
      }
      pendingResultsRef.current = [];
      // 清理聚合统计缓存和refs，防止状态泄露
      groupStatsRef.current.clear();
      groupRefs.current.clear();
      // 重置当前查询引用
      currentQueryRef.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();
    const trimmed = searchQuery.trim().replace(/\s+/g, ' ');
    if (!trimmed) return;

    setShowSuggestions(false);
    // 直接调用搜索函数
    performSearch(trimmed);
  };

  const handleSuggestionSelect = (suggestion: string) => {
    setShowSuggestions(false);
    // 直接调用搜索函数
    performSearch(suggestion);
  };

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

  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-muted' />
              <Input
                id='searchInput'
                type='text'
                value={searchQuery}
                onChange={handleInputChange}
                onFocus={handleInputFocus}
                placeholder='搜索电影、电视剧...'
                autoComplete="off"
                fullWidth
                className='pl-10 pr-12'
              />

              {/* 清除按钮 */}
              {searchQuery && (
                <Button
                  type='button'
                  isIconOnly
                  size='sm'
                  variant='ghost'
                  onPress={() => {
                    setSearchQuery('');
                    setShowSuggestions(false);
                    document.getElementById('searchInput')?.focus();
                  }}
                  className='absolute right-3 top-1/2 h-5 w-5 -translate-y-1/2 text-muted transition-colors hover:text-foreground'
                  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;

                  setShowSuggestions(false);
                  // 直接调用搜索函数
                  performSearch(trimmed);
                }}
              />
            </div>
          </form>
        </div>

        {/* 搜索结果或搜索历史 */}
        <div className='max-w-[95%] mx-auto mt-12 overflow-visible'>
          {showResults ? (
            <Card className='mb-12'>
              {/* 标题 */}
              <div className='mb-4'>
                <h2 className='text-xl font-semibold tracking-normal text-foreground'>
                  搜索结果
                  {totalSources > 0 && useFluidSearch && (
                    <span className='ml-2 text-sm font-normal text-muted'>
                      来源 {completedSources}/{totalSources}
                    </span>
                  )}
                  {isLoading && useFluidSearch && (
                    <Spinner size='sm' className='ml-2 inline-flex align-middle' />
                  )}
                </h2>
              </div>
              {/* 筛选器 + 聚合开关 同行 */}
              <div className='mb-8 flex items-center justify-between gap-3'>
                <div className='flex-1 min-w-0'>
                  {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>
                {/* 聚合开关 */}
                <Switch
                  size='sm'
                  isSelected={viewMode === 'agg'}
                  onChange={() => setViewMode(viewMode === 'agg' ? 'all' : 'agg')}
                >
                  <Switch.Control>
                    <Switch.Thumb />
                  </Switch.Control>
                  <Switch.Content>聚合</Switch.Content>
                </Switch>
              </div>
              {searchResults.length === 0 ? (
                isLoading ? (
                  <div className='flex h-40 items-center justify-center'>
                    <Spinner />
                  </div>
                ) : (
                  <EmptyState>
                    未找到相关结果
                  </EmptyState>
                )
              ) : (
                <div
                  key={`search-results-${viewMode}`}
                  className='justify-start grid grid-cols-3 gap-x-2 gap-y-14 sm:gap-y-20 px-0 sm:px-2 sm:grid-cols-[repeat(auto-fill,_minmax(11rem,_1fr))] sm:gap-x-8'
                >
                  {viewMode === 'agg'
                    ? filteredAggResults.map(([mapKey, group]) => {
                      const title = group[0]?.title || '';
                      const poster = group[0]?.poster || '';
                      const year = group[0]?.year || 'unknown';
                      const { episodes, source_names, douban_id } = computeGroupStats(group);
                      const type = episodes === 1 ? 'movie' : 'tv';

                      // 如果该聚合第一次出现，写入初始统计
                      if (!groupStatsRef.current.has(mapKey)) {
                        groupStatsRef.current.set(mapKey, { episodes, source_names, douban_id });
                      }

                      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) => (
                      <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={item.episodes.length > 1 ? 'tv' : 'movie'}
                        />
                      </div>
                    ))}
                </div>
              )}
            </Card>
          ) : searchHistory.length > 0 ? (
            // 搜索历史
            <Card className='mb-12'>
              <Card.Header className='flex-row items-center justify-between gap-3'>
                <Card.Title>搜索历史</Card.Title>
                {searchHistory.length > 0 && (
                  <Button
                    variant='danger'
                    size='sm'
                    onPress={() => {
                      clearSearchHistory(); // 事件监听会自动更新界面
                    }}
                  >
                    清空
                  </Button>
                )}
              </Card.Header>
              <div className='flex flex-wrap gap-2'>
                {searchHistory.map((item) => (
                  <div key={item} className='relative group'>
                    <Chip
                      role='button'
                      tabIndex={0}
                      onClick={() => {
                        // 直接调用搜索函数
                        performSearch(item.trim());
                      }}
                      color='accent'
                      variant='soft'
                    >
                      <Chip.Label>{item}</Chip.Label>
                    </Chip>
                    <button
                      type='button'
                      aria-label='删除搜索历史'
                      className='absolute -right-1 -top-1 inline-flex h-4 w-4 items-center justify-center rounded-full border border-border/80 bg-surface text-muted opacity-0 shadow-sm transition hover:bg-danger hover:text-white focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-danger/40 group-hover:opacity-100'
                      onClick={(event) => {
                        event.stopPropagation();
                        deleteSearchHistory(item); // 事件监听会自动更新界面
                      }}
                    >
                      <X className='h-2.5 w-2.5' strokeWidth={2.4} />
                    </button>
                  </div>
                ))}
              </div>
            </Card>
          ) : null}
        </div>
      </div>

      {/* 返回顶部悬浮按钮 */}
      <div
        className={`fixed bottom-20 md:bottom-6 right-6 z-[500] transition-all duration-300 ease-in-out ${showBackToTop
          ? 'opacity-100 translate-y-0 pointer-events-auto'
          : 'opacity-0 translate-y-4 pointer-events-none'
          }`}
      >
        <Tooltip>
          <Tooltip.Trigger>
          <Button
            onPress={scrollToTop}
            isIconOnly
            aria-label={`返回顶部 (${Math.round(scrollProgress)}%)`}
          >
            <ChevronUp className='w-6 h-6' />
          </Button>
          </Tooltip.Trigger>
          <Tooltip.Content>{Math.round(scrollProgress)}%</Tooltip.Content>
        </Tooltip>
      </div>
    </PageLayout>
  );
}

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