import React, { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { validateResponse } from '../../utils/validate';
import {
  classAttendanceRankingSchema,
  classroomOccupanciesSchema,
  classroomUtilStatsSchema,
  dashboardStatsSchema,
  expenseTypesSchema,
  ganttRoomsSchema,
  roomRankingSchema,
} from '../../api/schemas';
import { Row, Col, Card, Statistic, DatePicker, Spin, Grid, Collapse } from 'antd';
import {
  TeamOutlined,
  HomeOutlined,
  CheckCircleOutlined,
  BankOutlined,
  PercentageOutlined,
  UserSwitchOutlined,
  SolutionOutlined,
  FileProtectOutlined,
  ReadOutlined,
  CalendarOutlined,
} from '@ant-design/icons';
import ReactECharts from '../../components/ECharts';
import dayjs from 'dayjs';
import api from '../../api';
import { message } from '../../ui/app-message';
import {
  buildAttendanceLineOption,
  buildAttendanceRingOption,
  buildClassRankingOption,
  buildExpensePieOption,
  buildIncomeLineOption,
  buildRoomRankingBarOption,
} from './DashboardCharts';
import { ClassroomHeatmapCard, GanttCard } from './DashboardLazyCards';
import {
  MARGIN_BOTTOM_16_STYLE,
  SECTION_ROW_STYLE,
  type ClassAttendanceRank,
  type ClassroomOccupancy,
  type ClassroomUtilStats,
  type DashboardStats,
  type GanttRoom,
} from './Dashboard.types';
import { DashboardTodoCards } from './DashboardTodoCards';

const { RangePicker } = DatePicker;

const DashboardPage: React.FC = () => {
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.sm;
  const [period, setPeriod] = useState<[string, string]>([
    dayjs().startOf('month').format('YYYY-MM-DD'),
    dayjs().endOf('month').format('YYYY-MM-DD'),
  ]);

  const {
    data: fetchResult = {
      stats: null,
      classRanking: { top: [], bottom: [] },
      classroomOccupancy: [],
      ganttData: [],
      roomRanking: [],
      classroomUtil: null,
    },
    isLoading,
    isFetching,
  } = useQuery<{
    stats: DashboardStats | null;
    classRanking: { top: ClassAttendanceRank[]; bottom: ClassAttendanceRank[] };
    classroomOccupancy: ClassroomOccupancy[];
    ganttData: GanttRoom[];
    roomRanking: Array<{ roomNumber: string; total: string }>;
    classroomUtil: ClassroomUtilStats | null;
  }>({
    queryKey: ['dashboard', period],
    queryFn: async () => {
      // 各数据接口独立加载：单个接口失败只影响对应模块，避免整页数据被清零
      const settled = await Promise.allSettled([
        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] },
        }),
        api.get<ClassroomOccupancy[]>('/dashboard/classroom-occupancy'),
        api.get<ClassroomUtilStats>('/dashboard/classroom-utilization'),
      ]);
      const value = <T,>(r: PromiseSettledResult<T>): T | null =>
        r.status === 'fulfilled' ? r.value : null;
      const rejected = settled.filter((r) => r.status === 'rejected');
      if (rejected.length === settled.length) {
        // 全部失败：抛出让 react-query 自动重试
        console.error('看板数据加载失败', rejected);
        throw new Error('看板数据加载失败');
      }
      if (rejected.length > 0) {
        console.error('部分看板数据加载失败', rejected);
        message.warning(`有 ${rejected.length} 项数据加载失败，其余数据已正常显示`);
      }
      let stats: DashboardStats | null = null;
      const s = value(settled[0]);
      if (s) {
        try {
          stats = validateResponse<DashboardStats>(dashboardStatsSchema, s);
        } catch (e) {
          console.error(e);
        }
      }
      let roomRanking: Array<{ roomNumber: string; total: string }> = [];
      const rr = value(settled[1]);
      if (rr) {
        try {
          roomRanking = validateResponse<Array<{ roomNumber: string; total: string }>>(
            roomRankingSchema,
            rr,
          );
        } catch (e) {
          console.error(e);
        }
      }
      let classRanking: { top: ClassAttendanceRank[]; bottom: ClassAttendanceRank[] } = {
        top: [],
        bottom: [],
      };
      const cr = value(settled[2]);
      if (cr) {
        try {
          classRanking = validateResponse<{
            top: ClassAttendanceRank[];
            bottom: ClassAttendanceRank[];
          }>(classAttendanceRankingSchema, cr);
        } catch (e) {
          console.error(e);
        }
      }
      let ganttData: GanttRoom[] = [];
      const g = value(settled[3]);
      if (g) {
        try {
          ganttData = validateResponse<GanttRoom[]>(ganttRoomsSchema, g);
        } catch (e) {
          console.error(e);
        }
      }
      let classroomOccupancy: ClassroomOccupancy[] = [];
      const co = value(settled[4]);
      if (co) {
        try {
          classroomOccupancy = validateResponse<ClassroomOccupancy[]>(
            classroomOccupanciesSchema,
            co,
          );
        } catch (e) {
          console.error(e);
        }
      }
      let classroomUtil: ClassroomUtilStats | null = null;
      const cu = value(settled[5]);
      if (cu) {
        try {
          classroomUtil = validateResponse<ClassroomUtilStats>(classroomUtilStatsSchema, cu);
        } catch (e) {
          console.error(e);
        }
      }
      return { stats, classRanking, classroomOccupancy, ganttData, roomRanking, classroomUtil };
    },
  });
  const stats = fetchResult.stats;
  const classRanking = fetchResult.classRanking;
  const classroomOccupancy = fetchResult.classroomOccupancy;
  const ganttData = fetchResult.ganttData;
  const roomRanking = fetchResult.roomRanking;
  const classroomUtil = fetchResult.classroomUtil;
  const loading = isLoading;
  const refreshLoading = isFetching && !isLoading;

  const { data: expenseTypeMap = {} } = useQuery<Record<string, string>>({
    queryKey: ['expense-types', 'map'],
    queryFn: async () => {
      try {
        const types = validateResponse<Array<{ code: string; name: string }>>(
          expenseTypesSchema,
          await api.get<Array<{ code: string; name: string }>>('/expense-types'),
        );
        const map: Record<string, string> = {};
        for (const t of types) map[t.code] = t.name;
        return map;
      } catch {
        return {};
      }
    },
  });

  const absentCount = stats?.attendanceByStatus?.['absent'] ?? 0;
  const attendanceTotal = stats
    ? Object.values(stats.attendanceByStatus).reduce((sum, n) => sum + Number(n || 0), 0)
    : 0;
  const presentCount = stats?.attendanceByStatus?.present ?? 0;
  const todayAttendanceRate =
    stats?.todayAttendanceRate ??
    (attendanceTotal > 0 ? ((presentCount / attendanceTotal) * 100).toFixed(1) : '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?.[0] && dates?.[1])
              setPeriod([dates[0].format('YYYY-MM-DD'), dates[1].format('YYYY-MM-DD')]);
          }}
        />
      </div>

      {/* 待办与异常 */}
      <DashboardTodoCards
        absentCount={absentCount}
        draftCount={draftCount}
        draftTotal={draftTotal}
        pendingDeposits={pendingDeposits}
      />

      {/* 核心 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={todayAttendanceRate}
              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={buildAttendanceLineOption(stats?.attendanceTrend ?? [])}
                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={buildAttendanceRingOption(stats)}
                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={buildClassRankingOption(classRanking.top, '#34C759')}
                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={buildClassRankingOption(classRanking.bottom, '#FF3B30')}
                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={buildExpensePieOption(stats?.expenseByType ?? [], expenseTypeMap)}
                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={buildRoomRankingBarOption(roomRanking)}
                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={buildIncomeLineOption(stats?.incomeTrend ?? [])}
                style={{ width: '100%', height: isMobile ? 250 : 300 }}
              />
            ) : (
              <div style={{ textAlign: 'center', padding: 40, color: '#999' }}>暂无收入数据</div>
            )}
          </Card>
        </Col>
      </Row>

      {/* 图表：教室占用热力图（懒加载） */}
      <ClassroomHeatmapCard data={classroomOccupancy} isMobile={isMobile} />

      {/* 图表：入住时间线甘特图（懒加载） */}
      <GanttCard data={ganttData} isMobile={isMobile} periodEnd={period[1]} />
    </div>
  );
};

export default DashboardPage;
