import React, { useState, useEffect, useRef } from 'react';
import { Badge, Popover, Button, List, Typography, Empty } from 'antd';
import { BellOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import api from '../api';
import { formatNotificationText, notificationTypeLabels } from '../utils/notification-display';

interface NotificationItem {
  id: number;
  type: string;
  title: string;
  content: string;
  link: string | null;
  isRead: boolean;
  createdAt: string;
}

function timeAgo(dateStr: string): string {
  const diff = Date.now() - new Date(dateStr).getTime();
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return '刚刚';
  if (mins < 60) return `${mins}分钟前`;
  const hours = Math.floor(mins / 60);
  if (hours < 24) return `${hours}小时前`;
  const days = Math.floor(hours / 24);
  return `${days}天前`;
}

const NotificationBell: React.FC = () => {
  const [unreadCount, setUnreadCount] = useState(0);
  const [notifications, setNotifications] = useState<NotificationItem[]>([]);
  const [open, setOpen] = useState(false);
  const navigate = useNavigate();

  const fetchNotifications = async () => {
    try {
      const data = (await api.get('/notifications?limit=20')) as unknown as NotificationItem[];
      setNotifications(data);
    } catch {
      /* ignore */
    }
  };

  const fetchUnread = async () => {
    try {
      const data = (await api.get('/notifications/unread-count')) as unknown as { count: number };
      setUnreadCount(data.count);
    } catch {
      /* ignore */
    }
  };
  const openRef = useRef(open);
  openRef.current = open;
  const retryRef = useRef<number | null>(null);

  // SSE connection — decoupled from popover open state
  useEffect(() => {
    fetchUnread();
    const token = localStorage.getItem('token');
    if (!token) return;
    const es = new EventSource(`/api/notifications/stream?token=${encodeURIComponent(token)}`);
    es.onmessage = (event) => {
      try {
        JSON.parse(event.data);
        setUnreadCount((c) => c + 1);
        if (openRef.current) fetchNotifications();
      } catch {
        /* ignore */
      }
    };
    es.onerror = () => {
      es.close();
      if (retryRef.current !== null) clearInterval(retryRef.current);
      retryRef.current = window.setInterval(fetchUnread, 60_000);
    };
    return () => {
      es.close();
      clearInterval(retryRef.current ?? undefined);
      retryRef.current = null;
    };
  }, []);

  const handleOpen = (visible: boolean) => {
    setOpen(visible);
    if (visible) fetchNotifications();
  };

  const handleClick = async (item: NotificationItem) => {
    if (!item.isRead) {
      try {
        await api.put(`/notifications/${item.id}/read`);
        setUnreadCount((c) => Math.max(0, c - 1));
      } catch {
        /* ignore */
      }
    }
    setOpen(false);
    if (item.link) navigate(item.link);
  };

  const handleMarkAll = async () => {
    try {
      await api.put('/notifications/read-all');
      setUnreadCount(0);
      setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));
    } catch {
      /* ignore */
    }
  };

  const content = (
    <div style={{ width: 380, maxHeight: 480 }}>
      <div
        style={{
          display: 'flex',
          justifyContent: 'space-between',
          alignItems: 'center',
          padding: '12px 16px',
          borderBottom: '1px solid #f0f0f0',
        }}
      >
        <Typography.Text strong>通知中心</Typography.Text>
        <Button type="link" size="small" onClick={handleMarkAll}>
          全部已读
        </Button>
      </div>
      {notifications.length === 0 ? (
        <div style={{ padding: 40 }}>
          <Empty description="暂无通知" />
        </div>
      ) : (
        <List
          style={{ maxHeight: 380, overflow: 'auto' }}
          dataSource={notifications}
          renderItem={(item) => (
            <List.Item
              onClick={() => handleClick(item)}
              style={{
                padding: '12px 16px',
                cursor: 'pointer',
                backgroundColor: item.isRead ? 'transparent' : '#f0f7ff',
              }}
            >
              <List.Item.Meta
                avatar={
                  !item.isRead && (
                    <div
                      style={{
                        width: 8,
                        height: 8,
                        borderRadius: '50%',
                        backgroundColor: '#007aff',
                        marginTop: 6,
                      }}
                    />
                  )
                }
                title={
                  <Typography.Text strong={!item.isRead} style={{ fontSize: 14 }}>
                    [{notificationTypeLabels[item.type] || item.type}]{' '}
                    {formatNotificationText(item.title)}
                  </Typography.Text>
                }
                description={
                  <Typography.Text type="secondary" style={{ fontSize: 12 }}>
                    {timeAgo(item.createdAt)}
                  </Typography.Text>
                }
              />
            </List.Item>
          )}
        />
      )}
      <div
        style={{
          borderTop: '1px solid #f0f0f0',
          padding: '8px 16px',
          textAlign: 'center',
        }}
      >
        <Button
          type="link"
          size="small"
          onClick={() => {
            setOpen(false);
            navigate('/notifications');
          }}
        >
          查看全部 →
        </Button>
      </div>
    </div>
  );

  return (
    <Popover
      content={content}
      trigger="click"
      open={open}
      onOpenChange={handleOpen}
      placement="bottomRight"
    >
      <Badge count={unreadCount} size="small" offset={[-2, 2]}>
        <BellOutlined style={{ fontSize: 18, cursor: 'pointer' }} />
      </Badge>
    </Popover>
  );
};

export default NotificationBell;
