import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Avatar,
  Button,
  Card,
  Col,
  DatePicker,
  Drawer,
  Grid,
  Empty,
  Form,
  Input,
  Modal,
  Segmented,
  Row,
  Select,
  Spin,
  Table,
  Tag,
  Tooltip,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import {
  ArrowRightOutlined,
  CheckCircleFilled,
  ClockCircleOutlined,
  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 EditableCell from '../../components/EditableCell';
import { usePermission } from '../../hooks/usePermission';
import { message } from '../../ui/app-message';
import {
  canPullAttendance,
  getAttendanceExperience,
  getSchedulePhase,
  getPunchDisplayInfo,
  type AttendanceSummary,
  type SchedulePhase,
} from './attendance-workspace';
import LessonAttendanceDetail from './LessonAttendanceDetail';
import type { LessonAttendanceRecord, LessonAttendanceSchedule } from './types';
import './attendance.css';

const DEFAULT_ATTENDANCE_PERIODS = [
  {
    periodKey: 'morning_reading',
    label: '早自习',
    startTime: '07:30',
    endTime: '08:30',
    sortOrder: 1,
    enabled: true,
  },
  {
    periodKey: 'morning',
    label: '早课',
    startTime: '09:00',
    endTime: '12:00',
    sortOrder: 2,
    enabled: true,
  },
  {
    periodKey: 'afternoon',
    label: '晚课',
    startTime: '14:00',
    endTime: '17:00',
    sortOrder: 3,
    enabled: true,
  },
  {
    periodKey: 'evening_study',
    label: '晚自习',
    startTime: '18:30',
    endTime: '21:00',
    sortOrder: 4,
    enabled: true,
  },
];

const STATUS_META: Record<
  string,
  { label: string; color: string; className: string; short: string }
> = {
  present: { label: '出勤', color: 'success', className: 'is-present', 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 ADMIN_CORRECTION_OPTIONS = [
  { value: 'present', label: '正常' },
  { value: 'leave', label: '请假' },
  { value: 'absent', label: '缺勤' },
];

interface ClassTeacherOption {
  userId: number;
  username: string | null;
  name: string | null;
  roleType: string;
  subject: string | null;
}

interface ClassOption {
  classId: number;
  className: string;
  teachers?: ClassTeacherOption[];
}

type AttendanceRecordItem = LessonAttendanceRecord;

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

type TodaySchedule = LessonAttendanceSchedule;

interface HistoryScheduleOption {
  id: number;
  classId: number;
  weekDay: number;
  startTime: string;
  endTime: string;
  startDate: string;
  endDate: string;
  subject: string;
  teacherId: number | null;
  teacherName?: string | null;
  teacherUsername?: string | null;
  status: string;
}

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

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

interface AttendancePeriodConfigItem {
  id?: number;
  periodKey: string;
  label: string;
  startTime: string;
  endTime: string;
  sortOrder: number;
  enabled: boolean;
}

interface DingTalkSyncStatus {
  lastPulledAt: string | null;
  action: string | null;
  username: string | null;
  detail: string | null;
}

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 displayAttendanceStatus(status?: string | null): string {
  return status === 'pending' || !status ? 'absent' : status;
}

function getTeacherDisplayName(teacher?: {
  name?: string | null;
  username?: string | null;
}): string {
  const name = teacher?.name?.trim();
  if (name) return name;
  return teacher?.username?.trim() || '未设置';
}

function formatTeacherNames(
  teachers: readonly { name?: string | null; username?: string | null }[],
): string {
  const names = [
    ...new Set(
      teachers
        .map((teacher) => getTeacherDisplayName(teacher))
        .filter((name) => name && name !== '未设置'),
    ),
  ];
  return names.length > 0 ? names.join('、') : '未设置';
}

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

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 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((schedule: TodaySchedule) => {
    setSelectedSchedule(schedule);
  }, []);

  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',
  );

  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={() => openAttendance(schedule)}
                />
              );
            })}
          </div>
        )}
      </Spin>

      <LessonAttendanceDetail
        schedule={selectedSchedule}
        className={
          selectedSchedule
            ? classNameById.get(selectedSchedule.classId) || `班级 ${selectedSchedule.classId}`
            : ''
        }
        onClose={() => setSelectedSchedule(null)}
      />
    </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>
  );
};

interface AdminStudentPanel {
  key: string;
  studentId: number;
  studentName: string;
  studentNo: string;
  className: string;
  records: AttendanceRecordItem[];
  statusBySession: Partial<Record<string, AttendanceRecordItem>>;
  primaryStatus: string;
  rate: number;
  latestDate: string;
}

const ADMIN_METRIC_META = [
  { key: 'all', label: '出勤率', short: '率' },
  { key: 'present', label: '正常', short: '正常' },
  { key: 'leave', label: '请假', short: '请假' },
  { key: 'absent', label: '缺勤', short: '缺勤' },
];

function pickPrimaryStatus(records: AttendanceRecordItem[]) {
  const priority = ['absent', 'leave', 'present'];
  return (
    priority.find((item) =>
      records.some((record) => displayAttendanceStatus(record.status) === item),
    ) || 'absent'
  );
}

function buildAdminStudentPanels(records: AttendanceRecordItem[]): AdminStudentPanel[] {
  const map = new Map<number, AdminStudentPanel>();
  for (const record of records) {
    const current = map.get(record.studentId) ?? {
      key: String(record.studentId),
      studentId: record.studentId,
      studentName: record.student?.name || '未知学生',
      studentNo: record.student?.studentNo?.trim() || '',
      className: record.class?.name || '未关联班级',
      records: [],
      statusBySession: {},
      primaryStatus: 'absent',
      rate: 0,
      latestDate: record.attendanceDate,
    };
    current.records.push(record);
    if (!current.statusBySession[record.session]) current.statusBySession[record.session] = record;
    if (dayjs(record.attendanceDate).isAfter(dayjs(current.latestDate))) {
      current.latestDate = record.attendanceDate;
    }
    map.set(record.studentId, current);
  }

  return Array.from(map.values()).map((item) => {
    const checked = item.records.filter((record) => record.status === 'present').length;
    return {
      ...item,
      primaryStatus: pickPrimaryStatus(item.records),
      rate: item.records.length > 0 ? Math.round((checked / item.records.length) * 100) : 0,
    };
  });
}

const AdminAttendanceArchive: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.sm;
  const [records, setRecords] = useState<AttendanceRecordItem[]>([]);
  const [summary, setSummary] = useState<AttendanceSummary>(EMPTY_SUMMARY);
  const [alerts, setAlerts] = useState<AlertItem[]>([]);
  const [classOptions, setClassOptions] = useState<ClassOption[]>([]);
  const [scheduleOptions, setScheduleOptions] = useState<HistoryScheduleOption[]>([]);
  const [scheduleOptionsLoading, setScheduleOptionsLoading] = useState(false);
  const [periods, setPeriods] = useState<AttendancePeriodConfigItem[]>(DEFAULT_ATTENDANCE_PERIODS);
  const [periodModalOpen, setPeriodModalOpen] = useState(false);
  const [periodForm] = Form.useForm<{ periods: AttendancePeriodConfigItem[] }>();
  const [loading, setLoading] = useState(true);
  const [refreshingDingTalk, setRefreshingDingTalk] = useState(false);
  const [syncStatus, setSyncStatus] = useState<DingTalkSyncStatus | null>(null);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(48);
  const [total, setTotal] = useState(0);
  const [classId, setClassId] = useState<number>();
  const [attendanceDate, setAttendanceDate] = useState<Dayjs | null>(dayjs());
  const [status, setStatus] = useState<string>();
  const [session, setSession] = useState<string>();
  const [scheduleId, setScheduleId] = useState<number>();
  const [metricFilter, setMetricFilter] = useState('all');
  const [studentSearch, setStudentSearch] = useState('');
  const [selectedStudent, setSelectedStudent] = useState<AdminStudentPanel | null>(null);
  const [correctingRecordId, setCorrectingRecordId] = useState<number | null>(null);

  const enabledPeriods = useMemo(
    () => periods.filter((period) => period.enabled).sort((a, b) => a.sortOrder - b.sortOrder),
    [periods],
  );
  const sessionOptions = useMemo(
    () => enabledPeriods.map((period) => ({ value: period.periodKey, label: period.label })),
    [enabledPeriods],
  );
  const sessionMap = useMemo(
    () => Object.fromEntries(periods.map((period) => [period.periodKey, period.label])),
    [periods],
  );
  const periodOrder = useMemo(
    () => new Map(periods.map((period, index) => [period.periodKey, index])),
    [periods],
  );
  const sortAttendanceRecords = useCallback(
    (items: readonly AttendanceRecordItem[]) =>
      [...items].sort((a, b) => {
        const periodDiff =
          (periodOrder.get(a.session) ?? Number.MAX_SAFE_INTEGER) -
          (periodOrder.get(b.session) ?? Number.MAX_SAFE_INTEGER);
        if (periodDiff !== 0) return periodDiff;
        return (a.punchTime || a.createdAt || '').localeCompare(b.punchTime || b.createdAt || '');
      }),
    [periodOrder],
  );
  const subjectScheduleOptions = useMemo(
    () =>
      scheduleOptions.map((schedule) => ({
        value: schedule.id,
        label: `${schedule.subject}（${schedule.startTime}-${schedule.endTime}）`,
      })),
    [scheduleOptions],
  );

  const openPeriodConfig = () => {
    periodForm.setFieldsValue({ periods });
    setPeriodModalOpen(true);
  };

  const savePeriodConfig = async () => {
    try {
      const values = await periodForm.validateFields();
      const payload = {
        periods: values.periods.map((period, index) => ({
          ...period,
          sortOrder: index + 1,
          enabled: period.enabled ?? true,
        })),
      };
      const data = await api.put<AttendancePeriodConfigItem[]>(
        '/attendance-period-configs',
        payload,
      );
      setPeriods(data);
      setPeriodModalOpen(false);
      message.success('考勤时段配置已保存');
      if (session && !data.some((period) => period.enabled && period.periodKey === session)) {
        setSession(undefined);
      }
    } catch (error: unknown) {
      if ((error as { errorFields?: unknown })?.errorFields) return;
      message.error((error as { message?: string })?.message || '保存考勤时段配置失败');
    }
  };

  const resetPeriodConfig = async () => {
    try {
      const data = await api.post<AttendancePeriodConfigItem[]>('/attendance-period-configs/reset');
      setPeriods(data);
      periodForm.setFieldsValue({ periods: data });
      message.success('已恢复默认考勤时段');
    } catch (error: unknown) {
      message.error((error as { message?: string })?.message || '恢复默认配置失败');
    }
  };

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

  const loadSyncStatus = useCallback(async () => {
    try {
      setSyncStatus(await api.get<DingTalkSyncStatus>('/attendance-records/dingtalk-sync-status'));
    } catch {
      setSyncStatus(null);
    }
  }, []);

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

  const refreshDingTalkAttendance = useCallback(async () => {
    if (!attendanceDate) {
      message.warning('请先选择日期');
      return;
    }
    if (attendanceDate.isAfter(dayjs(), 'day')) {
      message.warning('不能查看或刷新未来日期的考勤');
      return;
    }
    setRefreshingDingTalk(true);
    try {
      const result = await api.post<{
        refreshed: number;
        imported: number;
        matched: number;
        errors: string[];
      }>('/attendance-records/refresh-dingtalk', {
        date: attendanceDate.format('YYYY-MM-DD'),
        classId,
        session,
      });
      if (result.errors.length > 0) {
        message.warning(result.errors[0]);
      } else {
        message.success(`已刷新 ${result.refreshed} 节课程考勤`);
      }
      await Promise.all([loadRecords(), loadSyncStatus()]);
    } catch (error: unknown) {
      message.error((error as { message?: string })?.message || '刷新钉钉考勤失败');
    } finally {
      setRefreshingDingTalk(false);
    }
  }, [attendanceDate, classId, loadRecords, loadSyncStatus, session]);

  useEffect(() => {
    void Promise.all([
      api.get<ClassOption[]>('/attendance-records/classes').then(setClassOptions),
      api.get<AlertItem[]>('/attendance-records/alerts').then(setAlerts),
      api.get<AttendancePeriodConfigItem[]>('/attendance-period-configs').then((data) => {
        setPeriods(data);
        periodForm.setFieldsValue({ periods: data });
      }),
    ]).catch(() => undefined);
  }, []);

  useEffect(() => {
    if (!classId || !attendanceDate) {
      setScheduleOptions([]);
      setScheduleId(undefined);
      return;
    }

    const selectedDate = attendanceDate.format('YYYY-MM-DD');
    setScheduleOptionsLoading(true);
    void api
      .get<HistoryScheduleOption[]>('/attendance-records/schedules', {
        params: { classId, date: selectedDate },
      })
      .then((options) => {
        setScheduleOptions(options);
        setScheduleId((current) =>
          current && options.some((schedule) => schedule.id === current) ? current : undefined,
        );
      })
      .catch((error: unknown) => {
        setScheduleOptions([]);
        setScheduleId(undefined);
        message.error((error as { message?: string })?.message || '加载班级科目失败');
      })
      .finally(() => setScheduleOptionsLoading(false));
  }, [attendanceDate, classId]);

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

  const resetFilters = () => {
    setClassId(undefined);
    setAttendanceDate(dayjs());
    setStatus(undefined);
    setSession(undefined);
    setScheduleId(undefined);
    setScheduleOptions([]);
    setMetricFilter('all');
    setStudentSearch('');
    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 patchRecordStatus = (recordId: number, nextStatus: string) => {
    setRecords((items) =>
      items.map((item) => (item.id === recordId ? { ...item, status: nextStatus } : item)),
    );
    setSelectedStudent((student) => {
      if (!student) return student;
      return {
        ...student,
        records: student.records.map((item) =>
          item.id === recordId ? { ...item, status: nextStatus } : item,
        ),
        statusBySession: Object.fromEntries(
          Object.entries(student.statusBySession).map(([key, item]) => [
            key,
            item?.id === recordId ? { ...item, status: nextStatus } : item,
          ]),
        ),
      };
    });
  };

  const updateAdminRecordStatus = async (record: AttendanceRecordItem, nextStatus: string) => {
    const previousStatus = record.status;
    const normalizedPrevious = displayAttendanceStatus(previousStatus);
    if (normalizedPrevious === nextStatus && previousStatus !== 'pending') return;

    patchRecordStatus(record.id, nextStatus);
    setCorrectingRecordId(record.id);
    try {
      await api.put(`/attendance-records/${record.id}`, { status: nextStatus });
      message.success('考勤结果已更新');
      void loadRecords();
    } catch (error: unknown) {
      patchRecordStatus(record.id, previousStatus);
      message.error((error as { message?: string })?.message || '更新失败');
    } finally {
      setCorrectingRecordId(null);
    }
  };

  const saveAdminRecordCell = async (
    record: AttendanceRecordItem,
    field: 'status' | 'remark',
    value: unknown,
  ) => {
    await api.put(`/attendance-records/${record.id}`, { [field]: value });
    message.success('考勤记录已保存');
    await loadRecords();
  };

  const studentPanels = useMemo(() => buildAdminStudentPanels(records), [records]);
  const visibleStudents = useMemo(() => {
    const query = studentSearch.trim().toLocaleLowerCase('zh-CN');
    return studentPanels.filter((student) => {
      const matchesQuery =
        !query ||
        student.studentName.toLocaleLowerCase('zh-CN').includes(query) ||
        student.studentNo.toLocaleLowerCase('zh-CN').includes(query);
      const matchesMetric =
        metricFilter === 'all' ||
        student.records.some((record) => displayAttendanceStatus(record.status) === metricFilter);
      return matchesQuery && matchesMetric;
    });
  }, [metricFilter, studentPanels, studentSearch]);

  const selectedClassOption = classId
    ? classOptions.find((item) => item.classId === classId)
    : undefined;
  const selectedClass =
    selectedClassOption?.className || (classId ? `班级 ${classId}` : '全部班级');
  const overviewTeachers = selectedClassOption?.teachers ?? [];
  const headTeacherNames = classId
    ? formatTeacherNames(overviewTeachers.filter((teacher) => teacher.roleType === 'head_teacher'))
    : '请选择班级';
  const lifeTeacherNames = classId
    ? formatTeacherNames(overviewTeachers.filter((teacher) => teacher.roleType === 'life_teacher'))
    : '请选择班级';
  const currentSchedule = scheduleId
    ? scheduleOptions.find((item) => item.id === scheduleId)
    : undefined;
  const subjectTeacherNames = currentSchedule
    ? getTeacherDisplayName({
        name: currentSchedule.teacherName,
        username: currentSchedule.teacherUsername,
      })
    : classId
      ? formatTeacherNames(
          overviewTeachers.filter((teacher) => teacher.roleType === 'subject_teacher'),
        )
      : '请选择班级';
  const attendanceRate =
    summary.total > 0 ? Math.round((summary.present / summary.total) * 100) : 0;
  const dateLabel = attendanceDate?.format('YYYY-MM-DD') || '未选择日期';

  const columns: ColumnsType<AttendanceRecordItem> = [
    {
      title: '学生',
      dataIndex: ['student', 'name'],
      fixed: isMobile ? undefined : '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) => sessionMap[value] || value,
    },
    {
      title: '状态',
      dataIndex: 'status',
      width: 105,
      render: (value: string, record) => (
        <EditableCell
          value={displayAttendanceStatus(value)}
          editor="select"
          options={ADMIN_CORRECTION_OPTIONS.map((item) => ({
            value: String(item.value),
            label: item.label,
          }))}
          disabled={!canEdit}
          onSave={(next) => saveAdminRecordCell(record, 'status', next)}
        >
          <AttendanceStatusTag status={displayAttendanceStatus(value)} />
        </EditableCell>
      ),
    },
    {
      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',
      ellipsis: true,
      render: (value: string | null, record) => (
        <EditableCell
          value={value}
          editor="textarea"
          disabled={!canEdit}
          onSave={(next) => saveAdminRecordCell(record, 'remark', next)}
        >
          {value || <span className="muted-text">—</span>}
        </EditableCell>
      ),
    },
    ...(canEdit
      ? [
          {
            title: '操作',
            key: 'action',
            fixed: isMobile ? undefined : ('right' as const),
            width: 220,
            render: (_: unknown, record: AttendanceRecordItem) => (
              <Segmented
                size="small"
                className="attendance-correction-segment"
                options={ADMIN_CORRECTION_OPTIONS}
                value={displayAttendanceStatus(record.status)}
                disabled={correctingRecordId === record.id}
                onChange={(value) => void updateAdminRecordStatus(record, String(value))}
              />
            ),
          },
        ]
      : []),
  ];

  return (
    <div className="attendance-page admin-attendance student-attendance-center">
      <header className="student-center-topbar">
        <div className="student-center-title">
          <h1>学生考勤中心</h1>
          <span>班级考勤总览</span>
        </div>
        <div className="student-center-actions">
          <Tooltip title={syncStatus?.detail || syncStatus?.action || '暂无钉钉拉取记录'}>
            <span className="student-sync-status">
              <i />
              {syncStatus?.lastPulledAt
                ? `最近拉取钉钉 ${dayjs(syncStatus.lastPulledAt).format('YYYY-MM-DD HH:mm')}`
                : '暂无钉钉拉取记录'}
            </span>
          </Tooltip>
          {canEdit && (
            <Button icon={<ScheduleOutlined />} onClick={openPeriodConfig}>
              时段配置
            </Button>
          )}
          <PermissionButton
            permission="attendance:create"
            icon={<ReloadOutlined />}
            loading={refreshingDingTalk}
            onClick={() => void refreshDingTalkAttendance()}
          >
            刷新钉钉考勤
          </PermissionButton>
          <PermissionButton
            permission="attendance:export"
            icon={<ExportOutlined />}
            onClick={handleExport}
          >
            导出当前报表
          </PermissionButton>
        </div>
      </header>

      <section className="student-filter-panel" aria-label="考勤筛选">
        <div className="student-filter-field student-filter-field--date">
          <label>日期</label>
          <DatePicker
            allowClear={false}
            value={attendanceDate}
            disabledDate={(current) => current.isAfter(dayjs(), 'day')}
            onChange={(value) => {
              setAttendanceDate(value);
              setScheduleId(undefined);
              setPage(1);
            }}
          />
        </div>
        <div className="student-filter-field">
          <label>班级</label>
          <Select
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder="全部班级"
            value={classId}
            onChange={(value) => {
              setClassId(value);
              setScheduleId(undefined);
              setPage(1);
            }}
            options={classOptions.map((item) => ({ value: item.classId, label: item.className }))}
          />
        </div>
        <div className="student-filter-field">
          <label>科目</label>
          <Select
            allowClear
            showSearch
            optionFilterProp="label"
            placeholder={classId ? '全部科目' : '请先选择班级'}
            value={scheduleId}
            loading={scheduleOptionsLoading}
            disabled={!classId || !attendanceDate}
            notFoundContent={scheduleOptionsLoading ? <Spin size="small" /> : '当前日期没有排课'}
            onChange={(value) => {
              setScheduleId(value);
              setPage(1);
            }}
            options={subjectScheduleOptions}
          />
        </div>
        <div className="student-filter-field">
          <label>任课老师</label>
          <Select disabled placeholder="全部老师" />
        </div>
        <div className="student-filter-field">
          <label>时段</label>
          <Select
            allowClear
            placeholder="全部时段"
            value={session}
            onChange={(value) => {
              setSession(value);
              setPage(1);
            }}
            options={sessionOptions}
          />
        </div>
        <div className="student-filter-actions">
          <Button onClick={resetFilters}>重置</Button>
          <Button type="primary" icon={<FileSearchOutlined />} onClick={() => void loadRecords()}>
            查询
          </Button>
        </div>
      </section>

      <section className="student-class-overview" aria-label="班级考勤汇总">
        <div className="student-class-identity">
          <div className="student-class-heading">
            <span className="student-overview-kicker">班级考勤概览</span>
            <h2>{selectedClass}</h2>
            <p>
              {dateLabel} · 当前展示 {visibleStudents.length} 名学生 / {total} 条记录
            </p>
          </div>
          <div className="student-teacher-list" aria-label="筛选上下文">
            <div className="student-teacher-item">
              <Avatar>班</Avatar>
              <div>
                <span>班主任</span>
                <strong>{headTeacherNames}</strong>
              </div>
            </div>
            <div className="student-teacher-item">
              <Avatar>生</Avatar>
              <div>
                <span>生活老师</span>
                <strong>{lifeTeacherNames}</strong>
              </div>
            </div>
            <div className="student-teacher-item">
              <Avatar>任</Avatar>
              <div>
                <span>任课老师</span>
                <strong>{subjectTeacherNames}</strong>
              </div>
            </div>
          </div>
        </div>
        <div className="student-metric-strip">
          {ADMIN_METRIC_META.map((metric) => {
            const value =
              metric.key === 'all'
                ? `${attendanceRate}%`
                : metric.key === 'absent'
                  ? summary.absent + summary.pending
                  : (summary[metric.key as keyof AttendanceSummary] ?? 0);
            const meta = STATUS_META[metric.key] ?? { className: 'is-present' };
            return (
              <button
                type="button"
                key={metric.key}
                className={`student-metric-card ${metricFilter === metric.key ? 'active' : ''}`}
                onClick={() => setMetricFilter(metric.key)}
              >
                <span className={`student-metric-icon ${meta.className}`}>{metric.short}</span>
                <span className="student-metric-copy">
                  <strong>{value}</strong>
                  <small>{metric.label}</small>
                </span>
              </button>
            );
          })}
        </div>
      </section>

      {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>
      )}

      <section className="student-workspace">
        <header className="student-workspace-header">
          <div>
            <h3>班级学生考勤</h3>
            <span>
              {metricFilter === 'all'
                ? `显示全部 ${visibleStudents.length} 名学生`
                : `筛出 ${ADMIN_METRIC_META.find((item) => item.key === metricFilter)?.label || ''}相关 ${visibleStudents.length} 名学生`}
            </span>
          </div>
          <div className="student-workspace-tools">
            <Input.Search
              allowClear
              placeholder="搜索姓名或学号"
              value={studentSearch}
              onChange={(event) => setStudentSearch(event.target.value)}
            />
            <Button icon={<ExportOutlined />} onClick={handleExport}>
              导出
            </Button>
          </div>
        </header>
        <div className="student-legend">
          <span>
            <i className="is-present" />
            正常
          </span>
          <span>
            <i className="is-leave" />
            请假
          </span>
          <span>
            <i className="is-absent" />
            缺勤
          </span>
          <em>仅显示当天已生成考勤的课程/时段，不再为无课时段补默认缺勤</em>
        </div>
        <Spin spinning={loading}>
          {visibleStudents.length === 0 ? (
            <Empty
              image={Empty.PRESENTED_IMAGE_SIMPLE}
              description="未找到匹配学生，请调整筛选条件或搜索关键词"
            />
          ) : (
            <div className="student-card-grid">
              {visibleStudents.map((student) => (
                <button
                  type="button"
                  key={student.key}
                  className={`student-attendance-card ${selectedStudent?.studentId === student.studentId ? 'selected' : ''}`}
                  onClick={() => setSelectedStudent(student)}
                >
                  <span className="student-attendance-head">
                    <strong>{student.studentName}</strong>
                    {student.studentNo && <small>学号 {student.studentNo}</small>}
                  </span>
                  <span className="student-status-blocks">
                    {sortAttendanceRecords(student.records).map((record) => {
                      const currentStatus = displayAttendanceStatus(record.status);
                      const meta = STATUS_META[currentStatus] ?? STATUS_META.absent;
                      const sessionLabel = sessionMap[record.session] || record.session;
                      return (
                        <span
                          key={record.id}
                          className={`student-status-block ${meta.className}`}
                          title={`${sessionLabel}：${meta.label}`}
                        >
                          {meta.label === '出勤' ? '正常' : meta.label}
                        </span>
                      );
                    })}
                  </span>
                </button>
              ))}
            </div>
          )}
        </Spin>
      </section>

      <Card className="student-record-card" bordered={false} title="原始考勤明细">
        <Table<AttendanceRecordItem>
          rowKey="id"
          columns={columns}
          dataSource={records}
          loading={loading}
          scroll={{ x: 'max-content' }}
          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>

      <Drawer
        open={Boolean(selectedStudent)}
        onClose={() => setSelectedStudent(null)}
        width={isMobile ? '100%' : 520}
        title="学生考勤明细"
        className="student-detail-drawer"
      >
        {selectedStudent && (
          <div className="student-detail-panel">
            <section className="student-detail-profile">
              <Avatar size={54}>{selectedStudent.studentName.slice(0, 1)}</Avatar>
              <div>
                <h4>{selectedStudent.studentName}</h4>
                <p>
                  {selectedStudent.className}
                  {selectedStudent.studentNo ? ` · 学号 ${selectedStudent.studentNo}` : ''}
                </p>
              </div>
              <div className="student-detail-rate">
                <strong>{selectedStudent.rate}%</strong>
                <span>累计出勤率</span>
              </div>
            </section>
            <section className="student-detail-rates">
              {sortAttendanceRecords(selectedStudent.records).map((record) => {
                const normal = record.status === 'present';
                return (
                  <div key={record.id}>
                    <strong>{normal ? '100%' : '0%'}</strong>
                    <span>{sessionMap[record.session] || record.session}</span>
                  </div>
                );
              })}
            </section>
            <section className="student-detail-section">
              <h5>当天打卡时间</h5>
              <div className="student-detail-timeline">
                {sortAttendanceRecords(selectedStudent.records).map((record) => (
                  <div key={record.id}>
                    <span>{sessionMap[record.session] || record.session}</span>
                    <AttendanceStatusTag status={displayAttendanceStatus(record.status)} />
                    <strong>
                      {record.punchTime ? dayjs(record.punchTime).format('HH:mm:ss') : '未记录'}
                    </strong>
                    {canEdit && (
                      <Segmented
                        size="small"
                        className="attendance-correction-segment"
                        options={ADMIN_CORRECTION_OPTIONS}
                        value={displayAttendanceStatus(record.status)}
                        disabled={correctingRecordId === record.id}
                        onChange={(value) => void updateAdminRecordStatus(record, String(value))}
                      />
                    )}
                  </div>
                ))}
              </div>
            </section>
          </div>
        )}
      </Drawer>

      <Modal
        open={periodModalOpen}
        title="考勤时段配置"
        okText="保存配置"
        width={860}
        className="attendance-period-modal"
        onOk={savePeriodConfig}
        onCancel={() => setPeriodModalOpen(false)}
        footer={(_, { OkBtn, CancelBtn }) => (
          <>
            <Button onClick={resetPeriodConfig}>恢复默认</Button>
            <CancelBtn />
            <OkBtn />
          </>
        )}
      >
        <Alert
          type="info"
          showIcon
          title="按课程开始时间自动匹配时段"
          description="默认：07:30-08:30 早自习，09:00-12:00 早课，14:00-17:00 晚课，18:30-21:00 晚自习。"
          style={{ marginBottom: 16 }}
        />
        <Form form={periodForm} layout="vertical">
          <Form.List name="periods">
            {(fields, { add, remove }) => (
              <div className="attendance-period-editor">
                {fields.map((field) => (
                  <div className="attendance-period-row" key={field.key}>
                    <Form.Item
                      name={[field.name, 'label']}
                      label="显示名称"
                      rules={[{ required: true, message: '请输入名称' }]}
                    >
                      <Input placeholder="早课" />
                    </Form.Item>
                    <Form.Item
                      name={[field.name, 'periodKey']}
                      label="类型标识"
                      rules={[{ required: true, message: '请输入标识' }]}
                    >
                      <Input placeholder="morning" />
                    </Form.Item>
                    <Form.Item
                      name={[field.name, 'startTime']}
                      label="开始时间"
                      rules={[{ required: true, message: '请选择开始时间' }]}
                    >
                      <Input type="time" />
                    </Form.Item>
                    <Form.Item
                      name={[field.name, 'endTime']}
                      label="结束时间"
                      rules={[{ required: true, message: '请选择结束时间' }]}
                    >
                      <Input type="time" />
                    </Form.Item>
                    <Form.Item name={[field.name, 'enabled']} label="状态">
                      <Select
                        options={[
                          { value: true, label: '启用' },
                          { value: false, label: '停用' },
                        ]}
                      />
                    </Form.Item>
                    <Button
                      danger
                      className="attendance-period-row__delete"
                      onClick={() => remove(field.name)}
                    >
                      删除
                    </Button>
                  </div>
                ))}
                <Button
                  block
                  type="dashed"
                  className="attendance-period-add"
                  onClick={() =>
                    add({
                      periodKey: '',
                      label: '',
                      startTime: '00:00',
                      endTime: '00:30',
                      enabled: true,
                    })
                  }
                >
                  添加时段
                </Button>
              </div>
            )}
          </Form.List>
        </Form>
      </Modal>
    </div>
  );
};

export default AttendancePage;
