import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Avatar,
  Button,
  Card,
  Col,
  DatePicker,
  Drawer,
  Empty,
  Form,
  Input,
  Modal,
  Progress,
  Row,
  Select,
  Space,
  Spin,
  Table,
  Tag,
  Tooltip,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import {
  ArrowRightOutlined,
  CheckCircleFilled,
  ClockCircleOutlined,
  EditOutlined,
  ExportOutlined,
  FileSearchOutlined,
  ReloadOutlined,
  ScheduleOutlined,
  TeamOutlined,
  WarningFilled,
} from '@ant-design/icons';
import dayjs, { type Dayjs } from 'dayjs';
import api from '../../api';
import PermissionButton from '../../components/PermissionButton';
import { usePermission } from '../../hooks/usePermission';
import { message } from '../../ui/app-message';
import {
  canPullAttendance,
  filterLessonAttendanceRecords,
  getAttendanceExperience,
  getPunchDisplayInfo,
  getSchedulePhase,
  summarizeLessonCheckins,
  type AttendanceSummary,
  type LessonAttendanceFilter,
  type SchedulePhase,
} from './attendance-workspace';
import './attendance.css';

const { RangePicker } = DatePicker;

const SESSION_OPTIONS = [
  { value: 'morning_reading', label: '早自习' },
  { value: 'morning', label: '上午' },
  { value: 'afternoon', label: '下午' },
  { value: 'evening_study', label: '晚自习' },
  { value: 'night_check', label: '晚寝' },
];

const SESSION_MAP: Record<string, string> = Object.fromEntries(
  SESSION_OPTIONS.map((item) => [item.value, item.label]),
);

const STATUS_META: Record<
  string,
  { label: string; color: string; className: string; short: string }
> = {
  present: { label: '出勤', color: 'success', className: 'is-present', short: '勤' },
  late: { label: '迟到', color: 'warning', className: 'is-late', short: '迟' },
  absent: { label: '缺勤', color: 'error', className: 'is-absent', short: '缺' },
  leave: { label: '请假', color: 'processing', className: 'is-leave', short: '假' },
  pending: { label: '待确认', color: 'default', className: 'is-pending', short: '待' },
};

const STATUS_OPTIONS = Object.entries(STATUS_META)
  .filter(([value]) => value !== 'pending')
  .map(([value, item]) => ({ value, label: item.label }));

interface ClassOption {
  classId: number;
  className: string;
}

interface AttendanceRecordItem {
  id: number;
  studentId: number;
  classId: number | null;
  attendanceDate: string;
  session: string;
  status: string;
  source?: string;
  remark: string | null;
  createdAt: string;
  student: { id: number; name: string };
  class: { id: number; name: string } | null;
  scheduleId?: number | null;
  attendanceSessionId?: number | null;
  punchTime?: string | null;
  punchSource?: string | null;
  punchDeviceName?: string | null;
  punchDeviceId?: string | null;
}

interface AssignedClass {
  classId: number;
  className: string;
  classCode: string;
  roleType: string;
  subject: string;
}

interface TodaySchedule {
  id: number;
  classId: number;
  classroomId: number;
  startTime: string;
  endTime: string;
  subject: string;
}

interface LessonAttendanceSession {
  id: number;
  scheduleId: number;
  classId: number;
  lessonDate: string;
  status: 'in_progress' | 'completed';
}

interface LessonAttendanceResponse {
  schedule: TodaySchedule;
  session: LessonAttendanceSession | null;
  records: AttendanceRecordItem[];
}

interface TeacherWorkspaceData {
  assignedClasses: AssignedClass[];
  todaySchedules: TodaySchedule[];
}

interface AlertItem {
  studentId: number;
  studentName: string;
  className: string;
  type: string;
  count: number;
  lastDate: string;
}

const EMPTY_SUMMARY: AttendanceSummary = {
  total: 0,
  present: 0,
  late: 0,
  absent: 0,
  leave: 0,
  pending: 0,
};

function readCurrentRoles(): string[] {
  try {
    const user = JSON.parse(localStorage.getItem('user') || '{}') as { roles?: string[] };
    return Array.isArray(user.roles) ? user.roles : [];
  } catch {
    return [];
  }
}

function AttendanceStatusTag({ status }: { status: string }) {
  const meta = STATUS_META[status] ?? {
    label: status,
    color: 'default',
    className: 'is-pending',
    short: '?',
  };
  return (
    <span className={`attendance-status ${meta.className}`}>
      <span className="attendance-status__dot" />
      {meta.label}
    </span>
  );
}

function SummaryStrip({ summary }: { summary: AttendanceSummary }) {
  const rate = summary.total > 0 ? Math.round((summary.present / summary.total) * 100) : 0;
  return (
    <div className="attendance-summary-strip">
      <div className="attendance-rate">
        <Progress
          type="circle"
          percent={rate}
          size={64}
          strokeWidth={9}
          strokeColor="#1677ff"
          trailColor="#e8eef7"
        />
        <div>
          <span>出勤率</span>
          <strong>{summary.total} 条记录</strong>
        </div>
      </div>
      {[
        ['present', summary.present],
        ['late', summary.late],
        ['absent', summary.absent],
        ['leave', summary.leave],
      ].map(([status, value]) => {
        const meta = STATUS_META[String(status)];
        return (
          <div className="attendance-summary-cell" key={String(status)}>
            <span className={`attendance-summary-icon ${meta.className}`}>{meta.short}</span>
            <div>
              <strong>{value}</strong>
              <span>{meta.label}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

function LessonCheckinSummaryStrip({ records }: { records: readonly AttendanceRecordItem[] }) {
  const summary = summarizeLessonCheckins(records);
  const rate = summary.total > 0 ? Math.round((summary.checkedIn / summary.total) * 100) : 0;
  return (
    <div className="attendance-summary-strip">
      <div className="attendance-rate">
        <Progress type="circle" percent={rate} size={64} strokeWidth={9} />
        <div><span>打卡率</span><strong>{summary.total} 人</strong></div>
      </div>
      <div className="attendance-summary-cell">
        <span className="attendance-summary-icon is-present">勤</span>
        <div><strong>{summary.checkedIn}</strong><span>已打卡</span></div>
      </div>
      <div className="attendance-summary-cell">
        <span className="attendance-summary-icon is-absent">缺</span>
        <div><strong>{summary.notCheckedIn}</strong><span>未打卡</span></div>
      </div>
    </div>
  );
}

const AttendancePage: React.FC = () => {
  const { permissions, hasPermission } = usePermission();
  const roles = useMemo(readCurrentRoles, []);
  const experience = getAttendanceExperience(permissions, roles);

  if (experience === 'teacher') {
    return <TeacherAttendanceWorkspace />;
  }

  return <AdminAttendanceArchive canEdit={hasPermission('attendance:edit')} />;
};

const TeacherAttendanceWorkspace: React.FC = () => {
  const [loading, setLoading] = useState(true);
  const [workspace, setWorkspace] = useState<TeacherWorkspaceData | null>(null);
  const [selectedSchedule, setSelectedSchedule] = useState<TodaySchedule | null>(null);
  const [lessonSession, setLessonSession] = useState<LessonAttendanceSession | null>(null);
  const [lessonRecords, setLessonRecords] = useState<AttendanceRecordItem[]>([]);
  const [recordLoading, setRecordLoading] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [studentKeyword, setStudentKeyword] = useState('');
  const [checkinFilter, setCheckinFilter] = useState<LessonAttendanceFilter>('all');

  const loadWorkspace = useCallback(async () => {
    setLoading(true);
    try {
      setWorkspace(await api.get<TeacherWorkspaceData>('/rbac/teacher-workspace'));
    } catch (error: unknown) {
      message.error((error as { message?: string })?.message || '加载今日课程失败');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const classNameById = useMemo(
    () => new Map(workspace?.assignedClasses.map((item) => [item.classId, item.className]) ?? []),
    [workspace],
  );


  const openAttendance = useCallback(async (schedule: TodaySchedule) => {
    setStudentKeyword('');
    setCheckinFilter('all');
    setSelectedSchedule(schedule);
    setDrawerOpen(true);
    setRecordLoading(true);
    try {
      const today = dayjs().format('YYYY-MM-DD');
      const data = await api.post<LessonAttendanceResponse>(
        `/attendance-lessons/schedules/${schedule.id}/pull`,
        { date: today },
      );
      setSelectedSchedule(data.schedule);
      setLessonSession(data.session);
      setLessonRecords(data.records);
      message.success('钉钉打卡已更新；课程截止后系统将自动结算');
    } catch (error: unknown) {
      setLessonSession(null);
      setLessonRecords([]);
      message.error(error instanceof Error ? error.message : '加载本节课考勤失败');
    } finally {
      setRecordLoading(false);
    }
  }, []);

  const updateLessonRecord = useCallback(
    async (record: AttendanceRecordItem, status: string) => {
      const previous = record.status;
      setLessonRecords((items) =>
        items.map((item) => (item.id === record.id ? { ...item, status } : item)),
      );
      try {
        await api.put(`/attendance-records/${record.id}`, { status });
      } catch (error: unknown) {
        setLessonRecords((items) =>
          items.map((item) => (item.id === record.id ? { ...item, status: previous } : item)),
        );
        message.error((error as { message?: string })?.message || '更新考勤失败');
      }
    },
    [],
  );


  const now = new Date();
  const schedules = workspace?.todaySchedules ?? [];
  const startedCount = schedules.filter(
    (item) => canPullAttendance(getSchedulePhase(item.startTime, item.endTime, now)),
  ).length;
  const nextSchedule = schedules.find(
    (item) => getSchedulePhase(item.startTime, item.endTime, now) !== 'ended',
  );
  const isAttendanceCompleted = lessonSession?.status === 'completed';
  const filteredLessonRecords = useMemo(
    () => filterLessonAttendanceRecords(lessonRecords, studentKeyword, checkinFilter),
    [lessonRecords, studentKeyword, checkinFilter],
  );

  return (
    <div className="attendance-page teacher-attendance">
      <section className="attendance-hero attendance-hero--teacher">
        <div>
          <span className="attendance-eyebrow">TEACHING DAY · {dayjs().format('MM月DD日 dddd')}</span>
          <h1>今天，从课程开始</h1>
          <p>课程开始后可查看最新打卡结果；课程截止时系统自动拉取并结算缺勤。</p>
        </div>
        <Button icon={<ReloadOutlined />} onClick={() => void loadWorkspace()}>
          刷新
        </Button>
      </section>

      <Row gutter={[16, 16]} className="teacher-overview">
        <Col xs={24} md={8}>
          <div className="teacher-kpi"><span>今日课程</span><strong>{schedules.length}</strong><small>节</small></div>
        </Col>
        <Col xs={24} md={8}>
          <div className="teacher-kpi"><span>已开始</span><strong>{startedCount}</strong><small>节，可查看考勤</small></div>
        </Col>
        <Col xs={24} md={8}>
          <div className="teacher-kpi teacher-kpi--next"><span>下一节</span><strong>{nextSchedule ? nextSchedule.startTime : '—'}</strong><small>{nextSchedule?.subject || '今天没有更多课程'}</small></div>
        </Col>
      </Row>

      <div className="attendance-section-heading">
        <div><span>今日教学节奏</span><h2>我的课程</h2></div>
        <span className="attendance-section-note">课程开始后可拉取钉钉考勤记录</span>
      </div>

      <Spin spinning={loading}>
        {schedules.length === 0 ? (
          <Card className="attendance-empty-card">
            <Empty
              image={Empty.PRESENTED_IMAGE_SIMPLE}
              description={<div><strong>今天还没有课程</strong><p>请联系教务管理员安排课程。</p></div>}
            />
          </Card>
        ) : (
          <div className="lesson-timeline">
            {schedules.map((schedule, index) => {
              const phase = getSchedulePhase(schedule.startTime, schedule.endTime, now);
              return (
                <LessonCard
                  key={schedule.id}
                  schedule={schedule}
                  phase={phase}
                  className={classNameById.get(schedule.classId) || `班级 ${schedule.classId}`}
                  index={index + 1}
                  onOpen={() => void openAttendance(schedule)}
                />
              );
            })}
          </div>
        )}
      </Spin>

      <Drawer open={drawerOpen} onClose={() => setDrawerOpen(false)} width={960} title={null} className="attendance-drawer">
        <div className="lesson-record-header">
          <span className="attendance-eyebrow">LESSON ATTENDANCE</span>
          <h2>{selectedSchedule?.subject || '课程考勤'}</h2>
          <p>{selectedSchedule ? classNameById.get(selectedSchedule.classId) : ''} · {selectedSchedule?.startTime}–{selectedSchedule?.endTime} · {dayjs().format('YYYY-MM-DD')}</p>
        </div>
        {lessonSession && (
          <Alert
            type={isAttendanceCompleted ? 'success' : 'info'}
            showIcon
            title={isAttendanceCompleted ? '本节课考勤已结算' : '当前打卡结果；课程截止后将自动做最终结算'}
            style={{ marginBottom: 16 }}
          />
        )}
        <LessonCheckinSummaryStrip records={lessonRecords} />
        <div className="lesson-record-filters">
          <Input.Search
            allowClear
            value={studentKeyword}
            placeholder="搜索学生姓名"
            onChange={(event) => setStudentKeyword(event.target.value)}
            className="lesson-record-search"
          />
          <Select<LessonAttendanceFilter>
            value={checkinFilter}
            onChange={setCheckinFilter}
            options={[
              { value: 'all', label: '全部学生' },
              { value: 'checked_in', label: '已打卡' },
              { value: 'not_checked_in', label: '未打卡' },
            ]}
            className="lesson-record-filter-select"
          />
          <span className="lesson-record-filter-count">
            显示 {filteredLessonRecords.length} / {lessonRecords.length} 人
          </span>
        </div>
        <Table<AttendanceRecordItem>
          rowKey="id"
          loading={recordLoading}
          dataSource={filteredLessonRecords}
          pagination={false}
          locale={{
            emptyText: <Empty
              image={Empty.PRESENTED_IMAGE_SIMPLE}
              description={lessonRecords.length === 0 ? '本节课尚未开始点名' : '没有符合条件的学生'}
            />,
          }}
          columns={[
            {
              title: '学生', dataIndex: ['student', 'name'],
              render: (name: string) => <div className="student-cell"><Avatar size={32}>{name?.slice(0, 1)}</Avatar><strong>{name || '-'}</strong></div>,
            },
            {
              title: '考勤结果', dataIndex: 'status', width: 230,
              render: (value: string, record: AttendanceRecordItem) => {
                const checkedIn = value === 'present' || value === 'late';
                return (
                  <div className="attendance-marking-actions">
                    <Button
                      size="small"
                      type={checkedIn ? 'primary' : 'default'}
                      onClick={() => void updateLessonRecord(record, 'present')}
                    >
                      已打卡
                    </Button>
                    <Button
                      size="small"
                      type={!checkedIn ? 'primary' : 'default'}
                      danger={!checkedIn}
                      onClick={() => void updateLessonRecord(record, 'absent')}
                    >
                      未打卡
                    </Button>
                  </div>
                );
              },
            },
            { title: '当前状态', dataIndex: 'status', width: 105, render: (value: string) => <AttendanceStatusTag status={value === 'present' || value === 'late' ? 'present' : 'absent'} /> },
            {
              title: '打卡设备',
              width: 220,
              render: (_: unknown, record: AttendanceRecordItem) => {
                const info = getPunchDisplayInfo(record);
                if (!info) return <span className="muted-text">—</span>;
                return (
                  <div className="punch-device-cell">
                    <Tag color={info.machine ? 'green' : 'blue'}>{info.label}</Tag>
                    {info.detail && <strong>{info.detail}</strong>}
                    {info.time && <span>{dayjs(info.time).format('HH:mm:ss')}</span>}
                  </div>
                );
              },
            },
            { title: '备注', dataIndex: 'remark', render: (value: string | null) => value || <span className="muted-text">—</span> },
          ]}
        />
      </Drawer>
    </div>
  );
};

const LessonCard: React.FC<{
  schedule: TodaySchedule;
  phase: SchedulePhase;
  className: string;
  index: number;
  onOpen: () => void;
}> = ({ schedule, phase, className, index, onOpen }) => {
  const phaseMeta = {
    upcoming: { label: '待上课', icon: <ClockCircleOutlined />, tone: 'upcoming' },
    ongoing: { label: '进行中', icon: <ScheduleOutlined />, tone: 'ongoing' },
    ended: { label: '已结束', icon: <CheckCircleFilled />, tone: 'ended' },
  }[phase];

  return (
    <article className={`lesson-card lesson-card--${phaseMeta.tone}`}>
      <div className="lesson-sequence">{String(index).padStart(2, '0')}</div>
      <div className="lesson-time"><strong>{schedule.startTime}</strong><span /><strong>{schedule.endTime}</strong></div>
      <div className="lesson-main">
        <div className="lesson-title-row"><h3>{schedule.subject}</h3><Tag icon={phaseMeta.icon}>{phaseMeta.label}</Tag></div>
        <p><TeamOutlined /> {className}<span>教室 {schedule.classroomId}</span></p>
      </div>
      <div className="lesson-action">
        {phase === 'upcoming' ? (
          <Tooltip title="课程尚未开始"><Button disabled>等待上课</Button></Tooltip>
        ) : (
          <Button type="primary" onClick={onOpen}>
            {phase === 'ongoing' ? '查看当前考勤' : '拉取 / 查看考勤'} <ArrowRightOutlined />
          </Button>
        )}
      </div>
    </article>
  );
};


const AdminAttendanceArchive: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
  const [records, setRecords] = useState<AttendanceRecordItem[]>([]);
  const [summary, setSummary] = useState<AttendanceSummary>(EMPTY_SUMMARY);
  const [alerts, setAlerts] = useState<AlertItem[]>([]);
  const [classOptions, setClassOptions] = useState<ClassOption[]>([]);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(20);
  const [total, setTotal] = useState(0);
  const [classId, setClassId] = useState<number>();
  const [dateRange, setDateRange] = useState<[Dayjs, Dayjs] | null>([
    dayjs().subtract(30, 'day'),
    dayjs(),
  ]);
  const [status, setStatus] = useState<string>();
  const [session, setSession] = useState<string>();
  const [editRecord, setEditRecord] = useState<AttendanceRecordItem | null>(null);
  const [editForm] = Form.useForm();

  const buildParams = useCallback(
    (withPagination = true) => {
      const params: Record<string, string | number> = {};
      if (withPagination) Object.assign(params, { page, pageSize });
      if (classId) params.classId = classId;
      if (dateRange?.[0]) params.dateFrom = dateRange[0].format('YYYY-MM-DD');
      if (dateRange?.[1]) params.dateTo = dateRange[1].format('YYYY-MM-DD');
      if (status) params.status = status;
      if (session) params.session = session;
      return params;
    },
    [page, pageSize, classId, dateRange, status, session],
  );

  const loadRecords = useCallback(async () => {
    setLoading(true);
    try {
      const [recordData, summaryData] = await Promise.all([
        api.get<{ list: AttendanceRecordItem[]; total: number }>('/attendance-records', {
          params: buildParams(true),
        }),
        api.get<AttendanceSummary>('/attendance-records/summary', {
          params: buildParams(false),
        }),
      ]);
      setRecords(recordData.list);
      setTotal(recordData.total);
      setSummary({ ...EMPTY_SUMMARY, ...summaryData });
    } catch (error: unknown) {
      message.error((error as { message?: string })?.message || '加载历史考勤失败');
    } finally {
      setLoading(false);
    }
  }, [buildParams]);

  useEffect(() => {
    void Promise.all([
      api.get<ClassOption[]>('/attendance-records/classes').then(setClassOptions),
      api.get<AlertItem[]>('/attendance-records/alerts').then(setAlerts),
    ]).catch(() => undefined);
  }, []);

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

  const resetFilters = () => {
    setClassId(undefined);
    setDateRange([dayjs().subtract(30, 'day'), dayjs()]);
    setStatus(undefined);
    setSession(undefined);
    setPage(1);
  };

  const handleExport = useCallback(() => {
    const params = new URLSearchParams();
    for (const [key, value] of Object.entries(buildParams(false))) params.set(key, String(value));
    const token = localStorage.getItem('token');
    fetch(`/api/attendance-records/export?${params.toString()}`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((response) => {
        if (!response.ok) throw new Error('导出失败');
        return response.blob();
      })
      .then((blob) => {
        const url = URL.createObjectURL(blob);
        const anchor = document.createElement('a');
        anchor.href = url;
        anchor.download = `历史考勤-${dayjs().format('YYYYMMDD')}.xlsx`;
        anchor.click();
        URL.revokeObjectURL(url);
      })
      .catch(() => message.error('导出失败'));
  }, [buildParams]);

  const submitEdit = async () => {
    if (!editRecord) return;
    try {
      const values = await editForm.validateFields();
      await api.put(`/attendance-records/${editRecord.id}`, values);
      message.success('考勤记录已更新');
      setEditRecord(null);
      void loadRecords();
    } catch (error: unknown) {
      if ((error as { errorFields?: unknown })?.errorFields) return;
      message.error((error as { message?: string })?.message || '更新失败');
    }
  };

  const columns: ColumnsType<AttendanceRecordItem> = [
    {
      title: '学生',
      dataIndex: ['student', 'name'],
      fixed: 'left',
      width: 150,
      render: (name: string, record) => (
        <div className="student-cell">
          <Avatar size={34}>{name?.slice(0, 1)}</Avatar>
          <div>
            <strong>{name || '-'}</strong>
            <span>{record.class?.name || '未关联班级'}</span>
          </div>
        </div>
      ),
    },
    { title: '日期', dataIndex: 'attendanceDate', width: 120 },
    {
      title: '时段',
      dataIndex: 'session',
      width: 110,
      render: (value: string) => SESSION_MAP[value] || value,
    },
    {
      title: '结果',
      dataIndex: 'status',
      width: 110,
      render: (value: string) => <AttendanceStatusTag status={value} />,
    },
    {
      title: '记录来源',
      dataIndex: 'source',
      width: 110,
      render: (value: string) => (value === 'dingtalk' ? '钉钉同步' : value === 'schedule' ? '课程生成' : value === 'lesson' ? '课堂点名' : '人工记录'),
    },
    {
      title: '备注',
      dataIndex: 'remark',
      ellipsis: true,
      render: (value: string | null) => value || <span className="muted-text">—</span>,
    },
    {
      title: '归档时间',
      dataIndex: 'createdAt',
      width: 165,
      render: (value: string) => dayjs(value).format('YYYY-MM-DD HH:mm'),
    },
    ...(canEdit
      ? [
          {
            title: '操作',
            key: 'action',
            fixed: 'right' as const,
            width: 80,
            render: (_: unknown, record: AttendanceRecordItem) => (
              <Button
                type="text"
                icon={<EditOutlined />}
                onClick={() => {
                  setEditRecord(record);
                  editForm.setFieldsValue({ status: record.status, remark: record.remark });
                }}
              >
                纠错
              </Button>
            ),
          },
        ]
      : []),
  ];

  return (
    <div className="attendance-page admin-attendance">
      <section className="attendance-hero attendance-hero--admin">
        <div>
          <span className="attendance-eyebrow">ATTENDANCE ARCHIVE</span>
          <h1>历史考勤档案</h1>
          <p>面向管理人员的历史检索、异常追踪与数据归档，不承载实时上课操作。</p>
        </div>
        <PermissionButton
          permission="attendance:export"
          icon={<ExportOutlined />}
          size="large"
          onClick={handleExport}
        >
          导出当前结果
        </PermissionButton>
      </section>

      <SummaryStrip summary={summary} />

      {alerts.length > 0 && (
        <div className="archive-alert">
          <WarningFilled />
          <div>
            <strong>{alerts.length} 名学生存在连续异常</strong>
            <span>建议优先核查最近 14 天的缺勤与迟到记录</span>
          </div>
          <Tooltip title={alerts.slice(0, 5).map((item) => `${item.studentName}：${item.type}${item.count}次`).join('；')}>
            <Button type="link">查看摘要</Button>
          </Tooltip>
        </div>
      )}

      <Card className="archive-card" bordered={false}>
        <div className="archive-toolbar">
          <div className="archive-toolbar__title">
            <FileSearchOutlined />
            <div>
              <strong>档案检索</strong>
              <span>默认查看最近 30 天</span>
            </div>
          </div>
          <Space wrap size={10}>
            <Select
              allowClear
              showSearch
              optionFilterProp="label"
              placeholder="全部班级"
              value={classId}
              onChange={(value) => {
                setClassId(value);
                setPage(1);
              }}
              options={classOptions.map((item) => ({ value: item.classId, label: item.className }))}
              style={{ width: 170 }}
            />
            <RangePicker
              value={dateRange}
              onChange={(value) => {
                setDateRange(value as [Dayjs, Dayjs] | null);
                setPage(1);
              }}
            />
            <Select
              allowClear
              placeholder="考勤结果"
              value={status}
              onChange={(value) => {
                setStatus(value);
                setPage(1);
              }}
              options={STATUS_OPTIONS}
              style={{ width: 130 }}
            />
            <Select
              allowClear
              placeholder="课程时段"
              value={session}
              onChange={(value) => {
                setSession(value);
                setPage(1);
              }}
              options={SESSION_OPTIONS}
              style={{ width: 130 }}
            />
            <Button icon={<ReloadOutlined />} onClick={resetFilters}>
              重置
            </Button>
          </Space>
        </div>

        <Table<AttendanceRecordItem>
          rowKey="id"
          columns={columns}
          dataSource={records}
          loading={loading}
          scroll={{ x: 1050 }}
          pagination={{
            current: page,
            pageSize,
            total,
            showSizeChanger: true,
            showTotal: (value) => `共 ${value} 条历史记录`,
            onChange: (nextPage, nextPageSize) => {
              setPage(nextPage);
              setPageSize(nextPageSize);
            },
          }}
          locale={{
            emptyText: (
              <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="当前条件下没有历史考勤记录" />
            ),
          }}
        />
      </Card>

      <Modal
        open={Boolean(editRecord)}
        title="考勤记录纠错"
        okText="保存修正"
        onOk={submitEdit}
        onCancel={() => setEditRecord(null)}
      >
        <Alert
          type="info"
          showIcon
          title="管理员修正会保留操作日志"
          style={{ marginBottom: 20 }}
        />
        <Form form={editForm} layout="vertical">
          <Form.Item name="status" label="考勤结果" rules={[{ required: true }]}>
            <Select options={STATUS_OPTIONS} />
          </Form.Item>
          <Form.Item name="remark" label="修正说明">
            <Input.TextArea rows={3} placeholder="建议填写修正原因，便于后续审计" />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
};

export default AttendancePage;
