"use client"

import { useCallback, useMemo, useState } from "react"
import Link from "next/link"
import { Mail, MailOpen, Plus, Send, Inbox, Search, Loader2, ChevronLeft, ChevronRight, Star } from "lucide-react"
import { useTranslations } from "next-intl"
import { toast } from "sonner"

import { Badge } from "@/shared/components/ui/badge"
import { Button } from "@/shared/components/ui/button"
import { Card, CardContent, CardHeader } from "@/shared/components/ui/card"
import { EmptyState } from "@/shared/components/ui/empty-state"
import { Input } from "@/shared/components/ui/input"
import { Tabs, TabsList, TabsTrigger } from "@/shared/components/ui/tabs"
import { cn, formatDate } from "@/shared/lib/utils"
import { usePermission } from "@/shared/hooks/use-permission"
import { Permissions } from "@/shared/types/permissions"

import { getMessagesAction, toggleMessageStarAction } from "../actions"
import { useMessageSearch } from "../hooks/use-message-search"
import type { Message, MessageType } from "../types"

type Tab = "inbox" | "sent"

/** 客户端分页大小 */
const PAGE_SIZE = 20

export function MessageList({
  messages,
  currentUserId,
  initialType = "inbox",
}: {
  messages: Message[]
  currentUserId: string
  initialType?: MessageType
}) {
  const t = useTranslations("messages")
  const [tab, setTab] = useState<Tab>(initialType === "sent" ? "sent" : "inbox")
  const [currentPage, setCurrentPage] = useState(1)
  const [starredOverride, setStarredOverride] = useState<Record<string, boolean>>({})
  const [togglingStarId, setTogglingStarId] = useState<string | null>(null)
  const { hasPermission } = usePermission()
  const canSend = hasPermission(Permissions.MESSAGE_SEND)

  const { keyword, setKeyword, results, searching, isUsingInitial } = useMessageSearch({
    searchAction: getMessagesAction,
    tab,
  })

  // 客户端过滤仅在初始数据（type=all）时需要，搜索结果已由服务端按 tab 过滤
  const filtered = useMemo(() => {
    const displayMessages = isUsingInitial ? messages : (results ?? [])
    if (!isUsingInitial) return displayMessages
    if (tab === "inbox") return displayMessages.filter((m) => m.receiverId === currentUserId)
    return displayMessages.filter((m) => m.senderId === currentUserId)
  }, [messages, results, tab, currentUserId, isUsingInitial])

  // 客户端分页：超过 PAGE_SIZE 条时显示分页 UI
  const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE))
  const safePage = Math.min(currentPage, totalPages)
  const paged = filtered.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE)
  const showPagination = filtered.length > PAGE_SIZE

  // 切换 tab 或搜索时重置分页
  const handleTabChange = (v: string): void => {
    setTab(v as Tab)
    setCurrentPage(1)
  }

  const handleKeywordChange = (v: string): void => {
    setKeyword(v)
    setCurrentPage(1)
  }

  const getIsStarred = (m: Message): boolean => {
    const override = starredOverride[m.id]
    return override === undefined ? m.isStarred : override
  }

  const handleToggleStar = useCallback(
    async (e: React.MouseEvent, messageId: string, currentStarred: boolean): Promise<void> => {
      e.preventDefault()
      e.stopPropagation()
      setTogglingStarId(messageId)
      // 乐观更新
      setStarredOverride((prev) => ({ ...prev, [messageId]: !currentStarred }))
      try {
        const res = await toggleMessageStarAction(messageId)
        if (res.success) {
          toast.success(t("messages.starToggled"))
        } else {
          // 回滚
          setStarredOverride((prev) => ({ ...prev, [messageId]: currentStarred }))
          toast.error(res.message)
        }
      } catch {
        // 回滚
        setStarredOverride((prev) => ({ ...prev, [messageId]: currentStarred }))
        toast.error(t("messages.sendFailed"))
      } finally {
        setTogglingStarId(null)
      }
    },
    [t]
  )

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <Tabs value={tab} onValueChange={handleTabChange}>
          <TabsList>
            <TabsTrigger value="inbox" className="gap-2">
              <Inbox className="h-4 w-4" />
              {t("tabs.inbox")}
            </TabsTrigger>
            <TabsTrigger value="sent" className="gap-2">
              <Send className="h-4 w-4" />
              {t("tabs.sent")}
            </TabsTrigger>
          </TabsList>
        </Tabs>
        {canSend ? (
          <Button asChild>
            <Link href="/messages/compose">
              <Plus className="mr-2 h-4 w-4" />
              {t("actions.compose")}
            </Link>
          </Button>
        ) : null}
      </div>

      {/* 搜索框 */}
      <div className="relative">
        <Search className="text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2" aria-hidden="true" />
        <Input
          type="search"
          aria-label={t("search.placeholder")}
          placeholder={t("search.placeholder")}
          value={keyword}
          onChange={(e) => handleKeywordChange(e.target.value)}
          className="pl-9"
        />
        {searching ? (
          <Loader2 className="text-muted-foreground absolute right-3 top-1/2 size-4 -translate-y-1/2 animate-spin" aria-hidden="true" />
        ) : null}
      </div>

      {paged.length === 0 ? (
        <EmptyState
          title={tab === "inbox" ? t("empty.inboxEmpty") : t("empty.sentEmpty")}
          description={
            tab === "inbox"
              ? t("empty.inboxEmptyDesc")
              : t("empty.sentEmptyDesc")
          }
          icon={Mail}
          className="h-auto border-none shadow-none"
        />
      ) : (
        <>
          <div className="space-y-3">
            {paged.map((m) => {
              const isReceived = m.receiverId === currentUserId
              const counterpart = isReceived ? m.senderName : m.receiverName
              const unread = isReceived && !m.isRead
              const isStarred = getIsStarred(m)
              return (
                <Link key={m.id} href={`/messages/${m.id}`} className="block" aria-label={m.subject ?? t("meta.noSubject")}>
                  <Card className={cn("transition-colors hover:bg-accent/50", unread && "border-primary/40")}>
                    <CardHeader className="flex flex-row items-start justify-between gap-2 space-y-0 pb-3">
                      <div className="space-y-1">
                        <div className="flex items-center gap-2">
                          {unread ? (
                            <Mail className="h-4 w-4 text-primary" aria-hidden="true" />
                          ) : (
                            <MailOpen className="text-muted-foreground h-4 w-4" aria-hidden="true" />
                          )}
                          <span className={cn("text-sm font-medium", unread && "text-primary")}>
                            {m.subject ?? t("meta.noSubject")}
                          </span>
                          {unread ? <Badge variant="default" className="text-xs">{t("status.new")}</Badge> : null}
                          {isStarred ? (
                            <Star className="h-3.5 w-3.5 fill-yellow-400 text-yellow-400" aria-hidden="true" />
                          ) : null}
                        </div>
                        <p className="text-muted-foreground text-xs">
                          {isReceived ? t("meta.from") : t("meta.to")}: {counterpart ?? t("meta.unknown")}
                        </p>
                      </div>
                      <div className="flex shrink-0 items-center gap-1">
                        <button
                          type="button"
                          onClick={(e) => void handleToggleStar(e, m.id, isStarred)}
                          disabled={togglingStarId === m.id}
                          aria-label={isStarred ? t("actions.unstar") : t("actions.star")}
                          className="text-muted-foreground hover:text-foreground inline-flex size-7 items-center justify-center rounded-md transition-colors hover:bg-accent disabled:opacity-50"
                        >
                          <Star
                            className={cn(
                              "h-4 w-4 transition-colors",
                              isStarred && "fill-yellow-400 text-yellow-400"
                            )}
                          />
                        </button>
                        <span className="text-muted-foreground text-xs">
                          {formatDate(m.createdAt)}
                        </span>
                      </div>
                    </CardHeader>
                    <CardContent className="pt-0">
                      <p className="text-muted-foreground line-clamp-2 text-sm whitespace-pre-wrap">
                        {m.content}
                      </p>
                    </CardContent>
                  </Card>
                </Link>
              )
            })}
          </div>

          {showPagination ? (
            <div className="flex items-center justify-center gap-4 pt-2" role="navigation" aria-label={t("tabs.inbox")}>
              <Button
                variant="outline"
                size="sm"
                onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
                disabled={safePage <= 1}
                aria-label="Previous page"
              >
                <ChevronLeft className="h-4 w-4" />
              </Button>
              <span className="text-muted-foreground text-sm" aria-live="polite">
                {safePage} / {totalPages}
              </span>
              <Button
                variant="outline"
                size="sm"
                onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
                disabled={safePage >= totalPages}
                aria-label="Next page"
              >
                <ChevronRight className="h-4 w-4" />
              </Button>
            </div>
          ) : null}
        </>
      )}
    </div>
  )
}
