// aislop-ignore-file: duplicate-block -- 表格/表单声明结构相似且参数不同，渲染逻辑已共享组件化
import React, { useState, useMemo, useCallback } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useApiMutation } from '../../hooks/useApiMutation';
import { validateResponse } from '../../utils/validate';
import { classesSchema } from '../../api/schemas';
import {
  App,
  Table,
  Button,
  Input,
  Select,
  Space,
  Tag,
  Modal,
  Form,
  InputNumber,
  DatePicker,
  Popconfirm,
  Card,
  Switch,
  Empty,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { PlusOutlined, SearchOutlined, TeamOutlined, InboxOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router';
import dayjs from 'dayjs';
import api from '../../api';
import PermissionButton from '../../components/PermissionButton';
import EditableCell from '../../components/EditableCell';
import { message } from '../../ui/app-message';
import { usePermission } from '../../hooks/usePermission';
import { QueryErrorState } from '../../components/QueryState';
import { useVisibleRefetch } from '../../hooks/usePageVisible';
import { useDirtyGuard } from '../../hooks/useDirtyGuard';

interface ClassItem {
  id: number;
  name: string;
  code: string;
  classType: string;
  startDate: string | null;
  endDate: string | null;
  status: string;
  headTeacherId: number | null;
  lifeTeacherId: number | null;
  academicTeacherId: number | null;
  maxStudents: number;
  notes: string | null;
  studentCount: number;
  isArchived: boolean;
  createdAt: string;
  updatedAt: string;
}

interface ClassFormValues {
  name: string;
  code: string;
  classType: string;
  startDate?: dayjs.Dayjs;
  endDate?: dayjs.Dayjs;
  maxStudents?: number;
  status?: string;
  notes?: string;
}

const STATUS_MAP: Record<string, { color: string; text: string }> = {
  enrolling: { color: 'blue', text: '招生中' },
  active: { color: 'green', text: '在读' },
  ended: { color: 'default', text: '结课' },
  suspended: { color: 'orange', text: '停课' },
};

const TYPE_MAP: Record<string, string> = {
  culture: '文化课',
  professional: '专业课',
  bootcamp: '集训营',
  sprint: '冲刺营',
};

const ClassesPage: React.FC = () => {
  const { modal } = App.useApp();
  const navigate = useNavigate();
  const { hasPermission } = usePermission();
  const canPurgeClass = hasPermission('class:purge');
  const [modalOpen, setModalOpen] = useState(false);
  const [editing, setEditing] = useState<ClassItem | null>(null);
  const [searchText, setSearchText] = useState('');
  const [filterStatus, setFilterStatus] = useState<string>();
  const [filterType, setFilterType] = useState<string>();
  const [form] = Form.useForm<ClassFormValues>();
  const classFormGuard = useDirtyGuard(form);
  const [saving, setSaving] = useState(false);
  const [showArchived, setShowArchived] = useState(false);

  const {
    data = [],
    isLoading,
    isFetching,
    isError,
    refetch,
  } = useQuery<ClassItem[]>({
    queryKey: ['classes', filterStatus, filterType, showArchived],
    queryFn: async () => {
      const params: Record<string, string | boolean | undefined> = {};
      if (filterStatus) params.status = filterStatus;
      if (filterType) params.classType = filterType;
      params.isArchived = showArchived;
      return validateResponse<ClassItem[]>(
        classesSchema,
        await api.get<ClassItem[]>('/classes', { params } as Record<string, unknown>),
      );
    },
  });
  const loading = isLoading || isFetching;
  // RouteKeeper 保活页面切回时刷新列表，避免看到陈旧数据
  useVisibleRefetch(['classes']);

  const saveMutation = useApiMutation(
    async (payload: Record<string, unknown>) =>
      editing ? api.put(`/classes/${editing.id}`, payload) : api.post('/classes', payload),
    { invalidate: [['classes']] },
  );
  const saveCellMutation = useApiMutation(
    async ({ record, field, value }: { record: ClassItem; field: string; value: unknown }) =>
      api.put(`/classes/${record.id}`, { [field]: value }),
    { invalidate: [['classes']] },
  );
  const archiveMutation = useApiMutation(
    async ({ id, archive }: { id: number; archive: boolean }) =>
      api.put(`/classes/${id}/${archive ? 'archive' : 'restore'}`),
    { invalidate: [['classes']] },
  );
  const purgeMutation = useApiMutation(
    async (id: number) => api.delete(`/classes/${id}/permanent`),
    { invalidate: [['classes']] },
  );

  const handleArchive = useCallback(
    async (id: number, archive: boolean) => {
      try {
        await archiveMutation.mutateAsync({ id, archive });
        message.success(archive ? '已归档' : '已恢复');
      } catch {
        // 错误提示由 useApiMutation 统一处理
      }
    },
    [archiveMutation],
  );

  const handlePurge = useCallback(
    (record: ClassItem) => {
      modal.confirm({
        title: `永久删除班级「${record.name}」？`,
        content: '删除后不可恢复，存在学生、教师、排课、考试或考勤关联时将无法删除。确定继续？',
        okText: '永久删除',
        okButtonProps: { danger: true },
        cancelText: '取消',
        onOk: async () => {
          try {
            await purgeMutation.mutateAsync(record.id);
            message.success('已永久删除（不可恢复）');
          } catch {
            // 错误提示由 useApiMutation 统一处理
          }
        },
      });
    },
    [modal, purgeMutation],
  );

  const filtered = useMemo(() => {
    if (!searchText) return data;
    const q = searchText.toLowerCase();
    return data.filter(
      (c) => c.name?.toLowerCase().includes(q) || c.code?.toLowerCase().includes(q),
    );
  }, [data, searchText]);

  const handleCreate = () => {
    setEditing(null);
    form.resetFields();
    classFormGuard.snapshot();
    setModalOpen(true);
  };

  const handleEdit = useCallback(
    (record: ClassItem) => {
      setEditing(record);
      form.setFieldsValue({
        ...record,
        notes: record.notes ?? undefined,
        startDate: record.startDate ? dayjs(record.startDate) : undefined,
        endDate: record.endDate ? dayjs(record.endDate) : undefined,
      });
      classFormGuard.snapshot();
      setModalOpen(true);
    },
    [form, classFormGuard],
  );

  const handleSubmit = async () => {
    setSaving(true);
    try {
      const values = await form.validateFields();
      const payload = {
        ...values,
        startDate: values.startDate?.format('YYYY-MM-DD'),
        endDate: values.endDate?.format('YYYY-MM-DD'),
      };
      await saveMutation.mutateAsync(payload);
      message.success(editing ? '更新成功' : '创建成功');
      setModalOpen(false);
    } catch {
      // 错误提示由 useApiMutation 统一处理
    } finally {
      setSaving(false);
    }
  };

  const saveCell = useCallback(
    async (record: ClassItem, field: string, value: unknown) => {
      try {
        await saveCellMutation.mutateAsync({ record, field, value });
        message.success('已保存');
      } catch {
        // 错误提示由 useApiMutation 统一处理
      }
    },
    [saveCellMutation],
  );

  const columns: ColumnsType<ClassItem> = useMemo(
    () => [
      {
        title: '班级名称',
        dataIndex: 'name',
        width: 120,
        sorter: (a, b) => a.name.localeCompare(b.name),
        render: (v: string, r: ClassItem) => (
          <EditableCell
            value={v}
            required
            permission="class:edit"
            disabled={r.isArchived}
            onSave={(next) => saveCell(r, 'name', next)}
          >
            {v}
          </EditableCell>
        ),
      },

      {
        title: '编码',
        dataIndex: 'code',
        width: 140,
        render: (v: string, r: ClassItem) => (
          <EditableCell
            value={v}
            required
            permission="class:edit"
            disabled={r.isArchived}
            onSave={(next) => saveCell(r, 'code', next)}
          >
            {v}
          </EditableCell>
        ),
      },

      {
        title: '班型',
        dataIndex: 'classType',
        width: 100,
        render: (v: string, r: ClassItem) => (
          <EditableCell
            value={v}
            editor="select"
            options={Object.entries(TYPE_MAP).map(([value, label]) => ({ value, label }))}
            permission="class:edit"
            disabled={r.isArchived}
            onSave={(next) => saveCell(r, 'classType', next)}
          >
            <Tag>{TYPE_MAP[v] || v}</Tag>
          </EditableCell>
        ),
      },

      {
        title: '开班日期',
        dataIndex: 'startDate',
        width: 110,
        render: (v: string | null, r: ClassItem) => (
          <EditableCell
            value={v}
            editor="date"
            permission="class:edit"
            disabled={r.isArchived}
            onSave={(next) => saveCell(r, 'startDate', next)}
          >
            {v || '-'}
          </EditableCell>
        ),
      },

      {
        title: '学员',
        width: 100,
        render: (_: unknown, r: ClassItem) => (
          <EditableCell
            value={r.maxStudents}
            editor="number"
            min={0}
            permission="class:edit"
            disabled={r.isArchived}
            onSave={(next) => saveCell(r, 'maxStudents', next)}
          >{`${r.studentCount || 0}/${r.maxStudents || '-'}`}</EditableCell>
        ),
      },

      {
        title: '状态',
        dataIndex: 'status',
        width: 100,
        render: (v: string, r: ClassItem) => (
          <EditableCell
            value={v}
            editor="select"
            options={Object.entries(STATUS_MAP).map(([value, item]) => ({
              value,
              label: item.text,
            }))}
            permission="class:edit"
            disabled={r.isArchived}
            onSave={(next) => saveCell(r, 'status', next)}
          >
            {(() => {
              const cfg = STATUS_MAP[v] || { color: 'default', text: v };
              return <Tag color={cfg.color}>{cfg.text}</Tag>;
            })()}
          </EditableCell>
        ),
      },

      {
        title: '操作',
        width: 280,
        render: (_: unknown, r: ClassItem) => (
          <Space>
            <Button
              size="small"
              icon={<TeamOutlined />}
              onClick={() => navigate(`/classes/${r.id}`)}
            >
              详情
            </Button>
            <PermissionButton permission="class:edit" size="small" onClick={() => handleEdit(r)}>
              编辑
            </PermissionButton>
            {r.isArchived ? (
              <>
                <Popconfirm title="确认恢复？" onConfirm={() => handleArchive(r.id, false)}>
                  <PermissionButton permission="class:edit" size="small">
                    恢复
                  </PermissionButton>
                </Popconfirm>
                {canPurgeClass ? (
                  <Button size="small" danger type="link" onClick={() => handlePurge(r)}>
                    删除
                  </Button>
                ) : null}
              </>
            ) : (
              <Popconfirm
                title="归档后可恢复，确认归档？"
                onConfirm={() => handleArchive(r.id, true)}
              >
                <PermissionButton permission="class:edit" size="small">
                  归档
                </PermissionButton>
              </Popconfirm>
            )}
          </Space>
        ),
      },
    ],
    [saveCell, canPurgeClass, handlePurge, navigate, handleEdit, handleArchive],
  );

  return (
    <Card>
      <Space
        style={{ marginBottom: 16 }}
        wrap
        className="responsive-toolbar responsive-toolbar--single"
      >
        <Input
          placeholder="搜索名称/编码"
          prefix={<SearchOutlined />}
          value={searchText}
          onChange={(e) => setSearchText(e.target.value)}
          style={{ width: 200 }}
        />
        <Select
          placeholder="班型"
          allowClear
          style={{ width: 120 }}
          value={filterType}
          onChange={setFilterType}
          options={Object.entries(TYPE_MAP).map(([k, v]) => ({ value: k, label: v }))}
        />
        <Select
          placeholder="状态"
          allowClear
          style={{ width: 120 }}
          value={filterStatus}
          onChange={setFilterStatus}
          options={Object.entries(STATUS_MAP).map(([k, v]) => ({ value: k, label: v.text }))}
        />
        <PermissionButton
          permission="class:create"
          type="primary"
          icon={<PlusOutlined />}
          onClick={handleCreate}
        >
          创建班级
        </PermissionButton>
        <span style={{ marginLeft: 8 }}>
          <InboxOutlined style={{ marginRight: 4 }} />
          归档
          <Switch
            size="small"
            style={{ marginLeft: 4 }}
            checked={showArchived}
            onChange={setShowArchived}
          />
        </span>
      </Space>
      {isError ? (
        <QueryErrorState
          title="班级数据加载失败"
          description="请检查网络后重试。"
          onRetry={() => void refetch()}
        />
      ) : (
        <Table<ClassItem>
          columns={columns}
          dataSource={filtered}
          rowKey="id"
          loading={loading}
          locale={{ emptyText: <Empty description="暂无数据" /> }}
          pagination={{
            defaultPageSize: 20,
            showSizeChanger: true,
            pageSizeOptions: [20, 50, 100],
          }}
          scroll={{ x: 1100 }}
        />
      )}

      <Modal
        title={editing ? '编辑班级' : '创建班级'}
        open={modalOpen}
        onOk={handleSubmit}
        onCancel={() => classFormGuard.confirmClose(() => setModalOpen(false))}
        confirmLoading={saving}
        width={600}
      >
        <Form form={form} layout="vertical">
          <Form.Item name="name" label="班级名称" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
          <Form.Item name="code" label="班级编码" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
          <Form.Item name="classType" label="班型" rules={[{ required: true }]}>
            <Select options={Object.entries(TYPE_MAP).map(([k, v]) => ({ value: k, label: v }))} />
          </Form.Item>
          <Space>
            <Form.Item name="startDate" label="开班日期">
              <DatePicker />
            </Form.Item>
            <Form.Item name="endDate" label="结课日期">
              <DatePicker />
            </Form.Item>
            <Form.Item name="maxStudents" label="人数上限">
              <InputNumber min={1} />
            </Form.Item>
          </Space>
          <Form.Item name="status" label="状态" initialValue="enrolling">
            <Select
              options={Object.entries(STATUS_MAP).map(([k, v]) => ({ value: k, label: v.text }))}
            />
          </Form.Item>
          <Form.Item name="notes" label="备注">
            <Input.TextArea rows={3} />
          </Form.Item>
        </Form>
      </Modal>
    </Card>
  );
};

export default ClassesPage;
