"use client"

import { useEffect, useRef, useState } from "react"

import type { ActionState } from "@/shared/types/action-state"
import type { Message, MessageType } from "../types"

type SearchMessagesResult = ActionState<{
  items: Message[]
  total: number
  page: number
  pageSize: number
  totalPages: number
}>

interface UseMessageSearchParams {
  /** 搜索动作（注入的接口，避免组件直接依赖具体 action） */
  searchAction: (params: {
    type: MessageType
    keyword: string
    page?: number
    pageSize?: number
  }) => Promise<SearchMessagesResult>
  /** 当前标签页 */
  tab: "inbox" | "sent"
  /** 防抖延迟（毫秒），默认 400 */
  debounceMs?: number
}

interface UseMessageSearchResult {
  keyword: string
  setKeyword: (v: string) => void
  results: Message[] | null
  searching: boolean
  /** 当前 keyword 为空时为 true，表示应使用 prop 传入的初始消息 */
  isUsingInitial: boolean
}

/**
 * 消息搜索 hook：将搜索逻辑从 MessageList 组件抽离为独立 hook，
 * 提升可测试性与可复用性。支持防抖、请求取消、状态匹配。
 *
 * 使用方式：
 * const { keyword, setKeyword, results, searching } = useMessageSearch({
 *   searchAction: getMessagesAction,
 *   tab,
 * })
 */
export function useMessageSearch({
  searchAction,
  tab,
  debounceMs = 400,
}: UseMessageSearchParams): UseMessageSearchResult {
  const [keyword, setKeyword] = useState("")
  const [results, setResults] = useState<Message[] | null>(null)
  const [searching, setSearching] = useState(false)
  const requestIdRef = useRef(0)

  useEffect(() => {
    const kw = keyword.trim()
    if (kw.length === 0) {
      setResults(null)
      setSearching(false)
      return
    }

    setSearching(true)
    const currentRequestId = ++requestIdRef.current
    const timer = setTimeout(async () => {
      // 在异步执行前检查是否已被后续请求取代
      if (currentRequestId !== requestIdRef.current) return

      try {
        const res = await searchAction({ type: tab, keyword: kw })
        // 请求返回后再次检查，避免竞态
        if (currentRequestId !== requestIdRef.current) return
        if (res.success && res.data) {
          setResults(res.data.items)
        } else {
          setResults([])
        }
      } catch {
        if (currentRequestId !== requestIdRef.current) return
        setResults([])
      } finally {
        if (currentRequestId === requestIdRef.current) {
          setSearching(false)
        }
      }
    }, debounceMs)

    return () => {
      clearTimeout(timer)
    }
  }, [keyword, tab, searchAction, debounceMs])

  const isUsingInitial = keyword.trim().length === 0

  return {
    keyword,
    setKeyword,
    results,
    searching,
    isUsingInitial,
  }
}
