import { useCallback, useEffect, useRef, useState } from "react"
import { useNavigate } from "react-router-dom"
import { Badge, Button, Empty, Modal, Popover, Space, Spin, Typography } from "antd"
import { BellOutlined } from "@ant-design/icons"
import {
  getUnreadCount,
  listNotifications,
  markNotificationRead,
  type NotificationItem,
} from "../api/notifications"

const { Paragraph, Text } = Typography

const POLL_INTERVAL = 3_000

const CATEGORY_DOT: Record<string, string> = {
  order: "#1677ff",
  instance: "#52c41a",
  finance: "#fa8c16",
  ticket: "#722ed1",
  promotion: "#eb2f96",
  membership: "#13c2c2",
  system: "#8c8c8c",
}

function relativeTime(value: string | null) {
  if (!value) return ""
  const then = new Date(value).getTime()
  const diff = Date.now() - then
  const min = Math.floor(diff / 60000)
  if (min < 1) return "刚刚"
  if (min < 60) return `${min} 分钟前`
  const hr = Math.floor(min / 60)
  if (hr < 24) return `${hr} 小时前`
  const day = Math.floor(hr / 24)
  if (day < 30) return `${day} 天前`
  return new Date(value).toLocaleDateString("zh-CN")
}

function formatDateTime(value: string | null) {
  if (!value) return "-"
  return new Date(value).toLocaleString("zh-CN", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  })
}

function senderName(item: NotificationItem) {
  return item.sender_name || item.source_label || "系统通知"
}

function actionOf(item: NotificationItem) {
  const url = item.action?.url || item.action_url || item.link
  const label = item.action?.label || item.action_label || "前往处理"
  return url ? { label, url } : null
}

export default function NotificationBell() {
  const navigate = useNavigate()
  const [total, setTotal] = useState(0)
  const [recent, setRecent] = useState<NotificationItem[]>([])
  const [viewing, setViewing] = useState<NotificationItem | null>(null)
  const [loading, setLoading] = useState(false)
  const [open, setOpen] = useState(false)
  const timerRef = useRef<number | null>(null)

  const refreshCount = useCallback(async () => {
    try {
      const data = await getUnreadCount()
      setTotal(data.total)
    } catch {
      // 静默：未登录或网络异常时不打扰用户
    }
  }, [])

  const loadRecent = useCallback(async () => {
    setLoading(true)
    try {
      const data = await listNotifications({ limit: 5, offset: 0 })
      setRecent(data.items)
    } catch {
      setRecent([])
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    void refreshCount()
    timerRef.current = window.setInterval(() => void refreshCount(), POLL_INTERVAL)
    return () => {
      if (timerRef.current) window.clearInterval(timerRef.current)
    }
  }, [refreshCount])

  const handleOpenChange = (next: boolean) => {
    setOpen(next)
    if (next) void loadRecent()
  }

  const handleClickItem = async (item: NotificationItem) => {
    const readItem = item.is_read
      ? item
      : { ...item, is_read: true, read_at: item.read_at ?? new Date().toISOString() }

    setOpen(false)
    setViewing(readItem)

    if (!item.is_read) {
      setRecent((items) => items.map((current) => (current.id === item.id ? readItem : current)))
      try {
        await markNotificationRead(item.id)
        void refreshCount()
      } catch {
        // ignore
      }
    }
  }

  const panel = (
    <div style={{ width: 340 }}>
      <div style={{ padding: "10px 16px", borderBottom: "1px solid #f0f0f0", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
        <Text strong>通知</Text>
        <Button type="link" size="small" style={{ padding: 0 }} onClick={() => { setOpen(false); navigate("/notifications") }}>
          查看全部
        </Button>
      </div>
      <div style={{ maxHeight: 360, overflowY: "auto" }}>
        {loading ? (
          <div style={{ padding: 32, textAlign: "center" }}><Spin /></div>
        ) : recent.length === 0 ? (
          <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无通知" style={{ padding: 24 }} />
        ) : (
          recent.map((item) => (
            <div
              key={item.id}
              onClick={() => void handleClickItem(item)}
              style={{
                padding: "10px 16px",
                borderBottom: "1px solid #f5f5f5",
                cursor: "pointer",
                background: item.is_read ? "#fff" : "#f0f7ff",
                display: "flex",
                gap: 8,
              }}
            >
              <span
                style={{
                  flex: "0 0 auto",
                  width: 8,
                  height: 8,
                  borderRadius: "50%",
                  marginTop: 6,
                  background: CATEGORY_DOT[item.category] ?? CATEGORY_DOT.system,
                }}
              />
              <div style={{ flex: 1, minWidth: 0 }}>
                <Text strong={!item.is_read} style={{ fontSize: 13, display: "block" }} ellipsis>{item.title}</Text>
                <Text type="secondary" style={{ fontSize: 12, display: "block" }} ellipsis>{item.content}</Text>
                <Text type="secondary" style={{ fontSize: 11 }}>
                  {senderName(item)} · {relativeTime(item.created_at)}
                </Text>
              </div>
            </div>
          ))
        )}
      </div>
    </div>
  )

  return (
    <>
      <Popover
        open={open}
        onOpenChange={handleOpenChange}
        placement="bottomRight"
        trigger="click"
        content={panel}
        styles={{ content: { padding: 0, overflow: "hidden" } }}
      >
        <Badge count={total} size="small" overflowCount={99}>
          <Button type="text" icon={<BellOutlined style={{ fontSize: 18 }} />} />
        </Badge>
      </Popover>

      <Modal
        open={!!viewing}
        title={viewing?.title}
        footer={
          <Space>
            {viewing && actionOf(viewing) && (
              <Button
                type="primary"
                onClick={() => {
                  const action = actionOf(viewing)
                  setViewing(null)
                  if (action?.url) navigate(action.url)
                }}
              >
                {actionOf(viewing)?.label}
              </Button>
            )}
            <Button onClick={() => setViewing(null)}>关闭</Button>
          </Space>
        }
        onCancel={() => setViewing(null)}
        width={640}
        style={{ maxWidth: "92vw" }}
        destroyOnHidden
      >
        {viewing && (
          <>
            <Text type="secondary" style={{ display: "block", marginBottom: 14, fontSize: 13 }}>
              {senderName(viewing)} · {formatDateTime(viewing.created_at)}
            </Text>
            <Paragraph style={{ marginBottom: 0, whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
              {viewing.content || "暂无内容"}
            </Paragraph>
          </>
        )}
      </Modal>
    </>
  )
}
