"use client"

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
import { Checkbox } from "@/components/ui/checkbox"
import { IconInput } from "@/components/ui/icon-input"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { Separator } from "@/components/ui/separator"
import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"
import { Switch } from "@/components/ui/switch"
import { listGames } from "@/lib/api"
import { searchCatalog } from "@/lib/api/search"
import { GameIcon } from "@/lib/game-icons"
import type { SearchResponse, SearchResultItem, SearchSort } from "@/lib/search/types"
import type { Game, Player } from "@/lib/types"
import { cn } from "@/lib/utils"
import {
  CheckCircle2,
  Clock,
  Filter,
  Gamepad2,
  Search,
  SlidersHorizontal,
  Star,
  Store,
  User,
  XCircle,
} from "lucide-react"
import Link from "next/link"
import { useRouter, useSearchParams } from "next/navigation"
import { Suspense, useCallback, useEffect, useState } from "react"

const SEARCH_SORTS: ReadonlySet<SearchSort> = new Set([
  "composite",
  "rating",
  "orders",
  "price_asc",
  "price_desc",
])

const DEFAULT_LIMIT = 12

function numberParam(value: string | null, fallback: number) {
  if (value === null) return fallback
  const parsed = Number(value)
  return Number.isFinite(parsed) ? parsed : fallback
}

function resetPagination(params: URLSearchParams) {
  params.set("limit", String(DEFAULT_LIMIT))
  params.set("offset", "0")
}

function StatusBadge({ status }: { status: Player["status"] }) {
  switch (status) {
    case "available":
      return (
        <Badge variant="outline" className="bg-green-50 text-green-700 border-green-200 gap-1">
          <CheckCircle2 className="w-3 h-3" />
          可接单
        </Badge>
      )
    case "busy":
      return (
        <Badge variant="outline" className="bg-yellow-50 text-yellow-700 border-yellow-200 gap-1">
          <Clock className="w-3 h-3" />
          忙碌中
        </Badge>
      )
    case "offline":
      return (
        <Badge variant="outline" className="bg-gray-50 text-gray-500 border-gray-200 gap-1">
          <XCircle className="w-3 h-3" />
          离线
        </Badge>
      )
    default:
      return null
  }
}

function PlayerCard({ player }: { player: Player }) {
  const minPrice =
    !player.services || player.services.length === 0
      ? 0
      : Math.min(...player.services.map((s) => s.price))

  const unit =
    !player.services || player.services.length === 0
      ? "局"
      : player.services.reduce((prev, curr) => (prev.price < curr.price ? prev : curr)).unit

  return (
    <Link href={`/player/${player.id}`} className="block h-full">
      <Card className="h-full overflow-hidden flex flex-col p-0 gap-0">
        <CardHeader className="p-4 pb-2 flex flex-row items-start justify-between space-y-0">
          <div className="flex items-center gap-3">
            <Avatar className="h-12 w-12 border-2 border-background shadow-sm">
              <AvatarImage src={player.user.avatar} alt={player.user.nickname} />
              <AvatarFallback>{player.user.nickname.slice(0, 2)}</AvatarFallback>
            </Avatar>
            <div>
              <h3 className="font-semibold text-base leading-none mb-1">{player.user.nickname}</h3>
              <div className="flex items-center gap-1 text-xs text-muted-foreground">
                {player.shopName ? (
                  <span className="flex items-center gap-0.5 text-blue-600 bg-blue-50 px-1.5 py-0.5 rounded-full">
                    <Store className="w-3 h-3" />
                    {player.shopName}
                  </span>
                ) : (
                  <span className="flex items-center gap-0.5 text-gray-600 bg-gray-100 px-1.5 py-0.5 rounded-full">
                    <User className="w-3 h-3" />
                    个人
                  </span>
                )}
              </div>
            </div>
          </div>
          <StatusBadge status={player.status} />
        </CardHeader>

        <CardContent className="p-4 pt-2 flex-grow">
          <div className="flex items-center gap-4 mb-3 text-sm">
            <div className="flex items-center gap-1 text-yellow-500 font-medium">
              <Star className="w-4 h-4 fill-current" />
              {player.rating.toFixed(1)}
            </div>
            <div className="text-muted-foreground">接单 {player.totalOrders}</div>
          </div>

          <div className="flex flex-wrap gap-1.5 mb-3">
            {player.games.slice(0, 3).map((game) => (
              <Badge key={game} variant="secondary" className="text-xs font-normal">
                {game}
              </Badge>
            ))}
            {player.games.length > 3 && (
              <Badge variant="secondary" className="text-xs font-normal">
                +{player.games.length - 3}
              </Badge>
            )}
          </div>

          <div className="flex flex-wrap gap-1">
            {player.tags.slice(0, 2).map((tag) => (
              <span
                key={tag}
                className="text-[10px] px-1.5 py-0.5 bg-muted rounded-full text-muted-foreground"
              >
                {tag}
              </span>
            ))}
          </div>
        </CardContent>

        <Separator />

        <CardFooter className="p-3 bg-muted/20 flex items-center justify-between">
          <div className="flex items-baseline gap-1">
            <span className="text-xs text-muted-foreground">起</span>
            <span className="text-lg font-bold text-primary">¥{minPrice}</span>
            <span className="text-xs text-muted-foreground">/{unit}</span>
          </div>
          <Button size="sm" variant="ghost" className="h-8 px-3 text-xs rounded-full">
            查看详情
          </Button>
        </CardFooter>
      </Card>
    </Link>
  )
}

type ShopSearchItem = Extract<SearchResultItem, { type: "shop" }>

function ShopCard({ item }: { item: ShopSearchItem }) {
  return (
    <Link href={`/shop/${item.shop.id}`} className="block h-full">
      <Card className="h-full overflow-hidden flex flex-col p-0 gap-0">
        <CardHeader className="p-4 pb-2 flex flex-row items-start justify-between space-y-0">
          <div className="flex items-center gap-3">
            <Avatar className="h-12 w-12 border-2 border-background shadow-sm">
              <AvatarImage src={item.shop.owner.avatar} alt={item.shop.name} />
              <AvatarFallback>{item.shop.name.slice(0, 2)}</AvatarFallback>
            </Avatar>
            <div>
              <h3 className="font-semibold text-base leading-none mb-1">{item.shop.name}</h3>
              <div className="flex items-center gap-1 text-xs text-muted-foreground">
                <span className="flex items-center gap-0.5 text-blue-600 bg-blue-50 px-1.5 py-0.5 rounded-full">
                  <Store className="w-3 h-3" />
                  店铺
                </span>
              </div>
            </div>
          </div>
          <StatusBadge status={item.hasAvailable ? "available" : "busy"} />
        </CardHeader>

        <CardContent className="p-4 pt-2 flex-grow">
          <div className="flex items-center gap-4 mb-3 text-sm">
            <div className="flex items-center gap-1 text-yellow-500 font-medium">
              <Star className="w-4 h-4 fill-current" />
              {item.shop.rating}
            </div>
            <div className="text-muted-foreground">接单 {item.shop.totalOrders}</div>
          </div>

          <div className="flex flex-wrap gap-1.5 mb-3">
            {item.games.slice(0, 3).map((game) => (
              <Badge key={game} variant="secondary" className="text-xs font-normal">
                {game}
              </Badge>
            ))}
            {item.games.length > 3 && (
              <Badge variant="secondary" className="text-xs font-normal">
                +{item.games.length - 3}
              </Badge>
            )}
          </div>
        </CardContent>

        <Separator />

        <CardFooter className="p-3 bg-muted/20 flex items-center justify-between">
          <div className="flex items-baseline gap-1">
            <span className="text-xs text-muted-foreground">起</span>
            <span className="text-lg font-bold text-primary">¥{item.minPrice}</span>
            <span className="text-xs text-muted-foreground">/{item.unit}</span>
          </div>
          <Button size="sm" variant="ghost" className="h-8 px-3 text-xs rounded-full">
            查看详情
          </Button>
        </CardFooter>
      </Card>
    </Link>
  )
}

interface FilterProps {
  games: Game[]
  selectedGames: string[]
  onGameChange: (game: string, checked: boolean) => void
  priceRange: { min: string; max: string }
  onPriceChange: (type: "min" | "max", value: string) => void
  onlyOnline: boolean
  onOnlineChange: (checked: boolean) => void
  minRating: string
  onRatingChange: (value: string) => void
  className?: string
}

function FilterSection({
  games,
  selectedGames,
  onGameChange,
  priceRange,
  onPriceChange,
  onlyOnline,
  onOnlineChange,
  minRating,
  onRatingChange,
  className,
}: FilterProps) {
  return (
    <div className={cn("space-y-6", className)}>
      <div className="space-y-3">
        <h3 className="font-medium text-sm flex items-center gap-2">
          <Gamepad2 className="w-4 h-4" />
          游戏类型
        </h3>
        <div className="space-y-2">
          {games.map((game) => (
            <div key={game.id} className="flex items-center space-x-2">
              <Checkbox
                id={`game-${game.id}`}
                checked={selectedGames.includes(game.name)}
                onCheckedChange={(checked) => onGameChange(game.name, checked as boolean)}
              />
              <Label
                htmlFor={`game-${game.id}`}
                className="text-sm font-normal cursor-pointer flex items-center gap-2"
              >
                <GameIcon name={game.icon} className="h-4 w-4" />
                {game.name}
              </Label>
            </div>
          ))}
        </div>
      </div>

      <Separator />

      <div className="space-y-3">
        <h3 className="font-medium text-sm flex items-center gap-2">
          价格区间 (元)
          {(priceRange.min || priceRange.max) && (
            <Badge variant="secondary" className="text-[10px] px-1.5 py-0 font-normal">
              ¥{priceRange.min || "-"} - ¥{priceRange.max || "-"}
            </Badge>
          )}
        </h3>
        <div className="flex items-center gap-2">
          <Input
            type="number"
            placeholder="最低"
            className="h-8 text-sm"
            value={priceRange.min}
            onChange={(e) => onPriceChange("min", e.target.value)}
            min={0}
          />
          <span className="text-muted-foreground">-</span>
          <Input
            type="number"
            placeholder="最高"
            className="h-8 text-sm"
            value={priceRange.max}
            onChange={(e) => onPriceChange("max", e.target.value)}
            min={0}
          />
        </div>
      </div>

      <Separator />

      <div className="flex items-center justify-between">
        <Label htmlFor="online-mode" className="font-medium text-sm cursor-pointer">
          只看在线
        </Label>
        <Switch id="online-mode" checked={onlyOnline} onCheckedChange={onOnlineChange} />
      </div>

      <Separator />

      <div className="space-y-3">
        <h3 className="font-medium text-sm flex items-center gap-2">
          <Star className="w-4 h-4" />
          最低评分
        </h3>
        <Select value={minRating} onValueChange={onRatingChange}>
          <SelectTrigger className="h-9 rounded-lg">
            <SelectValue placeholder="选择评分" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="0">不限</SelectItem>
            <SelectItem value="4.0">4.0分以上</SelectItem>
            <SelectItem value="4.5">4.5分以上</SelectItem>
            <SelectItem value="4.8">4.8分以上</SelectItem>
            <SelectItem value="5.0">5.0分满分</SelectItem>
          </SelectContent>
        </Select>
      </div>
    </div>
  )
}

function SearchPageContent() {
  const searchParams = useSearchParams()
  const router = useRouter()
  const [games, setGames] = useState<Game[]>([])

  const [searchQuery, setSearchQuery] = useState(searchParams.get("q") || "")
  const [selectedGames, setSelectedGames] = useState<string[]>(() => {
    const selected = searchParams.getAll("game")
    return [...new Set(selected)]
  })
  const [priceRange, setPriceRange] = useState<{ min: string; max: string }>({
    min: searchParams.get("min") || "",
    max: searchParams.get("max") || "",
  })
  const [onlyOnline, setOnlyOnline] = useState((searchParams.get("online") ?? "0") === "1")
  const [minRating, setMinRating] = useState(searchParams.get("minRating") ?? "0")
  const [sortBy, setSortBy] = useState<SearchSort>(() => {
    const sortParam = (searchParams.get("sort") ?? "composite") as SearchSort
    return SEARCH_SORTS.has(sortParam) ? sortParam : "composite"
  })

  const [response, setResponse] = useState<SearchResponse | null>(null)
  const [hasLoaded, setHasLoaded] = useState(false)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false

    listGames()
      .then((items) => {
        if (cancelled) return
        setGames(items)
      })
      .catch(() => {
        if (cancelled) return
        setGames([])
      })

    return () => {
      cancelled = true
    }
  }, [])

  const replaceUrl = useCallback(
    (updater: (params: URLSearchParams) => void) => {
      const params = new URLSearchParams(searchParams.toString())
      updater(params)
      router.replace(`/search?${params.toString()}`, { scroll: false })
    },
    [router, searchParams],
  )

  useEffect(() => {
    const timer = setTimeout(() => {
      const urlQ = searchParams.get("q") ?? ""
      if (searchQuery === urlQ) return

      replaceUrl((params) => {
        if (searchQuery) params.set("q", searchQuery)
        else params.delete("q")
        resetPagination(params)
      })
    }, 500)

    return () => clearTimeout(timer)
  }, [replaceUrl, searchParams, searchQuery])

  useEffect(() => {
    const controller = new AbortController()

    const q = searchParams.get("q") || undefined
    const selected = searchParams.getAll("game")
    const min = searchParams.get("min") || undefined
    const max = searchParams.get("max") || undefined
    const onlyOnlineParam = (searchParams.get("online") ?? "0") === "1"
    const minRatingParam = searchParams.get("minRating") ?? "0"

    const sortParam = (searchParams.get("sort") ?? "composite") as SearchSort
    const sort: SearchSort = SEARCH_SORTS.has(sortParam) ? sortParam : "composite"

    const limit = numberParam(searchParams.get("limit"), 12)
    const offset = numberParam(searchParams.get("offset"), 0)

    searchCatalog({
      q,
      selectedGames: selected,
      min,
      max,
      onlyOnline: onlyOnlineParam,
      minRating: minRatingParam,
      sort,
      limit,
      offset,
      signal: controller.signal,
    })
      .then((res) => {
        if (controller.signal.aborted) return
        setResponse(res)
        setHasLoaded(true)
        setError(null)
      })
      .catch((err: unknown) => {
        if (controller.signal.aborted) return
        setError(err instanceof Error ? err.message : "Search request failed")
        setHasLoaded(true)
      })

    return () => controller.abort()
  }, [searchParams])

  const handleGameChange = (game: string, checked: boolean) => {
    const next = checked
      ? [...new Set([...selectedGames, game])]
      : selectedGames.filter((item) => item !== game)

    setSelectedGames(next)
    replaceUrl((params) => {
      params.delete("game")
      for (const value of next) params.append("game", value)
      resetPagination(params)
    })
  }

  const handlePriceChange = (type: "min" | "max", value: string) => {
    const next = { ...priceRange, [type]: value }

    setPriceRange(next)
    replaceUrl((params) => {
      if (next.min) params.set("min", next.min)
      else params.delete("min")
      if (next.max) params.set("max", next.max)
      else params.delete("max")
      resetPagination(params)
    })
  }

  const handleOnlineChange = (checked: boolean) => {
    setOnlyOnline(checked)
    replaceUrl((params) => {
      if (checked) params.set("online", "1")
      else params.delete("online")
      resetPagination(params)
    })
  }

  const handleRatingChange = (value: string) => {
    setMinRating(value)
    replaceUrl((params) => {
      if (value && value !== "0") params.set("minRating", value)
      else params.delete("minRating")
      resetPagination(params)
    })
  }

  const setSortAndSync = (next: SearchSort) => {
    setSortBy(next)
    replaceUrl((params) => {
      if (next === "composite") params.delete("sort")
      else params.set("sort", next)
      resetPagination(params)
    })
  }

  const resetFilters = () => {
    setSelectedGames([])
    setPriceRange({ min: "", max: "" })
    setOnlyOnline(false)
    setMinRating("0")
    replaceUrl((params) => {
      params.delete("game")
      params.delete("min")
      params.delete("max")
      params.delete("online")
      params.delete("minRating")
      resetPagination(params)
    })
  }

  const clearAllFilters = () => {
    setSearchQuery("")
    setSelectedGames([])
    setPriceRange({ min: "", max: "" })
    setOnlyOnline(false)
    setMinRating("0")
    replaceUrl((params) => {
      params.delete("q")
      params.delete("game")
      params.delete("min")
      params.delete("max")
      params.delete("online")
      params.delete("minRating")
      resetPagination(params)
    })
  }

  const items = response?.items ?? []
  const total = response?.meta.total ?? 0
  const canLoadMore = response ? response.items.length < response.meta.total : false

  return (
    <div className="container mx-auto px-4 py-6 min-h-screen">
      <div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-8">
        <div>
          <h1 className="text-3xl font-bold tracking-tight">寻找陪玩</h1>
          <p className="text-muted-foreground mt-1">找陪玩</p>
        </div>

        <div className="flex items-center gap-2 w-full md:w-auto">
          <div className="flex-1 md:w-80">
            <IconInput
              inputSize="lg"
              icon={<Search />}
              type="search"
              placeholder="搜索陪玩、游戏、标签..."
              className="border-border bg-card shadow-card transition-shadow focus:shadow-card-hover"
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
            />
          </div>

          <Sheet>
            <SheetTrigger asChild>
              <Button variant="outline" size="icon" className="md:hidden shrink-0 rounded-full">
                <Filter className="h-4 w-4" />
              </Button>
            </SheetTrigger>
            <SheetContent side="left" className="w-[300px] sm:w-[400px] overflow-y-auto">
              <SheetHeader>
                <SheetTitle>筛选条件</SheetTitle>
                <SheetDescription>试试其他筛选条件</SheetDescription>
              </SheetHeader>
              <div className="py-6">
                <FilterSection
                  games={games}
                  selectedGames={selectedGames}
                  onGameChange={handleGameChange}
                  priceRange={priceRange}
                  onPriceChange={handlePriceChange}
                  onlyOnline={onlyOnline}
                  onOnlineChange={handleOnlineChange}
                  minRating={minRating}
                  onRatingChange={handleRatingChange}
                />
              </div>
              <SheetFooter>
                <SheetClose asChild>
                  <Button className="w-full rounded-full">查看 {total} 个结果</Button>
                </SheetClose>
              </SheetFooter>
            </SheetContent>
          </Sheet>
        </div>
      </div>

      <div className="flex flex-col md:flex-row gap-8">
        <aside className="hidden md:block w-64 shrink-0 space-y-6">
          <Card className="sticky top-24">
            <CardHeader className="pb-3">
              <div className="flex items-center justify-between">
                <h3 className="font-semibold">筛选</h3>
                {(selectedGames.length > 0 ||
                  priceRange.min ||
                  priceRange.max ||
                  onlyOnline ||
                  minRating !== "0") && (
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-auto p-0 text-xs text-muted-foreground hover:text-primary"
                    onClick={() => {
                      resetFilters()
                    }}
                  >
                    重置
                  </Button>
                )}
              </div>
            </CardHeader>
            <CardContent>
              <FilterSection
                games={games}
                selectedGames={selectedGames}
                onGameChange={handleGameChange}
                priceRange={priceRange}
                onPriceChange={handlePriceChange}
                onlyOnline={onlyOnline}
                onOnlineChange={handleOnlineChange}
                minRating={minRating}
                onRatingChange={handleRatingChange}
              />
            </CardContent>
          </Card>
        </aside>

        <main className="flex-1">
          <div className="flex items-center justify-between mb-6 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 sticky top-0 z-10 py-2 md:static md:bg-transparent md:p-0">
            <div className="flex items-center gap-2 overflow-x-auto pb-2 md:pb-0 no-scrollbar">
              <Button
                variant={sortBy === "composite" ? "default" : "ghost"}
                size="sm"
                onClick={() => setSortAndSync("composite")}
                className="whitespace-nowrap rounded-full"
              >
                综合排序
              </Button>
              <Button
                variant={sortBy === "rating" ? "default" : "ghost"}
                size="sm"
                onClick={() => setSortAndSync("rating")}
                className="whitespace-nowrap rounded-full"
              >
                评分最高
              </Button>
              <Button
                variant={sortBy === "orders" ? "default" : "ghost"}
                size="sm"
                onClick={() => setSortAndSync("orders")}
                className="whitespace-nowrap rounded-full"
              >
                接单最多
              </Button>
              <Button
                variant={sortBy.startsWith("price") ? "default" : "ghost"}
                size="sm"
                onClick={() => setSortAndSync(sortBy === "price_asc" ? "price_desc" : "price_asc")}
                className="whitespace-nowrap gap-1 rounded-full"
              >
                价格
                <SlidersHorizontal className="w-3 h-3" />
              </Button>
            </div>
            <div className="text-sm text-muted-foreground hidden sm:block">
              共找到 {total} 位陪玩
            </div>
          </div>

          {!hasLoaded ? (
            <div className="flex items-center justify-center min-h-[400px]">
              <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
            </div>
          ) : items.length > 0 ? (
            <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
              {items.map((result) => (
                <div
                  key={
                    result.type === "player"
                      ? `player-${result.player.id}`
                      : `shop-${result.shop.id}`
                  }
                >
                  {result.type === "player" ? (
                    <PlayerCard player={result.player} />
                  ) : (
                    <ShopCard item={result} />
                  )}
                </div>
              ))}
            </div>
          ) : (
            <div className="text-center py-20 bg-muted/30 rounded-lg border border-dashed">
              <div className="mx-auto w-12 h-12 rounded-full bg-muted flex items-center justify-center mb-4">
                <Search className="w-6 h-6 text-muted-foreground" />
              </div>
              <h3 className="text-lg font-medium">未找到相关陪玩</h3>
              <p className="text-muted-foreground mt-1 max-w-sm mx-auto">
                {error ? "请求失败，请稍后重试" : "尝试调整筛选条件或更换搜索关键词"}
              </p>
              <Button
                variant="outline"
                className="mt-4 rounded-full"
                onClick={() => {
                  clearAllFilters()
                }}
              >
                清除所有筛选
              </Button>
            </div>
          )}

          {canLoadMore && (
            <div className="mt-8 text-center">
              <Button
                variant="outline"
                size="lg"
                className="rounded-full px-8"
                onClick={() => {
                  const currentLimit = numberParam(searchParams.get("limit"), DEFAULT_LIMIT)
                  replaceUrl((params) => {
                    params.set("limit", String(currentLimit + DEFAULT_LIMIT))
                    params.set("offset", "0")
                  })
                }}
              >
                加载更多
              </Button>
            </div>
          )}
        </main>
      </div>
    </div>
  )
}

export default function SearchPage() {
  return (
    <Suspense
      fallback={
        <div className="container mx-auto px-4 py-6 flex items-center justify-center min-h-[400px]">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
        </div>
      }
    >
      <SearchPageContent />
    </Suspense>
  )
}
