import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Row, Col, Card, Statistic, DatePicker, Spin, Grid, Collapse } from 'antd';
import {
  TeamOutlined,
  HomeOutlined,
  CheckCircleOutlined,
  BankOutlined,
  PercentageOutlined,
  UserSwitchOutlined,
  SolutionOutlined,
  FileProtectOutlined,
  ReadOutlined,
  CalendarOutlined,
  ArrowRightOutlined,
  ExclamationCircleOutlined,
  DollarOutlined,
} from '@ant-design/icons';
import ReactECharts, { type EChartsOption } from '../../components/ECharts';
import dayjs from 'dayjs';
import { useNavigate } from 'react-router-dom';
import api from '../../api';
import { message } from '../../ui/app-message';

const { RangePicker } = DatePicker;

const COLORS = [
  '#007AFF',
  '#34C759',
  '#FF9500',
  '#FF3B30',
  '#5AC8FA',
  '#AF52DE',
  '#FF2D55',
  '#FFCC00',
];

interface BillStatRow {
  status: string;
  count: string;
  total: string;
}
interface ClassAttendanceRank {
  className: string;
  present: number;
  total: number;
  rate: number;
}
interface ClassroomOccupancy {
  name: string;
  building: string;
  capacity: number;
  scheduleDays: number;
  rentalCount: number;
  occupancy: number;
}
interface ClassroomUtilStats {
  totalClassrooms: number;
  inUseCount: number;
  utilizationRate: string;
  scheduleCount: number;
  rentalCount: number;
}
interface AttendanceTrendRow {
  date: string;
  rate: string;
}
interface IncomeTrendRow {
  month: string;
  amount: number;
}
interface OccupancyByBuildingRow {
  building: string;
  count: string;
}
interface ExpenseByTypeRow {
  type: string;
  total: string;
}
interface GanttOccupancy {
  studentName: string;
  studentId?: string;
  checkInDate: string;
  checkOutDate: string | null;
  billingStartDate?: string;
  billingEndDate?: string;
}
interface GanttRoom {
  roomNumber: string;
  occupancies: GanttOccupancy[];
}

interface DashboardStats {
  totalRooms: number;
  totalStudents: number;
  occupiedBeds: number;
  totalCapacity: number;
  occupancyRate: string;
  billStats: BillStatRow[];
  classroomCount: number;
  classroomOccupancyRate: string;
  todayAttendanceRate: string;
  monthlyIncome: number;
  classCount: number;
  teacherCount: number;
  pendingDeposits: number;
  activeRentals: number;
  todayPresent: number;
  occupancyByBuilding: OccupancyByBuildingRow[];
  attendanceByStatus: Record<string, number>;
  expenseByType: ExpenseByTypeRow[];
  attendanceTrend: AttendanceTrendRow[];
  incomeTrend: IncomeTrendRow[];
}

const attendanceLabelMap: Record<string, string> = {
  present: '出勤',
  absent: '缺勤',
  late: '迟到',
  early: '早退',
  leave: '请假',
};

const SECTION_ROW_STYLE: React.CSSProperties = { marginBottom: 24 };
const MARGIN_BOTTOM_16_STYLE: React.CSSProperties = { marginBottom: 16 };

// ─── 待办卡片样式 ───
const TODO_CARD_BASE: React.CSSProperties = {
  cursor: 'pointer',
  transition: 'box-shadow 0.2s, transform 0.2s',
  borderRadius: 8,
  height: '100%',
};
const TODO_CARD_WARN: React.CSSProperties = {
  ...TODO_CARD_BASE,
  borderLeft: '4px solid #FF9500',
  background: '#fff7e6',
};
const TODO_CARD_DANGER: React.CSSProperties = {
  ...TODO_CARD_BASE,
  borderLeft: '4px solid #FF3B30',
  background: '#fff1f0',
};
const TODO_CARD_OK: React.CSSProperties = {
  ...TODO_CARD_BASE,
  borderLeft: '4px solid #34C759',
  background: '#f0fff4',
};
const TODO_CARD_DRAFT: React.CSSProperties = {
  ...TODO_CARD_BASE,
  borderLeft: '4px solid #AF52DE',
  background: '#f9f0ff',
};

// ─── IntersectionObserver 自定义 hook ───
// 用 callback ref 注册 observer，避免元素在首屏 loading 后才挂载、
// 而 effect 因依赖不变不再重跑导致 observer 从未注册的问题。
const useInViewport = (rootMargin = '200px') => {
  const [inView, setInView] = useState(false);
  const observerRef = useRef<IntersectionObserver | null>(null);

  const ref = useCallback(
    (el: HTMLDivElement | null) => {
      observerRef.current?.disconnect();
      if (!el) return;
      const observer = new IntersectionObserver(
        ([entry]) => {
          if (entry.isIntersecting) {
            setInView(true);
            observer.disconnect();
          }
        },
        { rootMargin },
      );
      observer.observe(el);
      observerRef.current = observer;
    },
    [rootMargin],
  );

  return { ref, inView };
};

const DashboardPage: React.FC = () => {
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.sm;
  const navigate = useNavigate();
  const [stats, setStats] = useState<DashboardStats | null>(null);
  const [classRanking, setClassRanking] = useState<{
    top: ClassAttendanceRank[];
    bottom: ClassAttendanceRank[];
  }>({ top: [], bottom: [] });
  const [classroomOccupancy, setClassroomOccupancy] = useState<ClassroomOccupancy[]>([]);
  const [ganttData, setGanttData] = useState<GanttRoom[]>([]);
  const [roomRanking, setRoomRanking] = useState<Array<{ roomNumber: string; total: string }>>([]);
  const [classroomUtil, setClassroomUtil] = useState<ClassroomUtilStats | null>(null);
  const [loading, setLoading] = useState(true);
  const [refreshLoading, setRefreshLoading] = useState(false);
  const loadedRef = useRef(false);
  const [period, setPeriod] = useState<[string, string]>([
    dayjs().startOf('month').format('YYYY-MM-DD'),
    dayjs().endOf('month').format('YYYY-MM-DD'),
  ]);

  const fetchData = useCallback(async () => {
    const isRefresh = loadedRef.current;
    if (isRefresh) {
      setRefreshLoading(true);
    } else {
      setLoading(true);
    }
    try {
      const [s, rr, cr, g] = await Promise.all([
        api.get<DashboardStats>('/dashboard/stats'),
        api.get<Array<{ roomNumber: string; total: string }>>('/dashboard/room-ranking', {
          params: { periodStart: period[0], periodEnd: period[1] },
        }),
        api.get<{ top: ClassAttendanceRank[]; bottom: ClassAttendanceRank[] }>(
          '/dashboard/class-attendance-ranking',
        ),
        api.get<GanttRoom[]>('/dashboard/gantt', {
          params: { periodStart: period[0], periodEnd: period[1] },
        }),
      ]);
      setStats(s);
      setRoomRanking(rr);
      setClassRanking(cr);
      setGanttData(g);
      const co = await api.get<ClassroomOccupancy[]>('/dashboard/classroom-occupancy');
      setClassroomOccupancy(co);
      const cu = await api.get<ClassroomUtilStats>('/dashboard/classroom-utilization');
      setClassroomUtil(cu);
      loadedRef.current = true;
    } catch (e) {
      console.error(e);
      message.error('数据加载失败，请稍后重试');
    }
    setLoading(false);
    setRefreshLoading(false);
  }, [period]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const [expenseTypeMap, setExpenseTypeMap] = useState<Record<string, string>>({});

  useEffect(() => {
    api
      .get<Array<{ code: string; name: string }>>('/expense-types')
      .then((types) => {
        const map: Record<string, string> = {};
        for (const t of types) map[t.code] = t.name;
        setExpenseTypeMap(map);
      })
      .catch(() => {});
  }, []);

  // ─── 图表 option 计算（保留全部原有逻辑） ───

  // 今日出勤状态分布环图
  const attendanceRingOption = useMemo<EChartsOption>(
    () => ({
      tooltip: { trigger: 'item' },
      legend: { bottom: 0 },
      series: [
        {
          type: 'pie',
          radius: ['40%', '70%'],
          center: ['50%', '45%'],
          data: Object.entries(stats?.attendanceByStatus ?? {}).map(([status, count]) => ({
            name: attendanceLabelMap[status] ?? status,
            value: count,
          })),
          itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
        },
      ],
      color: COLORS,
    }),
    [stats?.attendanceByStatus],
  );

  // 宿舍费用排行
  const barOption = useMemo<EChartsOption>(
    () => ({
      tooltip: {},
      grid: { left: 80, right: 20, bottom: 30, top: 10 },
      xAxis: { type: 'value' },
      yAxis: {
        type: 'category',
        data: roomRanking.map((r) => r.roomNumber).reverse(),
        inverse: false,
      },
      series: [
        {
          type: 'bar',
          data: roomRanking.map((r) => Number(r.total)).reverse(),
          itemStyle: { color: '#007AFF', borderRadius: [0, 4, 4, 0] },
        },
      ],
    }),
    [roomRanking],
  );

  // 班级考勤排行 - 前5
  const classRankingTopOption: EChartsOption = {
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'shadow' },
      valueFormatter: (v: number) => `${v}%`,
    },
    grid: { left: 80, right: 30, bottom: 30, top: 10 },
    xAxis: { type: 'value', max: 100, axisLabel: { formatter: '{value}%' } },
    yAxis: {
      type: 'category',
      data: classRanking.top.map((r) => r.className),
      inverse: true,
    },
    series: [
      {
        type: 'bar',
        data: classRanking.top.map((r) => r.rate),
        itemStyle: { color: '#34C759', borderRadius: [0, 4, 4, 0] },
        label: { show: true, position: 'right', formatter: '{c}%' },
      },
    ],
  };

  // 班级考勤排行 - 后5
  const classRankingBottomOption: EChartsOption = {
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'shadow' },
      valueFormatter: (v: number) => `${v}%`,
    },
    grid: { left: 80, right: 30, bottom: 30, top: 10 },
    xAxis: { type: 'value', max: 100, axisLabel: { formatter: '{value}%' } },
    yAxis: {
      type: 'category',
      data: classRanking.bottom.map((r) => r.className),
      inverse: true,
    },
    series: [
      {
        type: 'bar',
        data: classRanking.bottom.map((r) => r.rate),
        itemStyle: { color: '#FF3B30', borderRadius: [0, 4, 4, 0] },
        label: { show: true, position: 'right', formatter: '{c}%' },
      },
    ],
  };

  // 考勤趋势折线图
  const attendanceLineOption: EChartsOption = {
    tooltip: { trigger: 'axis' },
    grid: { left: 50, right: 20, bottom: 30, top: 10 },
    xAxis: {
      type: 'category',
      data: (stats?.attendanceTrend || []).map((d: { date: string }) => d.date),
      axisLabel: { rotate: 45, fontSize: 10 },
    },
    yAxis: { type: 'value', min: 0, max: 100, axisLabel: { formatter: '{value}%' } },
    series: [
      {
        type: 'line',
        data: (stats?.attendanceTrend || []).map((d: { rate: string }) => parseFloat(d.rate) || 0),
        smooth: true,
        lineStyle: { color: '#007AFF', width: 2 },
        itemStyle: { color: '#007AFF' },
        areaStyle: { color: 'rgba(0,122,255,0.1)' },
      },
    ],
  };

  // 收入趋势折线图
  const incomeLineOption: EChartsOption = {
    tooltip: { trigger: 'axis', valueFormatter: (v: number) => `¥${v.toLocaleString()}` },
    grid: { left: 70, right: 20, bottom: 30, top: 10 },
    xAxis: {
      type: 'category',
      data: (stats?.incomeTrend || []).map((d: { month: string }) => d.month),
    },
    yAxis: {
      type: 'value',
      axisLabel: { formatter: (v: number) => `¥${(v / 10000).toFixed(0)}万` },
    },
    series: [
      {
        type: 'line',
        data: (stats?.incomeTrend || []).map((d: { amount: number }) => d.amount),
        smooth: true,
        lineStyle: { color: '#34C759', width: 2 },
        itemStyle: { color: '#34C759' },
        areaStyle: { color: 'rgba(52,199,89,0.1)' },
      },
    ],
  };

  // 入住时间线（甘特图）
  const ganttOption = useMemo<EChartsOption>(
    () => ({
      tooltip: {
        formatter: (p: { data: { name: string; value: [string, string, string, boolean] } }) =>
          `${p.data.name}<br/>入住: ${p.data.value[1]}<br/>退宿: ${p.data.value[2]}`,
      },
      grid: { left: 100, right: 30, bottom: 40, top: 20 },
      xAxis: { type: 'time' },
      yAxis: { type: 'category', data: ganttData.map((r) => r.roomNumber), inverse: true },
      dataZoom: [
        { type: 'slider', xAxisIndex: 0, bottom: 10, height: 20 },
        { type: 'inside', xAxisIndex: 0 },
      ],
      series: [
        {
          type: 'custom',
          renderItem: (
            _params: unknown,
            api: {
              value: (i: number) => string | boolean;
              coord: (p: [string | number, string | number]) => [number, number];
              size: (p: [number, number]) => [number, number];
            },
          ) => {
            const [cat, startDate, endDate, isActive] = [
              api.value(0),
              api.value(1),
              api.value(2),
              api.value(3),
            ] as unknown as [string, string, string, boolean];
            const start = api.coord([startDate, cat]);
            const end = api.coord([endDate, cat]);
            const height = api.size([0, 1])[1] * 0.6;
            const rectShape = {
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height,
            };
            return {
              type: 'rect' as const,
              shape: rectShape,
              style: { fill: isActive ? '#34C759' : '#FF9500', stroke: '#fff', lineWidth: 1 },
            };
          },
          encode: { x: [1, 2], y: 0 },
          data: ganttData.flatMap((r) =>
            (r.occupancies || []).map((o) => ({
              name: o.studentName,
              value: [
                r.roomNumber,
                o.checkInDate,
                o.checkOutDate || new Date().toISOString().slice(0, 10),
                !o.checkOutDate,
              ] as [string, string, string, boolean],
            })),
          ),
        },
      ],
    }),
    [ganttData],
  );

  // ─── 懒加载 hooks ───
  const classroomHeatmapVp = useInViewport('200px');
  const ganttVp = useInViewport('200px');

  // ─── 待办卡片数据 ───
  const absentCount = stats?.attendanceByStatus?.['absent'] ?? 0;
  const draftBill = (stats?.billStats ?? []).find((b) => b.status === 'draft');
  const draftCount = draftBill ? Number(draftBill.count) : 0;
  const draftTotal = draftBill ? Number(draftBill.total) : 0;
  const pendingDeposits = stats?.pendingDeposits ?? 0;

  if (loading && !stats)
    return <Spin size="large" style={{ display: 'block', margin: '100px auto' }} />;

  return (
    <div>
      {/* ─── 顶部标题栏 ─── */}
      <div
        style={{
          marginBottom: 16,
          display: 'flex',
          justifyContent: 'space-between',
          alignItems: isMobile ? 'flex-start' : 'center',
          flexDirection: isMobile ? 'column' : 'row',
          gap: 12,
        }}
      >
        <h2 style={{ margin: 0 }}>
          工作台{refreshLoading && <Spin size="small" style={{ marginLeft: 12 }} />}
        </h2>
        <RangePicker
          aria-label="选择日期范围"
          value={[dayjs(period[0]), dayjs(period[1])]}
          onChange={(dates) => {
            if (dates) setPeriod([dates[0]!.format('YYYY-MM-DD'), dates[1]!.format('YYYY-MM-DD')]);
          }}
        />
      </div>

      {/* ═══════════ 待办与异常 ═══════════ */}
      <Card title="待办与异常" style={MARGIN_BOTTOM_16_STYLE}>
        <Row gutter={[16, 16]}>
          {/* 今日缺勤 */}
          <Col xs={24} sm={8}>
            <Card
              style={absentCount > 0 ? TODO_CARD_WARN : TODO_CARD_OK}
              styles={{ body: { padding: 16 } }}
              onClick={() => navigate('/attendance')}
            >
              <div
                style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
              >
                <ExclamationCircleOutlined
                  style={{ fontSize: 28, color: absentCount > 0 ? '#FF9500' : '#999' }}
                />
                <ArrowRightOutlined style={{ color: '#bbb' }} />
              </div>
              <div style={{ marginTop: 8 }}>
                <div
                  style={{
                    fontSize: 24,
                    fontWeight: 700,
                    color: absentCount > 0 ? '#FF9500' : '#999',
                  }}
                >
                  {absentCount}
                </div>
                <div style={{ fontSize: 13, color: '#666', marginTop: 2 }}>今日缺勤人数</div>
                {absentCount > 0 ? (
                  <div style={{ fontSize: 12, color: '#FF9500', marginTop: 4 }}>需要关注</div>
                ) : (
                  <div style={{ fontSize: 12, color: '#34C759', marginTop: 4 }}>全员到齐</div>
                )}
              </div>
            </Card>
          </Col>

          {/* 待处理账单 */}
          <Col xs={24} sm={8}>
            <Card
              style={draftCount > 0 ? TODO_CARD_DRAFT : TODO_CARD_OK}
              styles={{ body: { padding: 16 } }}
              onClick={() => navigate('/bills')}
            >
              <div
                style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
              >
                <DollarOutlined
                  style={{ fontSize: 28, color: draftCount > 0 ? '#AF52DE' : '#999' }}
                />
                <ArrowRightOutlined style={{ color: '#bbb' }} />
              </div>
              <div style={{ marginTop: 8 }}>
                <div
                  style={{
                    fontSize: 24,
                    fontWeight: 700,
                    color: draftCount > 0 ? '#AF52DE' : '#999',
                  }}
                >
                  {draftCount}
                </div>
                <div style={{ fontSize: 13, color: '#666', marginTop: 2 }}>待处理账单</div>
                <div
                  style={{ fontSize: 12, color: draftCount > 0 ? '#AF52DE' : '#999', marginTop: 4 }}
                >
                  {draftCount > 0 ? `合计 ¥${draftTotal.toLocaleString()}` : '暂无待处理'}
                </div>
              </div>
            </Card>
          </Col>

          {/* 待退押金 */}
          <Col xs={24} sm={8}>
            <Card
              style={pendingDeposits > 0 ? TODO_CARD_DANGER : TODO_CARD_OK}
              styles={{ body: { padding: 16 } }}
              onClick={() => navigate('/deposits')}
            >
              <div
                style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
              >
                <BankOutlined
                  style={{ fontSize: 28, color: pendingDeposits > 0 ? '#FF3B30' : '#999' }}
                />
                <ArrowRightOutlined style={{ color: '#bbb' }} />
              </div>
              <div style={{ marginTop: 8 }}>
                <div
                  style={{
                    fontSize: 24,
                    fontWeight: 700,
                    color: pendingDeposits > 0 ? '#FF3B30' : '#999',
                  }}
                >
                  ¥{pendingDeposits.toLocaleString()}
                </div>
                <div style={{ fontSize: 13, color: '#666', marginTop: 2 }}>待退押金</div>
                <div
                  style={{
                    fontSize: 12,
                    color: pendingDeposits > 0 ? '#FF3B30' : '#999',
                    marginTop: 4,
                  }}
                >
                  {pendingDeposits > 0 ? '需要处理' : '暂无待退'}
                </div>
              </div>
            </Card>
          </Col>
        </Row>
      </Card>

      {/* ═══════════ 核心 KPI ═══════════ */}
      <Row gutter={[16, 16]} style={SECTION_ROW_STYLE}>
        <Col xs={12} sm={8} md={4}>
          <Card>
            <Statistic
              title="入住率"
              value={stats?.occupancyRate || 0}
              suffix="%"
              prefix={<PercentageOutlined />}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card>
            <Statistic
              title="当前在住"
              value={stats?.occupiedBeds || 0}
              suffix={`/ ${stats?.totalCapacity || 0}`}
              prefix={<CheckCircleOutlined />}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card>
            <Statistic
              title="今日出勤率"
              value={stats?.todayAttendanceRate || 0}
              suffix="%"
              prefix={<UserSwitchOutlined />}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card>
            <Statistic
              title="教室占用率"
              value={stats?.classroomOccupancyRate || 0}
              suffix="%"
              prefix={<PercentageOutlined />}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card>
            <Statistic
              title="本月收入"
              value={stats?.monthlyIncome || 0}
              precision={2}
              prefix="¥"
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          {/* 占位：保持 6 列布局最后一个空位 */}
        </Col>
      </Row>

      {/* ═══════════ 更多指标（折叠） ═══════════ */}
      <Collapse
        ghost
        items={[
          {
            key: 'more-metrics',
            label: '更多指标',
            children: (
              <>
                <Row gutter={[16, 16]} style={SECTION_ROW_STYLE}>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="宿舍总数"
                        value={stats?.totalRooms || 0}
                        prefix={<HomeOutlined />}
                      />
                    </Card>
                  </Col>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="在读学生"
                        value={stats?.totalStudents || 0}
                        prefix={<TeamOutlined />}
                      />
                    </Card>
                  </Col>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="教室总数"
                        value={stats?.classroomCount || 0}
                        prefix={<BankOutlined />}
                      />
                    </Card>
                  </Col>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="班级总数"
                        value={stats?.classCount ?? 0}
                        prefix={<TeamOutlined />}
                      />
                    </Card>
                  </Col>
                </Row>
                <Row gutter={[16, 16]} style={SECTION_ROW_STYLE}>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="教师总数"
                        value={stats?.teacherCount ?? 0}
                        prefix={<SolutionOutlined />}
                      />
                    </Card>
                  </Col>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="待退押金"
                        value={stats?.pendingDeposits ?? 0}
                        precision={2}
                        prefix="¥"
                      />
                    </Card>
                  </Col>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="活跃租赁"
                        value={stats?.activeRentals ?? 0}
                        prefix={<FileProtectOutlined />}
                      />
                    </Card>
                  </Col>
                  <Col xs={12} sm={12} md={6}>
                    <Card>
                      <Statistic
                        title="今日出勤"
                        value={stats?.todayPresent ?? 0}
                        suffix="人"
                        prefix={<CheckCircleOutlined />}
                      />
                    </Card>
                  </Col>
                </Row>
                <Card title="教室利用率" style={MARGIN_BOTTOM_16_STYLE}>
                  <Row gutter={[24, 16]}>
                    <Col xs={12} sm={6}>
                      <Statistic
                        title="教室总数"
                        value={classroomUtil?.totalClassrooms ?? '-'}
                        prefix={<ReadOutlined />}
                      />
                    </Col>
                    <Col xs={12} sm={6}>
                      <Statistic
                        title="今日使用"
                        value={classroomUtil?.inUseCount ?? '-'}
                        prefix={<CheckCircleOutlined />}
                      />
                    </Col>
                    <Col xs={12} sm={6}>
                      <Statistic
                        title="利用率"
                        value={classroomUtil?.utilizationRate ?? '-'}
                        suffix="%"
                        prefix={<PercentageOutlined />}
                        styles={{
                          value: {
                            color:
                              Number(classroomUtil?.utilizationRate ?? 0) > 70
                                ? '#34C759'
                                : '#FF9500',
                          },
                        }}
                      />
                    </Col>
                    <Col xs={12} sm={6}>
                      <Statistic
                        title="内部排课"
                        value={classroomUtil?.scheduleCount ?? '-'}
                        prefix={<CalendarOutlined />}
                      />
                    </Col>
                  </Row>
                </Card>
              </>
            ),
          },
        ]}
      />

      {/* ═══════════ 图表：考勤趋势 + 出勤分布 ═══════════ */}
      <Row gutter={[16, 16]} style={SECTION_ROW_STYLE}>
        <Col xs={24} sm={12}>
          <Card title="考勤趋势（近30天）">
            {(stats?.attendanceTrend || []).length > 0 ? (
              <ReactECharts
                option={attendanceLineOption}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无考勤数据</div>
            )}
          </Card>
        </Col>
        <Col xs={24} sm={12}>
          <Card title="今日出勤状态分布">
            {Object.keys(stats?.attendanceByStatus ?? {}).length > 0 ? (
              <ReactECharts
                option={attendanceRingOption}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无考勤数据</div>
            )}
          </Card>
        </Col>
      </Row>

      {/* ═══════════ 图表：班级出勤排行 ═══════════ */}
      <Row gutter={[16, 16]} style={SECTION_ROW_STYLE}>
        <Col xs={24} sm={12}>
          <Card title="班级出勤率 TOP 5">
            {classRanking.top.length > 0 ? (
              <ReactECharts
                option={classRankingTopOption}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无考勤数据</div>
            )}
          </Card>
        </Col>
        <Col xs={24} sm={12}>
          <Card title="班级出勤率 末位 5">
            {classRanking.bottom.length > 0 ? (
              <ReactECharts
                option={classRankingBottomOption}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无考勤数据</div>
            )}
          </Card>
        </Col>
      </Row>

      {/* ═══════════ 图表：费用分布 + 宿舍排行 ═══════════ */}
      <Row gutter={[16, 16]} style={SECTION_ROW_STYLE}>
        <Col xs={24} sm={12}>
          <Card title="费用类型分布">
            {(stats?.expenseByType ?? []).length > 0 ? (
              <ReactECharts
                option={
                  {
                    tooltip: { trigger: 'item' },
                    legend: { bottom: 0 },
                    color: COLORS,
                    series: [
                      {
                        type: 'pie',
                        radius: ['40%', '70%'],
                        center: ['50%', '45%'],
                        data: (stats?.expenseByType ?? []).map((e) => ({
                          name: expenseTypeMap[e.type] ?? e.type,
                          value: Number(e.total),
                        })),
                      },
                    ],
                  } satisfies EChartsOption
                }
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无费用数据</div>
            )}
          </Card>
        </Col>
        <Col xs={24} sm={12}>
          <Card title="宿舍费用排行 TOP 20">
            {roomRanking.length > 0 ? (
              <ReactECharts
                option={barOption}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无费用数据</div>
            )}
          </Card>
        </Col>
      </Row>

      {/* ═══════════ 图表：月度收入趋势 ═══════════ */}
      <Row gutter={[16, 16]}>
        <Col xs={24}>
          <Card title="月度收入趋势">
            {(stats?.incomeTrend || []).length > 0 ? (
              <ReactECharts
                option={incomeLineOption}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无收入数据</div>
            )}
          </Card>
        </Col>
      </Row>

      {/* ═══════════ 图表：教室占用热力图（懒加载） ═══════════ */}
      <div ref={classroomHeatmapVp.ref} style={SECTION_ROW_STYLE}>
        {classroomHeatmapVp.inView ? (
          <Row gutter={[16, 16]}>
            <Col xs={24}>
              <Card title="教室占用热力图">
                {classroomOccupancy.length > 0 ? (
                  <ReactECharts
                    option={
                      {
                        tooltip: {
                          formatter: (p: {
                            name: string;
                            data: { scheduleDays: number; rentalCount: number; occupancy: number };
                          }) =>
                            `${p.name}<br/>排课: ${p.data.scheduleDays}天 租赁: ${p.data.rentalCount}个 占用率: ${(p.data.occupancy * 100).toFixed(0)}%`,
                        },
                        grid: { left: 100, right: 20, bottom: 30, top: 10 },
                        xAxis: { type: 'value', max: 1 },
                        yAxis: {
                          type: 'category',
                          data: classroomOccupancy.map((r) => r.name),
                          inverse: true,
                        },
                        visualMap: {
                          min: 0,
                          max: 1,
                          orient: 'horizontal',
                          left: 'center',
                          bottom: 0,
                          inRange: {
                            color: ['#e6f4ff', '#91caff', '#40a9ff', '#0050b3', '#002c8c'],
                          },
                        },
                        series: [
                          {
                            type: 'bar',
                            data: classroomOccupancy.map((r) => ({
                              name: r.name,
                              value: r.occupancy,
                              scheduleDays: r.scheduleDays,
                              rentalCount: r.rentalCount,
                              occupancy: r.occupancy,
                            })),
                            itemStyle: { borderRadius: [0, 4, 4, 0] },
                            label: {
                              show: true,
                              position: 'right',
                              formatter: (p: { data: { occupancy: number } }) =>
                                `${(p.data.occupancy * 100).toFixed(0)}%`,
                            },
                          },
                        ],
                      } satisfies EChartsOption
                    }
                    style={{ width: '100%', height: isMobile ? 300 : 400 }}
                  />
                ) : (
                  <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>
                    暂无教室数据
                  </div>
                )}
              </Card>
            </Col>
          </Row>
        ) : (
          <Card title="教室占用热力图" style={{ minHeight: isMobile ? 340 : 440 }}>
            <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>加载中…</div>
          </Card>
        )}
      </div>

      {/* ═══════════ 图表：入住时间线甘特图（懒加载） ═══════════ */}
      <div ref={ganttVp.ref}>
        {ganttVp.inView ? (
          <Row gutter={[16, 16]}>
            <Col xs={24}>
              <Card title="入住时间线（甘特图）">
                {ganttData.length > 0 ? (
                  <ReactECharts
                    option={ganttOption}
                    style={{ width: '100%', height: isMobile ? 300 : 450 }}
                  />
                ) : (
                  <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>
                    暂无入住数据
                  </div>
                )}
              </Card>
            </Col>
          </Row>
        ) : (
          <Card title="入住时间线（甘特图）" style={{ minHeight: isMobile ? 340 : 490 }}>
            <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>加载中…</div>
          </Card>
        )}
      </div>
    </div>
  );
};

export default DashboardPage;
