import { useEffect, useMemo, useState } from 'react';
import Taro from '@tarojs/taro';
import { Button, Input, Text, Textarea, View } from '@tarojs/components';
import {
  bulkAssignTenantClassMembers,
  bulkUpsertTenantStudents,
  generateTenantStudentSupervision,
  loadTenantClasses,
  loadTenantStudentFollowups,
  loadTenantStudentFollowupReport,
  loadTenantStudentNotes,
  loadTenantStudentSupervisionRules,
  loadTenantStudents,
  loadTenantTeachers,
  loadTenantMembers,
  previewTenantStudentSupervision,
  pushTenantStudentsToCrm,
  updateTenantStudentStatus,
  upsertTenantStudent,
  upsertTenantStudentFollowup,
  upsertTenantStudentNote,
  upsertTenantStudentSupervisionRule,
  type BulkOperationResult,
  type TenantClassItem,
  type TenantStudentFollowupItem,
  type TenantStudentInput,
  type TenantStudentItem,
  type TenantStudentNoteItem,
  type TenantStudentCrmPushInput,
  type TenantStudentFollowupReport,
  type TenantStudentSupervisionCandidate,
  type TenantStudentSupervisionRuleItem,
  type TenantTeacherItem,
  type TenantMemberItem,
} from '@/services/tenantAdmin';
import '../admin.css';

const statusOptions = ['', 'active', 'invited', 'disabled'];
const noteTypes = ['general', 'learning', 'service', 'sales', 'risk', 'follow_up'];
const followupTypes = ['learning', 'service', 'sales', 'renewal', 'risk', 'custom'];
const followupPriorities = ['low', 'normal', 'high', 'urgent'];
const followupStatuses = ['open', 'in_progress', 'done', 'cancelled'];
const crmAssignableRoles = ['tenant_owner', 'tenant_admin', 'tenant_operator', 'teacher', 'sales', 'agent'];
const defaultSupervisionRules = {
  windowDays: 14,
  inactivityDays: 7,
  minAnswers: 10,
  lowAccuracyThreshold: 0.6,
  wrongQuestionThreshold: 5,
  vocabularyDueThreshold: 20,
  staleSessionDays: 3,
};

function emptyStudentForm(): TenantStudentInput {
  return {
    userId: '',
    username: '',
    name: '',
    phone: '',
    email: '',
    regionId: '',
    selectedSchoolId: '',
    selectedMajorId: '',
    status: 'active',
  };
}

function normalizeBlank(value: string | null | undefined) {
  return value && value.trim() ? value.trim() : undefined;
}

function parseJsonOrRows(text: string): TenantStudentInput[] {
  const trimmed = text.trim();
  if (!trimmed) return [];
  if (trimmed.startsWith('[')) {
    const parsed = JSON.parse(trimmed) as TenantStudentInput[];
    return Array.isArray(parsed) ? parsed : [];
  }
  return trimmed
    .split(/\r?\n/)
    .map(row => row.trim())
    .filter(Boolean)
    .map(row => {
      const [name, phone, email, status] = row.split(/[\t,，]/).map(part => part.trim());
      return {
        name,
        phone,
        email,
        status: status || 'active',
      };
    });
}

function resultSummary(result: BulkOperationResult | null) {
  if (!result) return '';
  return `总数 ${result.total || 0} · 成功 ${result.successCount || 0} · 失败 ${result.errorCount || 0}`;
}

function parseIdRows(text: string) {
  return Array.from(new Set(text
    .split(/\r?\n|,|，|\s+/)
    .map(item => item.trim())
    .filter(Boolean)));
}

function studentTitle(item: TenantStudentItem | null) {
  if (!item) return '未选择学生';
  return item.name || item.phone || item.email || item.username || item.userId;
}

export default function TenantStudentsPage() {
  const [keyword, setKeyword] = useState('');
  const [classes, setClasses] = useState<TenantClassItem[]>([]);
  const [students, setStudents] = useState<TenantStudentItem[]>([]);
  const [teachers, setTeachers] = useState<TenantTeacherItem[]>([]);
  const [crmAssignees, setCrmAssignees] = useState<TenantMemberItem[]>([]);
  const [notes, setNotes] = useState<TenantStudentNoteItem[]>([]);
  const [followups, setFollowups] = useState<TenantStudentFollowupItem[]>([]);
  const [selectedClassId, setSelectedClassId] = useState('');
  const [studentStatus, setStudentStatus] = useState('');
  const [selectedStudent, setSelectedStudent] = useState<TenantStudentItem | null>(null);
  const [studentForm, setStudentForm] = useState<TenantStudentInput>(emptyStudentForm());
  const [bulkText, setBulkText] = useState('');
  const [assignText, setAssignText] = useState('');
  const [noteForm, setNoteForm] = useState({ noteType: 'learning', content: '', visibility: 'tenant_staff', isPinned: false });
  const [followupForm, setFollowupForm] = useState({ title: '', description: '', followupType: 'learning', priority: 'normal', status: 'open', dueAt: '', assignedToUserId: '', classId: '' });
  const [crmPushText, setCrmPushText] = useState('');
  const [crmPushForm, setCrmPushForm] = useState<TenantStudentCrmPushInput>({
    studentUserIds: [],
    source: 'manual_batch',
    title: '',
    message: '',
    followupType: 'sales',
    priority: 'normal',
    assignedToUserId: '',
    classId: '',
    dueAt: '',
  });
  const [bulkResult, setBulkResult] = useState<BulkOperationResult | null>(null);
  const [assignResult, setAssignResult] = useState<BulkOperationResult | null>(null);
  const [crmPushResult, setCrmPushResult] = useState<BulkOperationResult | null>(null);
  const [supervisionResult, setSupervisionResult] = useState<BulkOperationResult | null>(null);
  const [followupReport, setFollowupReport] = useState<TenantStudentFollowupReport['item'] | null>(null);
  const [supervisionCandidates, setSupervisionCandidates] = useState<TenantStudentSupervisionCandidate[]>([]);
  const [supervisionRulesList, setSupervisionRulesList] = useState<TenantStudentSupervisionRuleItem[]>([]);
  const [supervisionRules, setSupervisionRules] = useState(defaultSupervisionRules);
  const [scoped, setScoped] = useState(false);
  const [busy, setBusy] = useState('');
  const [error, setError] = useState('');

  const activeClass = useMemo(
    () => classes.find(item => item.id === selectedClassId) || null,
    [classes, selectedClassId],
  );

  function reload(nextClassId = selectedClassId, nextKeyword = keyword, nextStatus = studentStatus) {
    setError('');
    Promise.all([
      loadTenantClasses(80).catch(() => ({ items: [] })),
      loadTenantTeachers({ limit: 80 }).catch(() => ({ items: [] })),
      loadTenantMembers({ status: 'active', limit: 80 }).catch(() => ({ items: [] })),
      loadTenantStudents({
        classId: nextClassId || undefined,
        keyword: nextKeyword || undefined,
        status: nextStatus || undefined,
        limit: 80,
      }),
      loadTenantStudentFollowups({ status: 'open', limit: 30 }).catch(() => ({ items: [] })),
      loadTenantStudentFollowupReport({ timeRange: '30d', classId: nextClassId || undefined, limit: 8 }).catch(() => ({ item: null })),
      loadTenantStudentSupervisionRules({ limit: 20 }).catch(() => ({ items: [] })),
    ]).then(([classPayload, teacherPayload, memberPayload, studentPayload, followupPayload, reportPayload, supervisionRulePayload]) => {
      setClasses(classPayload.items || []);
      setTeachers(teacherPayload.items || []);
      setCrmAssignees((memberPayload.items || []).filter(item => crmAssignableRoles.includes(String(item.role || ''))));
      setStudents(studentPayload.items || []);
      setScoped(studentPayload.scoped === true);
      setFollowups(followupPayload.items || []);
      setFollowupReport(reportPayload.item || null);
      setSupervisionRulesList(supervisionRulePayload.items || []);
    }).catch(nextError => setError(nextError instanceof Error ? nextError.message : '学生数据加载失败'));
  }

  useEffect(() => {
    reload('', '');
  }, []);

  function chooseClass(classId: string) {
    setSelectedClassId(classId);
    setFollowupForm(prev => ({ ...prev, classId }));
    reload(classId, keyword, studentStatus);
  }

  function chooseStatus(status: string) {
    setStudentStatus(status);
    reload(selectedClassId, keyword, status);
  }

  async function selectStudent(item: TenantStudentItem) {
    setSelectedStudent(item);
    setStudentForm({
      userId: item.userId,
      username: item.username || '',
      name: item.name || '',
      phone: item.phone || '',
      email: item.email || '',
      regionId: item.regionId || '',
      selectedSchoolId: item.selectedSchoolId || '',
      selectedMajorId: item.selectedMajorId || '',
      status: item.status || 'active',
    });
    setFollowupForm(prev => ({ ...prev, studentUserId: item.userId, classId: selectedClassId || String((item.classes || [])[0]?.classId || '') } as typeof prev));
    setCrmPushText(item.userId);
    setCrmPushForm(prev => ({
      ...prev,
      studentUserIds: [item.userId],
      classId: selectedClassId || String((item.classes || [])[0]?.classId || ''),
    }));
    setError('');
    try {
      const [notePayload, followupPayload] = await Promise.all([
        loadTenantStudentNotes(item.userId).catch(() => ({ items: [] })),
        loadTenantStudentFollowups({ studentUserId: item.userId, limit: 20 }).catch(() => ({ items: [] })),
      ]);
      setNotes(notePayload.items || []);
      setFollowups(followupPayload.items || []);
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '学生详情加载失败');
    }
  }

  function newStudent() {
    setSelectedStudent(null);
    setNotes([]);
    setFollowups([]);
    setStudentForm(emptyStudentForm());
    setNoteForm({ noteType: 'learning', content: '', visibility: 'tenant_staff', isPinned: false });
    setFollowupForm({ title: '', description: '', followupType: 'learning', priority: 'normal', status: 'open', dueAt: '', assignedToUserId: '', classId: selectedClassId });
  }

  async function saveStudent() {
    setBusy('student');
    setError('');
    try {
      await upsertTenantStudent({
        ...studentForm,
        userId: normalizeBlank(studentForm.userId),
        username: normalizeBlank(studentForm.username),
        name: normalizeBlank(studentForm.name),
        phone: normalizeBlank(studentForm.phone),
        email: normalizeBlank(studentForm.email),
        regionId: normalizeBlank(studentForm.regionId),
        selectedSchoolId: normalizeBlank(studentForm.selectedSchoolId),
        selectedMajorId: normalizeBlank(studentForm.selectedMajorId),
        status: studentForm.status || 'active',
      });
      Taro.showToast({ title: '学生已保存', icon: 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '学生保存失败');
    } finally {
      setBusy('');
    }
  }

  async function changeStudentStatus(item: TenantStudentItem, status: string) {
    const modal = await Taro.showModal({
      title: status === 'disabled' ? '禁用学生' : '恢复学生',
      content: studentTitle(item),
      confirmText: status === 'disabled' ? '禁用' : '恢复',
      cancelText: '取消',
    });
    if (!modal.confirm) return;
    setBusy(`status:${item.userId}`);
    setError('');
    try {
      await updateTenantStudentStatus({ userId: item.userId, status, reason: 'taro-tenant-admin' });
      Taro.showToast({ title: '状态已更新', icon: 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '状态更新失败');
    } finally {
      setBusy('');
    }
  }

  async function submitBulkUpsert() {
    setBusy('bulk');
    setError('');
    try {
      const rows = parseJsonOrRows(bulkText);
      const result = await bulkUpsertTenantStudents(rows);
      setBulkResult(result);
      Taro.showToast({ title: '批量导入已完成', icon: result.errorCount ? 'none' : 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '批量导入失败');
    } finally {
      setBusy('');
    }
  }

  async function submitBulkAssign() {
    if (!selectedClassId) {
      Taro.showToast({ title: '请选择班级', icon: 'none' });
      return;
    }
    setBusy('assign');
    setError('');
    try {
      const rows = parseJsonOrRows(assignText).map(item => ({ ...item, memberType: 'student', status: 'active' }));
      const result = await bulkAssignTenantClassMembers({ classId: selectedClassId, assignments: rows });
      setAssignResult(result);
      Taro.showToast({ title: '批量分班已完成', icon: result.errorCount ? 'none' : 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '批量分班失败');
    } finally {
      setBusy('');
    }
  }

  async function submitCrmPush() {
    const studentUserIds = parseIdRows(crmPushText);
    if (!studentUserIds.length) {
      Taro.showToast({ title: '请填写学生ID', icon: 'none' });
      return;
    }
    if (!crmPushForm.title?.trim()) {
      Taro.showToast({ title: '请填写任务标题', icon: 'none' });
      return;
    }
    setBusy('crmPush');
    setError('');
    try {
      const result = await pushTenantStudentsToCrm({
        ...crmPushForm,
        studentUserIds,
        title: crmPushForm.title.trim(),
        message: crmPushForm.message?.trim() || null,
        assignedToUserId: crmPushForm.assignedToUserId || null,
        classId: crmPushForm.classId || selectedClassId || null,
        dueAt: crmPushForm.dueAt || null,
        metadata: { source: 'taro-tenant-admin' },
        idempotencyKey: `taro-${Date.now()}`,
      });
      setCrmPushResult(result);
      Taro.showToast({ title: 'CRM推送已入队', icon: result.errorCount ? 'none' : 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : 'CRM推送失败');
    } finally {
      setBusy('');
    }
  }

  async function previewSupervision() {
    setBusy('supervisionPreview');
    setError('');
    try {
      const payload = await previewTenantStudentSupervision({
        ...supervisionRules,
        classId: selectedClassId || undefined,
        limit: 20,
      });
      setSupervisionCandidates(payload.item?.candidates || []);
      Taro.showToast({ title: '督导候选已刷新', icon: 'success' });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '学习督导预览失败');
    } finally {
      setBusy('');
    }
  }

  async function generateSupervision() {
    if (!supervisionCandidates.length) {
      Taro.showToast({ title: '请先预览候选', icon: 'none' });
      return;
    }
    setBusy('supervisionGenerate');
    setError('');
    try {
      const result = await generateTenantStudentSupervision({
        rules: supervisionRules,
        classId: selectedClassId || null,
        studentUserIds: supervisionCandidates.map(item => item.studentUserId),
        batchKey: `taro-supervision-${new Date().toISOString().slice(0, 10)}-${selectedClassId || 'all'}`,
        limit: supervisionCandidates.length,
        metadata: { source: 'taro-tenant-admin' },
      });
      setSupervisionResult(result);
      Taro.showToast({ title: '督导任务已生成', icon: result.errorCount ? 'none' : 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '学习督导生成失败');
    } finally {
      setBusy('');
    }
  }

  async function saveSupervisionRule() {
    setBusy('supervisionRule');
    setError('');
    try {
      const payload = await upsertTenantStudentSupervisionRule({
        name: `${activeClass?.name || '全租户'} 学习督导`,
        status: 'active',
        rules: supervisionRules,
        schedule: {
          enabled: true,
          frequency: 'daily',
          hour: 9,
          minute: 0,
          timezone: 'Asia/Shanghai',
          weekdays: [1, 2, 3, 4, 5, 6, 7],
        },
        classId: selectedClassId || null,
        limit: 20,
        metadata: { source: 'taro-tenant-admin' },
      });
      setSupervisionRulesList(prev => [payload.item, ...prev.filter(item => item.id !== payload.item?.id)].filter(Boolean) as TenantStudentSupervisionRuleItem[]);
      Taro.showToast({ title: '督导规则已保存', icon: 'success' });
      reload();
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '督导规则保存失败');
    } finally {
      setBusy('');
    }
  }

  async function saveNote() {
    if (!selectedStudent) {
      Taro.showToast({ title: '请选择学生', icon: 'none' });
      return;
    }
    setBusy('note');
    setError('');
    try {
      await upsertTenantStudentNote({
        studentUserId: selectedStudent.userId,
        noteType: noteForm.noteType,
        content: noteForm.content,
        visibility: noteForm.visibility,
        isPinned: noteForm.isPinned,
        metadata: { source: 'taro-tenant-admin' },
      });
      setNoteForm(prev => ({ ...prev, content: '' }));
      await selectStudent(selectedStudent);
      Taro.showToast({ title: '备注已保存', icon: 'success' });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '备注保存失败');
    } finally {
      setBusy('');
    }
  }

  async function saveFollowup() {
    if (!selectedStudent) {
      Taro.showToast({ title: '请选择学生', icon: 'none' });
      return;
    }
    setBusy('followup');
    setError('');
    try {
      await upsertTenantStudentFollowup({
        studentUserId: selectedStudent.userId,
        assignedToUserId: followupForm.assignedToUserId || null,
        classId: followupForm.classId || null,
        title: followupForm.title,
        description: followupForm.description || null,
        followupType: followupForm.followupType,
        priority: followupForm.priority,
        status: followupForm.status,
        dueAt: followupForm.dueAt || null,
        metadata: { source: 'taro-tenant-admin' },
      });
      setFollowupForm(prev => ({ ...prev, title: '', description: '' }));
      await selectStudent(selectedStudent);
      Taro.showToast({ title: '跟进已保存', icon: 'success' });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '跟进保存失败');
    } finally {
      setBusy('');
    }
  }

  async function completeFollowup(item: TenantStudentFollowupItem) {
    if (!selectedStudent && !item.studentUserId) return;
    setBusy(`followup:${item.id}`);
    setError('');
    try {
      await upsertTenantStudentFollowup({
        id: item.id,
        studentUserId: item.studentUserId || selectedStudent?.userId || '',
        assignedToUserId: item.assignedToUserId || null,
        classId: item.classId || null,
        title: item.title || '跟进任务',
        description: item.description || null,
        followupType: item.followupType || 'learning',
        priority: item.priority || 'normal',
        status: 'done',
        dueAt: item.dueAt || null,
        metadata: item.metadata || { source: 'taro-tenant-admin' },
      });
      if (selectedStudent) await selectStudent(selectedStudent);
      else reload();
      Taro.showToast({ title: '已完成', icon: 'success' });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '跟进更新失败');
    } finally {
      setBusy('');
    }
  }

  return (
    <View className='admin-page'>
      <View className='admin-shell'>
        <View className='admin-header'>
          <Text className='admin-kicker'>Students</Text>
          <Text className='admin-title'>学生运营</Text>
          <Text className='admin-subtitle'>学生、班级、教师范围权限和学习督导的后台入口。</Text>
        </View>

        <View className='admin-actions'>
          <Input className='admin-input' placeholder='手机号、姓名、邮箱' value={keyword} onInput={event => setKeyword(String(event.detail.value || ''))} />
          <Button className='admin-button primary' onClick={() => reload(selectedClassId, keyword, studentStatus)}>搜索</Button>
          <Button className='admin-button' onClick={newStudent}>新建</Button>
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>班级</Text>
          <View className='admin-tabs'>
            <Button className={`admin-button ${selectedClassId ? '' : 'active'}`} onClick={() => chooseClass('')}>全部</Button>
            {classes.map(item => (
              <Button key={item.id} className={`admin-button ${selectedClassId === item.id ? 'active' : ''}`} onClick={() => chooseClass(item.id)}>
                {item.name}
              </Button>
            ))}
          </View>
          <View className='admin-grid'>
            {classes.slice(0, 6).map(item => (
              <View className='admin-metric' key={item.id}>
                <Text className='admin-metric-label'>{item.code || item.status || '班级'}</Text>
                <Text className='admin-metric-value'>{item.name}</Text>
                <Text className='admin-row-meta'>{item.studentCount || 0} 学生 · {item.teacherCount || 0} 教师</Text>
              </View>
            ))}
          </View>
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>状态</Text>
          <View className='admin-actions compact'>
            {statusOptions.map(status => (
              <Button key={status || 'all'} className={`admin-button ${studentStatus === status ? 'active' : ''}`} onClick={() => chooseStatus(status)}>
                {status || '全部'}
              </Button>
            ))}
          </View>
          {scoped ? <Text className='admin-row-meta'>当前角色已启用班级/学生范围过滤。</Text> : null}
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>学生档案</Text>
          <View className='admin-form-grid'>
            <Input className='admin-input' placeholder='userId，可留空' value={studentForm.userId || ''} onInput={event => setStudentForm(prev => ({ ...prev, userId: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='姓名' value={studentForm.name || ''} onInput={event => setStudentForm(prev => ({ ...prev, name: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='手机号' value={studentForm.phone || ''} onInput={event => setStudentForm(prev => ({ ...prev, phone: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='邮箱' value={studentForm.email || ''} onInput={event => setStudentForm(prev => ({ ...prev, email: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='地区 ID' value={studentForm.regionId || ''} onInput={event => setStudentForm(prev => ({ ...prev, regionId: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='院校 ID' value={studentForm.selectedSchoolId || ''} onInput={event => setStudentForm(prev => ({ ...prev, selectedSchoolId: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='专业 ID' value={studentForm.selectedMajorId || ''} onInput={event => setStudentForm(prev => ({ ...prev, selectedMajorId: String(event.detail.value || '') }))} />
          </View>
          <View className='admin-actions compact'>
            {['active', 'invited', 'disabled'].map(status => (
              <Button key={status} className={`admin-button ${studentForm.status === status ? 'active' : ''}`} onClick={() => setStudentForm(prev => ({ ...prev, status }))}>{status}</Button>
            ))}
            <Button className='admin-button primary' loading={busy === 'student'} onClick={saveStudent}>保存学生</Button>
          </View>
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>批量导入</Text>
          <Textarea
            className='admin-textarea'
            placeholder='张三,13800000001,student@example.com,active'
            value={bulkText}
            onInput={event => setBulkText(String(event.detail.value || ''))}
          />
          <View className='admin-actions compact'>
            <Button className='admin-button primary' loading={busy === 'bulk'} onClick={submitBulkUpsert}>执行导入</Button>
            {bulkResult ? <Text className='admin-row-meta'>{resultSummary(bulkResult)}</Text> : null}
          </View>
          {bulkResult?.errors?.slice(0, 3).map(item => (
            <Text className='admin-row-meta break-line' key={`${item.index}:${item.code}`}>第 {Number(item.index || 0) + 1} 行 · {item.code} · {item.message}</Text>
          ))}
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>批量分班</Text>
          <View className='admin-row'>
            <Text className='admin-row-main'>{activeClass?.name || '未选择班级'}</Text>
            <Text className='admin-row-meta'>{activeClass?.studentCount || 0} 学生 · {activeClass?.teacherCount || 0} 教师</Text>
          </View>
          <Textarea
            className='admin-textarea'
            placeholder='李四,13800000002,student2@example.com'
            value={assignText}
            onInput={event => setAssignText(String(event.detail.value || ''))}
          />
          <View className='admin-actions compact'>
            <Button className='admin-button primary' loading={busy === 'assign'} onClick={submitBulkAssign}>执行分班</Button>
            {assignResult ? <Text className='admin-row-meta'>{resultSummary(assignResult)}</Text> : null}
          </View>
          {assignResult?.errors?.slice(0, 3).map(item => (
            <Text className='admin-row-meta break-line' key={`${item.index}:${item.code}`}>第 {Number(item.index || 0) + 1} 行 · {item.code} · {item.message}</Text>
          ))}
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>学生列表</Text>
          <View className='admin-list'>
            {students.map(item => (
              <View className='admin-row' key={item.userId}>
                <Text className='admin-row-main'>{item.name || item.phone || item.email || item.userId}</Text>
                <Text className='admin-row-meta'>{item.status || 'active'} · {item.regionName || '未选地区'}{item.selectedSchoolName ? ` · ${item.selectedSchoolName}` : ''}{item.selectedMajorName ? ` · ${item.selectedMajorName}` : ''}</Text>
                <Text className='admin-row-meta'>今日答题 {item.questionsAnsweredToday || 0} · 掌握单词 {item.masteredWordsCount || 0} · 班级 {(item.classes || []).length}</Text>
                <View className='admin-row-actions'>
                  <Button className='admin-mini-button primary' onClick={() => void selectStudent(item)}>详情</Button>
                  {item.status === 'disabled' ? (
                    <Button className='admin-mini-button' loading={busy === `status:${item.userId}`} onClick={() => changeStudentStatus(item, 'active')}>恢复</Button>
                  ) : (
                    <Button className='admin-mini-button' loading={busy === `status:${item.userId}`} onClick={() => changeStudentStatus(item, 'disabled')}>禁用</Button>
                  )}
                </View>
              </View>
            ))}
          </View>
          {!students.length ? <View className='admin-empty'>暂无学生，或当前角色没有可见学生范围。</View> : null}
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>跟进看板</Text>
          <View className='admin-grid'>
            <View className='admin-metric'>
              <Text className='admin-metric-label'>30 天跟进</Text>
              <Text className='admin-metric-value'>{followupReport?.summary?.total || 0}</Text>
              <Text className='admin-row-meta'>完成 {followupReport?.summary?.done || 0} · CRM {followupReport?.summary?.crmPushTasks || 0}</Text>
            </View>
            <View className='admin-metric'>
              <Text className='admin-metric-label'>待处理</Text>
              <Text className='admin-metric-value'>{followupReport?.summary?.openBacklog || 0}</Text>
              <Text className='admin-row-meta'>逾期 {followupReport?.summary?.overdueBacklog || 0} · 高优先级 {followupReport?.summary?.highPriority || 0}</Text>
            </View>
            <View className='admin-metric'>
              <Text className='admin-metric-label'>完成率</Text>
              <Text className='admin-metric-value'>{Math.round((followupReport?.summary?.completionRate || 0) * 100)}%</Text>
              <Text className='admin-row-meta'>平均 {followupReport?.summary?.avgCompleteHours || 0} 小时</Text>
            </View>
          </View>
          <View className='admin-list'>
            {(followupReport?.byAssignee || []).slice(0, 4).map((item, index) => (
              <View className='admin-row' key={`${item.assignedToUserId || 'none'}:${index}`}>
                <Text className='admin-row-main'>{String(item.assignedToName || '未指派')} · {String(item.assignedToRole || '-')}</Text>
                <Text className='admin-row-meta'>总数 {String(item.total || 0)} · 待处理 {String(item.open || 0)} · 完成 {String(item.done || 0)} · 逾期 {String(item.overdue || 0)}</Text>
              </View>
            ))}
          </View>
          {(followupReport?.overdueItems || []).slice(0, 3).map(item => (
            <Text className='admin-row-meta break-line' key={item.id}>逾期 · {item.title || '跟进任务'} · {item.studentName || item.studentUserId || '-'} · {item.assignedToName || '未指派'}</Text>
          ))}
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>学习督导自动化</Text>
          <View className='admin-form-grid'>
            <Input className='admin-input' placeholder='观察天数' value={String(supervisionRules.windowDays)} onInput={event => setSupervisionRules(prev => ({ ...prev, windowDays: Number(event.detail.value || prev.windowDays) }))} />
            <Input className='admin-input' placeholder='未学习天数' value={String(supervisionRules.inactivityDays)} onInput={event => setSupervisionRules(prev => ({ ...prev, inactivityDays: Number(event.detail.value || prev.inactivityDays) }))} />
            <Input className='admin-input' placeholder='最低答题数' value={String(supervisionRules.minAnswers)} onInput={event => setSupervisionRules(prev => ({ ...prev, minAnswers: Number(event.detail.value || prev.minAnswers) }))} />
            <Input className='admin-input' placeholder='低正确率阈值' value={String(supervisionRules.lowAccuracyThreshold)} onInput={event => setSupervisionRules(prev => ({ ...prev, lowAccuracyThreshold: Number(event.detail.value || prev.lowAccuracyThreshold) }))} />
            <Input className='admin-input' placeholder='错题阈值' value={String(supervisionRules.wrongQuestionThreshold)} onInput={event => setSupervisionRules(prev => ({ ...prev, wrongQuestionThreshold: Number(event.detail.value || prev.wrongQuestionThreshold) }))} />
            <Input className='admin-input' placeholder='待复习单词阈值' value={String(supervisionRules.vocabularyDueThreshold)} onInput={event => setSupervisionRules(prev => ({ ...prev, vocabularyDueThreshold: Number(event.detail.value || prev.vocabularyDueThreshold) }))} />
          </View>
          <View className='admin-actions compact'>
            <Button className='admin-button primary' loading={busy === 'supervisionPreview'} onClick={previewSupervision}>预览候选</Button>
            <Button className='admin-button' loading={busy === 'supervisionGenerate'} onClick={generateSupervision}>生成跟进任务</Button>
            <Button className='admin-button' loading={busy === 'supervisionRule'} onClick={saveSupervisionRule}>保存每日规则</Button>
            {supervisionResult ? <Text className='admin-row-meta'>{resultSummary(supervisionResult)}</Text> : null}
          </View>
          <View className='admin-list'>
            {supervisionCandidates.slice(0, 6).map(item => (
              <View className='admin-row' key={item.studentUserId}>
                <Text className='admin-row-main'>{item.studentName || item.studentUserId} · 风险 {String(item.riskScore || 0)}</Text>
                <Text className='admin-row-meta'>{item.priority || 'normal'} · {item.description || '学习状态需要跟进'}</Text>
              </View>
            ))}
          </View>
          {!supervisionCandidates.length ? <Text className='admin-row-meta'>可按当前班级范围预览未学习、错题积压、正确率偏低、单词待复习和未完成练习的学生。</Text> : null}
          <View className='admin-list'>
            {supervisionRulesList.slice(0, 5).map(item => (
              <View className='admin-row' key={item.id}>
                <Text className='admin-row-main'>{item.name} · {item.status || 'active'}</Text>
                <Text className='admin-row-meta'>范围 {item.className || '全租户'} · 下次 {String(item.nextRunAt || '-')} · 最近 {String(item.lastResult?.status || '未运行')}</Text>
              </View>
            ))}
          </View>
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>CRM 批量推送</Text>
          <View className='admin-form-grid'>
            <Input className='admin-input' placeholder='跟进标题' value={crmPushForm.title} onInput={event => setCrmPushForm(prev => ({ ...prev, title: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='到期时间，例如 2026-07-01T10:00:00.000Z' value={crmPushForm.dueAt || ''} onInput={event => setCrmPushForm(prev => ({ ...prev, dueAt: String(event.detail.value || '') }))} />
          </View>
          <Textarea
            className='admin-textarea'
            placeholder='每行一个学生 userId'
            value={crmPushText}
            onInput={event => setCrmPushText(String(event.detail.value || ''))}
          />
          <Textarea
            className='admin-textarea'
            placeholder='推送说明'
            value={crmPushForm.message || ''}
            onInput={event => setCrmPushForm(prev => ({ ...prev, message: String(event.detail.value || '') }))}
          />
          <View className='admin-actions compact'>
            {followupTypes.map(item => <Button key={item} className={`admin-button ${crmPushForm.followupType === item ? 'active' : ''}`} onClick={() => setCrmPushForm(prev => ({ ...prev, followupType: item }))}>{item}</Button>)}
          </View>
          <View className='admin-actions compact'>
            {followupPriorities.map(item => <Button key={item} className={`admin-button ${crmPushForm.priority === item ? 'active' : ''}`} onClick={() => setCrmPushForm(prev => ({ ...prev, priority: item }))}>{item}</Button>)}
          </View>
          <View className='admin-actions compact'>
            <Button className={`admin-button ${crmPushForm.assignedToUserId ? '' : 'active'}`} onClick={() => setCrmPushForm(prev => ({ ...prev, assignedToUserId: '' }))}>不指派</Button>
            {crmAssignees.slice(0, 12).map(item => (
              <Button key={item.userId} className={`admin-button ${crmPushForm.assignedToUserId === item.userId ? 'active' : ''}`} onClick={() => setCrmPushForm(prev => ({ ...prev, assignedToUserId: item.userId }))}>{item.name || item.phone || item.username || '成员'}</Button>
            ))}
          </View>
          <View className='admin-actions compact'>
            <Button className='admin-button primary' loading={busy === 'crmPush'} onClick={submitCrmPush}>入队推送</Button>
            {selectedStudent ? <Button className='admin-button' onClick={() => setCrmPushText(selectedStudent.userId)}>填入当前学生</Button> : null}
            {crmPushResult ? <Text className='admin-row-meta'>{resultSummary(crmPushResult)}</Text> : null}
          </View>
          {crmPushResult?.errors?.slice(0, 3).map(item => (
            <Text className='admin-row-meta break-line' key={`${item.index}:${item.code}`}>第 {Number(item.index || 0) + 1} 行 · {item.code} · {item.message}</Text>
          ))}
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>学生跟进</Text>
          <View className='admin-row'>
            <Text className='admin-row-main'>{studentTitle(selectedStudent)}</Text>
            <Text className='admin-row-meta'>{selectedStudent?.regionName || '未选地区'} · {selectedStudent?.status || '-'}</Text>
          </View>
          <View className='admin-actions compact'>
            {noteTypes.map(item => (
              <Button key={item} className={`admin-button ${noteForm.noteType === item ? 'active' : ''}`} onClick={() => setNoteForm(prev => ({ ...prev, noteType: item }))}>{item}</Button>
            ))}
            <Button className={`admin-button ${noteForm.isPinned ? 'active' : ''}`} onClick={() => setNoteForm(prev => ({ ...prev, isPinned: !prev.isPinned }))}>置顶</Button>
          </View>
          <Textarea className='admin-textarea' placeholder='学生备注' value={noteForm.content} onInput={event => setNoteForm(prev => ({ ...prev, content: String(event.detail.value || '') }))} />
          <View className='admin-actions compact'>
            <Button className='admin-button primary' loading={busy === 'note'} onClick={saveNote}>保存备注</Button>
          </View>
          <View className='admin-list'>
            {notes.slice(0, 5).map(item => (
              <View className='admin-row' key={item.id}>
                <Text className='admin-row-main'>{item.noteType || 'note'}{item.isPinned ? ' · 置顶' : ''}</Text>
                <Text className='admin-row-meta break-line'>{item.content}</Text>
                <Text className='admin-row-meta'>{item.createdByName || item.createdByUsername || '成员'} · {item.createdAt || '-'}</Text>
              </View>
            ))}
          </View>
        </View>

        <View className='admin-section'>
          <Text className='admin-section-title'>跟进任务</Text>
          <View className='admin-form-grid'>
            <Input className='admin-input' placeholder='标题' value={followupForm.title} onInput={event => setFollowupForm(prev => ({ ...prev, title: String(event.detail.value || '') }))} />
            <Input className='admin-input' placeholder='到期时间，例如 2026-07-01T10:00:00.000Z' value={followupForm.dueAt} onInput={event => setFollowupForm(prev => ({ ...prev, dueAt: String(event.detail.value || '') }))} />
          </View>
          <View className='admin-actions compact'>
            {followupTypes.map(item => <Button key={item} className={`admin-button ${followupForm.followupType === item ? 'active' : ''}`} onClick={() => setFollowupForm(prev => ({ ...prev, followupType: item }))}>{item}</Button>)}
          </View>
          <View className='admin-actions compact'>
            {followupPriorities.map(item => <Button key={item} className={`admin-button ${followupForm.priority === item ? 'active' : ''}`} onClick={() => setFollowupForm(prev => ({ ...prev, priority: item }))}>{item}</Button>)}
          </View>
          <View className='admin-actions compact'>
            {followupStatuses.map(item => <Button key={item} className={`admin-button ${followupForm.status === item ? 'active' : ''}`} onClick={() => setFollowupForm(prev => ({ ...prev, status: item }))}>{item}</Button>)}
          </View>
          <View className='admin-actions compact'>
            <Button className={`admin-button ${followupForm.assignedToUserId ? '' : 'active'}`} onClick={() => setFollowupForm(prev => ({ ...prev, assignedToUserId: '' }))}>不指派</Button>
            {teachers.slice(0, 10).map(item => (
              <Button key={item.userId} className={`admin-button ${followupForm.assignedToUserId === item.userId ? 'active' : ''}`} onClick={() => setFollowupForm(prev => ({ ...prev, assignedToUserId: item.userId }))}>{item.name || item.phone || item.username || '教师'}</Button>
            ))}
          </View>
          <Textarea className='admin-textarea' placeholder='描述' value={followupForm.description} onInput={event => setFollowupForm(prev => ({ ...prev, description: String(event.detail.value || '') }))} />
          <View className='admin-actions compact'>
            <Button className='admin-button primary' loading={busy === 'followup'} onClick={saveFollowup}>保存跟进</Button>
          </View>
          <View className='admin-list'>
            {followups.slice(0, 8).map(item => (
              <View className='admin-row' key={item.id}>
                <Text className='admin-row-main'>{item.title || '跟进任务'} · {item.status || 'open'}</Text>
                <Text className='admin-row-meta'>{item.studentName || item.studentUserId || '-'} · {item.className || '未绑定班级'} · {item.priority || 'normal'}</Text>
                <Text className='admin-row-meta'>{item.assignedToName || item.assignedToUserId || '未指派'} · {item.dueAt || '无到期时间'}</Text>
                {item.description ? <Text className='admin-row-meta break-line'>{item.description}</Text> : null}
                {item.status !== 'done' ? (
                  <View className='admin-row-actions'>
                    <Button className='admin-mini-button primary' loading={busy === `followup:${item.id}`} onClick={() => completeFollowup(item)}>完成</Button>
                  </View>
                ) : null}
              </View>
            ))}
          </View>
        </View>

        {error ? <Text className='admin-error'>{error}</Text> : null}
      </View>
    </View>
  );
}
