import React, { useCallback, useEffect, useState } from 'react';
import dayjs from 'dayjs';
import { validateResponse } from '../../utils/validate';
import { notificationsSchema } from '../../api/schemas';
import { List, Typography, Menu, Layout, Button, Spin, Space, Grid, Select } from 'antd';
import {
  BellOutlined,
  DollarOutlined,
  HomeOutlined,
  TeamOutlined,
  SettingOutlined,
} from '@ant-design/icons';
import { useNavigate } from 'react-router';
import api from '../../api';
import { message } from '../../ui/app-message';
import { formatNotificationText } from '../../utils/notification-display';
import { QueryErrorState, QueryEmpty } from '../../components/QueryState';

const { Sider, Content } = Layout;
const { useBreakpoint } = Grid;

const PAGE_SIZE = 50;

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

const typeMap: Record<string, { label: string; icon: React.ReactNode }> = {
  bill_generated: { label: '账单', icon: <DollarOutlined /> },
  bill_paid: { label: '账单', icon: <DollarOutlined /> },
  check_in: { label: '入住', icon: <HomeOutlined /> },
  check_out: { label: '退宿', icon: <HomeOutlined /> },
  deposit_due: { label: '押金', icon: <DollarOutlined /> },
  deposit_refunded: { label: '押金', icon: <DollarOutlined /> },
  class_change: { label: '班级', icon: <TeamOutlined /> },
  schedule_conflict: { label: '排课', icon: <BellOutlined /> },
  announcement: { label: '公告', icon: <SettingOutlined /> },
};

function timeAgo(dateStr: string): string {
  const diff = Date.now() - dayjs(dateStr).valueOf();
  if (diff < 60_000) return '刚刚';
  // 7 天内用相对时间（dayjs relativeTime 已全局配置），更早显示具体日期
  if (diff < 7 * 86_400_000) return dayjs(dateStr).fromNow();
  return dayjs(dateStr).format('YYYY/M/D');
}

const FILTER_ITEMS: Array<{ key: string; icon: React.ReactNode; label: string }> = [
  { key: 'all', icon: <BellOutlined />, label: '全部' },
  { key: 'bill_generated', icon: <DollarOutlined />, label: '账单' },
  { key: 'check_in', icon: <HomeOutlined />, label: '入住' },
  { key: 'class_change', icon: <TeamOutlined />, label: '班级' },
  { key: 'announcement', icon: <SettingOutlined />, label: '公告' },
];

const NotificationsPage: React.FC = () => {
  const screens = useBreakpoint();
  const isMobile = !screens.sm;
  const [filter, setFilter] = useState('all');
  const navigate = useNavigate();

  const [notifications, setNotifications] = useState<NotificationItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState(false);
  const [hasMore, setHasMore] = useState(true);

  const loadPage = useCallback(async (after?: number) => {
    if (after === undefined) {
      setLoading(true);
    } else {
      setLoadingMore(true);
    }
    setError(false);
    try {
      const params =
        after !== undefined ? `?after=${after}&limit=${PAGE_SIZE}` : `?limit=${PAGE_SIZE}`;
      const res = validateResponse<NotificationItem[]>(
        notificationsSchema,
        await api.get(`/notifications${params}`),
      );
      setNotifications((prev) => (after === undefined ? res : [...prev, ...res]));
      setHasMore(res.length === PAGE_SIZE);
    } catch (e: any) {
      console.error('加载通知失败', e);
      setError(true);
    } finally {
      setLoading(false);
      setLoadingMore(false);
    }
  }, []);

  useEffect(() => {
    void loadPage();
  }, [loadPage]);

  const loadMore = () => {
    const last = notifications[notifications.length - 1];
    if (!last || loadingMore || loading) return;
    // 列表按 createdAt DESC 排序，最后一条 id 最小，作为下一页游标
    void loadPage(last.id);
  };

  const handleClick = async (item: NotificationItem) => {
    if (!item.isRead) {
      try {
        await api.put(`/notifications/${item.id}/read`);
        setNotifications((prev) =>
          prev.map((n) => (n.id === item.id ? { ...n, isRead: true } : n)),
        );
      } catch (e: any) {
        console.error('标记已读失败', e);
        message.error(e?.message || '标记已读失败');
      }
    }
    if (item.link) navigate(item.link);
  };

  const handleMarkAll = async () => {
    try {
      await api.put('/notifications/read-all');
      setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));
    } catch (e: any) {
      console.error('全部已读失败', e);
      message.error(e?.message || '操作失败');
    }
  };

  const filtered =
    filter === 'all' ? notifications : notifications.filter((n) => n.type === filter);

  return (
    <Layout className="notifications-layout" style={{ minHeight: '100%', background: '#fff' }}>
      {!isMobile && (
        <Sider width={180} style={{ background: '#fff', borderRight: '1px solid #f0f0f0' }}>
          <Menu
            mode="inline"
            selectedKeys={[filter]}
            onClick={({ key }) => setFilter(key)}
            items={FILTER_ITEMS}
          />
        </Sider>
      )}
      <Content className="notifications-content" style={{ padding: isMobile ? 0 : 24 }}>
        <div className="notifications-header">
          <Typography.Title level={4} style={{ margin: 0 }}>
            通知中心
          </Typography.Title>
          <Button onClick={handleMarkAll}>全部已读</Button>
        </div>
        {isMobile && (
          <Select
            value={filter}
            onChange={setFilter}
            options={FILTER_ITEMS.map((item) => ({ value: item.key, label: item.label }))}
            className="notifications-filter"
          />
        )}
        {error && !loading ? (
          <QueryErrorState
            title="通知加载失败"
            description="请检查网络后重试。"
            onRetry={() => void loadPage()}
          />
        ) : (
          <Spin spinning={loading}>
            {filtered.length === 0 ? (
              <QueryEmpty description="暂无通知，有新消息时会在这里提醒你" />
            ) : (
              <List
                dataSource={filtered}
                renderItem={(item) => {
                  const meta = typeMap[item.type] || { label: item.type, icon: <BellOutlined /> };
                  return (
                    <List.Item
                      role="button"
                      tabIndex={0}
                      aria-label={`通知: ${item.title}`}
                      onClick={() => handleClick(item)}
                      onKeyDown={(e) => {
                        if (e.key === 'Enter' || e.key === ' ') {
                          e.preventDefault();
                          handleClick(item);
                        }
                      }}
                      style={{
                        cursor: 'pointer',
                        padding: '16px 0',
                        backgroundColor: item.isRead ? 'transparent' : '#f0f7ff',
                      }}
                    >
                      <List.Item.Meta
                        avatar={
                          <div
                            style={{
                              width: 40,
                              height: 40,
                              borderRadius: '50%',
                              background: '#f0f0f0',
                              display: 'flex',
                              alignItems: 'center',
                              justifyContent: 'center',
                            }}
                          >
                            {meta.icon}
                          </div>
                        }
                        title={
                          <Space wrap size={[8, 2]}>
                            <Typography.Text strong={!item.isRead} style={{ fontSize: 15 }}>
                              {formatNotificationText(item.title)}
                            </Typography.Text>
                            <Typography.Text type="secondary" style={{ fontSize: 12 }}>
                              {timeAgo(item.createdAt)}
                            </Typography.Text>
                          </Space>
                        }
                        description={
                          item.content && (
                            <Typography.Paragraph
                              type="secondary"
                              ellipsis={{ rows: 1 }}
                              style={{ marginBottom: 0 }}
                            >
                              {formatNotificationText(item.content)}
                            </Typography.Paragraph>
                          )
                        }
                      />
                    </List.Item>
                  );
                }}
              />
            )}
            {filtered.length > 0 && hasMore && (
              <div style={{ textAlign: 'center', padding: '16px 0' }}>
                <Button loading={loadingMore} onClick={loadMore}>
                  加载更多
                </Button>
              </div>
            )}
          </Spin>
        )}
      </Content>
    </Layout>
  );
};

export default NotificationsPage;
