"use client"

import { ProjectDetail } from "@/components/label/api/project/typing"
import { getTaskList, taskRelease } from "@/components/label/api/task"
import { Task } from "@/components/label/api/task/typing"
import {
  useBackUrlStore,
  usePermissionStore,
} from "@/components/label/store/auth"
import {
  TaskStatusEnum,
  TaskStatusOpts,
} from "@/components/label/utils/constants"
import {
  SettingContentPanel,
  SettingDataTable,
  SettingFilterActions,
  SettingFilterPanel,
  SettingHeaderActions,
  SettingListHeader,
} from "@/components/setting/PageSurface"
import {
  Button,
  Collapse,
  Flex,
  Group,
  Modal,
  MultiSelect,
  Select,
  SimpleGrid,
  Stack,
  Text,
  TextInput,
} from "@mantine/core"
import { DatePickerInput, type DatesRangeValue } from "@mantine/dates"
import { modals } from "@mantine/modals"
import { notifications } from "@mantine/notifications"
import {
  IconChevronDown,
  IconChevronUp,
  IconRefresh,
  IconSearch,
} from "@tabler/icons-react"
import dayjs from "dayjs"
import "dayjs/locale/zh-cn"
import duration from "dayjs/plugin/duration"
import { DataTableColumn, type DataTableSortStatus } from "mantine-datatable"
import { useRouter, useSearchParams } from "next/navigation"
import { useCallback, useEffect, useMemo, useState } from "react"
import * as XLSX from "xlsx-js-style"
import DispatchModal from "./components/DispatchModal"
import ReleaseModal from "./components/ReleaseModal"
import TaskStatusTag from "./components/TaskStatusTag"
import WorkflowModal from "./components/WorkflowModal"
dayjs.extend(duration)

interface FilterFormRecord {
  search_id: string
  search_status: string
  rejected: string
  current_uid: string[]
  label_user: string[]
  review_user1: string[]
  review_user2: string[]
  first_commit_label_time: DatesRangeValue
  first_commit_review1_time: DatesRangeValue
}

function createInitialFilters(): FilterFormRecord {
  return {
    search_id: "",
    search_status: "0",
    rejected: "",
    current_uid: [],
    label_user: [],
    review_user1: [],
    review_user2: [],
    first_commit_label_time: [null, null],
    first_commit_review1_time: [null, null],
  }
}

const DEFAULT_RECORDS_PER_PAGE_OPTIONS = [10, 15, 20]
const INITIAL_SORT_ACCESSOR = "__initial__"

type SortableTaskSizeAccessor = keyof Task.SizeProps

const SORTABLE_TASK_SIZE_COLUMNS: Array<{
  accessor: SortableTaskSizeAccessor
  title: string
  width: number
}> = [
  { accessor: "object_size", title: "对象总数", width: 110 },
  { accessor: "valid_size", title: "有效对象数", width: 120 },
  { accessor: "new_size", title: "新增对象数", width: 120 },
  { accessor: "key_frame_size", title: "关键帧数", width: 120 },
  { accessor: "dynamic_size", title: "动态对象数", width: 120 },
  { accessor: "static_size", title: "静态对象数", width: 120 },
  { accessor: "prelabel_size", title: "预标注对象数", width: 120 },
  { accessor: "prelabel_modify_size", title: "预标注对象修改数", width: 160 },
  { accessor: "question_size", title: "问题数", width: 120 },
  { accessor: "total_qa_group_size", title: "总问答组数", width: 120 },
  { accessor: "single_qa_group_size", title: "单轮问答组数", width: 120 },
  { accessor: "multiple_qa_group_size", title: "多轮问答组数", width: 120 },
  { accessor: "new_qa_group_size", title: "新增问答组数", width: 120 },
  {
    accessor: "new_single_qa_group_size",
    title: "新增单轮问答组数",
    width: 160,
  },
  {
    accessor: "new_multiple_qa_group_size",
    title: "新增多轮问答组数",
    width: 160,
  },
  { accessor: "review_question_size", title: "审核问题数", width: 120 },
  { accessor: "comment_question_size", title: "首次批注问题数", width: 140 },
  { accessor: "review_size", title: "审核对象数", width: 120 },
  { accessor: "review_dynamic_size", title: "审核动态对象数", width: 140 },
  { accessor: "review_static_size", title: "审核静态对象数", width: 140 },
  { accessor: "first_comment_size", title: "批注数(1)", width: 120 },
  { accessor: "second_comment_size", title: "批注数(2)", width: 120 },
]

const EMPTY_TASK_SIZE: Task.SizeProps = Object.freeze({
  object_size: 0,
  valid_size: 0,
  first_comment_size: 0,
  second_comment_size: 0,
  new_size: 0,
  prelabel_size: 0,
  prelabel_modify_size: 0,
  dynamic_size: 0,
  static_size: 0,
  review_size: 0,
  review_dynamic_size: 0,
  review_static_size: 0,
  key_frame_size: 0,
  question_size: 0,
  total_qa_group_size: 0,
  single_qa_group_size: 0,
  multiple_qa_group_size: 0,
  new_qa_group_size: 0,
  new_single_qa_group_size: 0,
  new_multiple_qa_group_size: 0,
  review_question_size: 0,
  comment_question_size: 0,
})

export interface selectedDataProps {
  status: number
  uid: number | null
  reject: boolean
}

const checkSelectedData: (
  keys: React.Key[],
  records: Task.DataProps[]
) => {
  flag: boolean
  resultData: selectedDataProps
} = (keys: React.Key[], records: Task.DataProps[]) => {
  const checkData = records.filter((item: any) => keys.includes(item.id))
  const initStatus = checkData[0].label_status
  const initReject = checkData[0].rejected
  const initCurrentUid = checkData[0].current_uid || null
  const initCurrentName = checkData[0].current_username || ""
  if (checkData.length === 1)
    return {
      flag: true,
      resultData: {
        uid: initCurrentUid,
        status: initStatus,
        reject: initReject,
      },
    }
  let statusFlag = true
  let currentFlag = true
  let rejectFlag = true
  checkData.forEach((item: any) => {
    const s = item.label_status
    const c = item.current_username || ""
    const r = item.rejected
    if (s !== initStatus) statusFlag = false
    if (c !== initCurrentName) currentFlag = false
    if (r !== initReject) rejectFlag = false
  })
  return {
    flag: statusFlag && currentFlag && rejectFlag,
    resultData: {
      uid: initCurrentUid,
      status: initStatus,
      reject: initReject,
    },
  }
}

export default function TaskTableContainer(props: {
  info: ProjectDetail.DataProps | undefined
  userEnums: {
    allEnum: Map<any, any>
    labelEnum: Map<any, any>
    review1Enum: Map<any, any>
    review2Enum: Map<any, any>
  }
}) {
  const { info, userEnums } = props

  const { user_id, detailInfo } = usePermissionStore()
  const hasRolePermissions = Boolean(detailInfo?.roles?.length)

  const urlParams = useSearchParams()
  const id = urlParams.get("id")
  const type = urlParams.get("type")

  const projectId =
    typeof id === "string" && !isNaN(Number(id)) ? Number(id) : -1

  const router = useRouter()
  const { setBackProps } = useBackUrlStore()

  const [total, setTotal] = useState(0)
  const [totalSize, setTotalSize] = useState<Task.SizeProps>(EMPTY_TASK_SIZE)

  const [pageNumber, setPageNumber] = useState(1)
  const [pageSize, setPageSize] = useState(15)
  const [recordsPerPageOptions, setRecordsPerPageOptions] = useState<number[]>(
    () => [...DEFAULT_RECORDS_PER_PAGE_OPTIONS]
  )
  const [customPageSizeInput, setCustomPageSizeInput] = useState("")
  const [customPageSizeModalOpened, setCustomPageSizeModalOpened] =
    useState(false)

  const [searchExpanded, setSearchExpanded] = useState(false)

  const [filters, setFilters] = useState(() => createInitialFilters())
  const [form, setForm] = useState<FilterFormRecord>(createInitialFilters())

  const [records, setRecords] = useState<Task.DataProps[]>([])
  const [selectedRecords, setSelectedRecords] = useState<Task.DataProps[]>([])
  const [loading, setLoading] = useState(false)
  const [queryTrigger, setQueryTrigger] = useState(0)
  const [sortStatus, setSortStatus] = useState<
    DataTableSortStatus<Task.DataProps>
  >({
    columnAccessor: INITIAL_SORT_ACCESSOR,
    direction: "asc",
  })

  const [workflowTaskId, setWorkflowTaskId] = useState<number | null>(null)
  const [dispatchRecordModal, setDispatchModalConfig] = useState<{
    open: boolean
    dispatchData?: selectedDataProps
    task_ids: Task.DataProps[]
  }>({
    open: false,
    task_ids: [],
  })
  const [releaseRecord, setReleaseRecord] = useState<Task.DataProps | null>(
    null
  )

  const userOptions = useMemo(() => {
    const arr: Array<{ label: string; value: string }> = []
    userEnums.allEnum?.forEach((label, value) => {
      arr.push({ label: String(label), value: String(value) })
    })
    return arr
  }, [userEnums.allEnum])

  const appliedParams = useMemo(() => {
    const obj: Task.ListRequest = {
      page_number: pageNumber ?? 1,
      page_size: pageSize ?? 20,
      project_id: projectId !== -1 ? [projectId] : undefined,
      get_data: false,
    }
    if (form.search_id) {
      const idValue = Number(form.search_id)
      if (Number.isFinite(idValue)) obj.id = [idValue]
    }
    if (form.search_status !== "0") {
      const statusValue = Number(form.search_status)
      if (Number.isFinite(statusValue)) obj.label_status = [statusValue]
    } else {
      delete obj.label_status
    }
    if (form.rejected !== "") {
      const rejected = Number(form.rejected)
      if (Number.isFinite(rejected))
        obj.rejected = rejected === 1 ? true : false
    }
    if (form.current_uid?.length) {
      obj.current_uid = form.current_uid?.map((item) => Number(item))
    }
    if (form.label_user?.length) {
      obj.label_user = form.label_user?.map((item) => Number(item))
    }
    if (form.review_user1?.length) {
      obj.review_user1 = form.review_user1?.map((item) => Number(item))
    }
    if (form.review_user2?.length) {
      obj.review_user2 = form.review_user2?.map((item) => Number(item))
    }
    if (form.first_commit_label_time[0] && form.first_commit_label_time[1]) {
      obj.first_commit_label_time_start = dayjs(
        form.first_commit_label_time[0]
      ).format("YYYY-MM-DD")
      obj.first_commit_label_time_end = dayjs(
        form.first_commit_label_time[1]
      ).format("YYYY-MM-DD")
    }
    if (
      form.first_commit_review1_time[0] &&
      form.first_commit_review1_time[1]
    ) {
      obj.first_commit_review1_time_start = dayjs(
        form.first_commit_review1_time[0]
      ).format("YYYY-MM-DD")
      obj.first_commit_review1_time_end = dayjs(
        form.first_commit_review1_time[1]
      ).format("YYYY-MM-DD")
    }
    if (sortStatus.columnAccessor !== INITIAL_SORT_ACCESSOR) {
      obj.order_by = `${sortStatus.columnAccessor} ${sortStatus.direction}`
    }
    return obj
  }, [
    form.current_uid,
    form.first_commit_label_time,
    form.first_commit_review1_time,
    form.label_user,
    form.rejected,
    form.review_user1,
    form.review_user2,
    form.search_id,
    form.search_status,
    pageNumber,
    pageSize,
    projectId,
    sortStatus.columnAccessor,
    sortStatus.direction,
  ])

  const load = useCallback(async () => {
    if (!queryTrigger) return
    if (projectId === -1) return
    setLoading(true)
    try {
      const res = await getTaskList(appliedParams)
      setRecords(res?.task_list ?? [])
      setTotal(res?.total_items ?? 0)
      setTotalSize(res?.total_size ?? EMPTY_TASK_SIZE)
    } catch (e) {
      setRecords([])
      setTotal(0)
      setTotalSize(EMPTY_TASK_SIZE)
      notifications.show({
        color: "red",
        title: "加载失败",
        message: e instanceof Error ? e.message : "请求失败",
      })
    } finally {
      setLoading(false)
    }
  }, [appliedParams, projectId, queryTrigger, setTotal])

  useEffect(() => {
    load()
  }, [load])

  useEffect(() => {
    queueMicrotask(() => {
      setQueryTrigger((v) => v + 1)
    })
  }, [])

  const openCustomPageSizeModal = useCallback(() => {
    setCustomPageSizeModalOpened(true)
  }, [])

  const closeCustomPageSizeModal = useCallback(() => {
    setCustomPageSizeModalOpened(false)
    setCustomPageSizeInput("")
  }, [])

  const handleAddCustomPageSize = useCallback(() => {
    const rawValue = customPageSizeInput.trim()
    if (!rawValue) return
    const size = Number(rawValue)
    if (!Number.isInteger(size) || size <= 0) {
      notifications.show({
        color: "red",
        title: "输入无效",
        message: "请填写大于 0 的整数条数",
      })
      return
    }
    if (recordsPerPageOptions.includes(size)) {
      notifications.show({
        color: "blue",
        title: "已存在",
        message: `每页 ${size} 条已在可选项中`,
      })
      return
    }
    setRecordsPerPageOptions((prev) => [...prev, size].sort((a, b) => a - b))
    closeCustomPageSizeModal()
    notifications.show({
      color: "green",
      title: "添加成功",
      message: `已新增每页 ${size} 条`,
    })
  }, [closeCustomPageSizeModal, customPageSizeInput, recordsPerPageOptions])

  const handleCustomPageSizeEnter = useCallback(
    (event: React.KeyboardEvent<HTMLInputElement>) => {
      if (event.key !== "Enter") return
      event.preventDefault()
      handleAddCustomPageSize()
    },
    [handleAddCustomPageSize]
  )

  const clickDispatchTask = () => {
    if (!selectedRecords.length) {
      notifications.show({
        color: "yellow",
        title: "警告",
        message: "请先选择任务",
      })
      return
    }
    const { flag, resultData } = checkSelectedData(
      selectedRecords.map((item) => item.id),
      records
    )
    if (!flag) {
      notifications.show({
        color: "yellow",
        title: "警告",
        message: "请保证选取任务的标注状态及负责人一致",
      })
      return
    }
    setDispatchModalConfig({
      open: true,
      dispatchData: resultData,
      task_ids: selectedRecords,
    })
  }

  const clickReleaseTask = () => {
    if (!selectedRecords.length) {
      notifications.show({
        color: "yellow",
        title: "警告",
        message: "请先选择任务",
      })
      return
    }
    const { flag, resultData } = checkSelectedData(
      selectedRecords.map((item) => item.id),
      records
    )
    if (!flag) {
      notifications.show({
        color: "yellow",
        title: "警告",
        message: "请保证选取任务的标注状态及负责人一致",
      })
      return
    }
    if (![2, 4, 6, 7].includes(resultData.status)) {
      notifications.show({
        color: "red",
        title: "错误",
        message: "所选任务状态无法释放",
      })
      return
    }
    modals.openConfirmModal({
      title: "释放任务",
      centered: true,
      children: <Text size="sm">是否释放所选所有任务？</Text>,
      labels: { confirm: "释放", cancel: "取消" },
      confirmProps: { color: "red" },
      onConfirm: async () => {
        const reqParams = {
          operation_uid: user_id,
          task_ids: selectedRecords.map((item) => item.id),
          uid: resultData.uid || 0,
          reject: resultData.reject,
          task_status: resultData.status,
        }
        try {
          await taskRelease(reqParams)
          notifications.show({
            color: "green",
            title: "操作成功",
            message: "已释放所选所有任务",
          })
          load()
        } catch {}
      },
    })
  }

  const handleExport = async () => {
    try {
      notifications.show({
        color: "yellow",
        title: "提示",
        message: "导出统计数据中...",
      })
      const res = await getTaskList({
        id: selectedRecords.map((item) => item.id),
        page_number: 1,
        page_size: selectedRecords.length,
        get_data: false,
      })
      const { task_list } = res
      const exportTableHeader = [
        "任务ID",
        "状态",
        "当前负责人",
        "标注员",
        "审核员",
        "复审员",
        "对象总数",
        "有效对象数",
        "新增对象数",
        "关键帧数",
        "动态对象数",
        "静态对象数",
        "预标注对象数",
        "预标注对象修改数",
        "问题数",
        "总问答组数",
        "单轮问答组数",
        "多轮问答组数",
        "新增问答组数",
        "新增单轮问答组数",
        "新增多轮问答组数",
        "审核问题数",
        "首次批注问题数",
        "审核对象数",
        "审核动态对象数",
        "审核静态对象数",
        "批注数(1)",
        "批注数(2)",
        "标注首次提交时间",
        "审核首次提交时间",
        "驳回次数",
        "标注总耗时",
        "审核总耗时",
        "复审总耗时",
        "标注首次耗时",
        "审核首次耗时",
        "复审首次耗时",
        "审核首次驳回时间",
      ]
      let data = task_list.map((item) => {
        return [
          item.id,
          `${TaskStatusEnum.get(item.label_status)}${
            item.rejected ? "返工" : ""
          }`,
          item.current_username,
          item.label_username,
          item.review1_username,
          item.review2_username,
          item.label_object_size.object_size,
          item.label_object_size.valid_size,
          item.label_object_size.new_size,
          item.label_object_size.key_frame_size,
          item.label_object_size.dynamic_size,
          item.label_object_size.static_size,
          item.label_object_size.prelabel_size,
          item.label_object_size.prelabel_modify_size,
          item.label_object_size.question_size,
          item.label_object_size.total_qa_group_size,
          item.label_object_size.single_qa_group_size,
          item.label_object_size.multiple_qa_group_size,
          item.label_object_size.new_qa_group_size,
          item.label_object_size.new_single_qa_group_size,
          item.label_object_size.new_multiple_qa_group_size,
          item.label_object_size.review_question_size,
          item.label_object_size.comment_question_size,
          item.label_object_size.review_size,
          item.label_object_size.review_dynamic_size,
          item.label_object_size.review_static_size,
          item.label_object_size.first_comment_size,
          item.label_object_size.second_comment_size,
          item.first_commit_label_time,
          item.first_commit_review1_time,
          item.reject_times,
          item.work_time.label_work_time,
          item.work_time.first_review_work_time,
          item.work_time.second_review_work_time,
          item.label_first_work_time,
          item.review1_first_work_time,
          item.review2_first_work_time,
          item.first_reject_label_time,
        ]
      })
      const exportData = [exportTableHeader, ...data]
      const wb = XLSX.utils.book_new()
      const ws = XLSX.utils.aoa_to_sheet(exportData)
      XLSX.utils.book_append_sheet(wb, ws, "任务列表数据")
      XLSX.writeFile(wb, `任务列表数据.xlsx`)
    } catch {}
  }

  const handleSearch = () => {
    setPageNumber(1)
    setForm({ ...filters })
    setQueryTrigger((v) => v + 1)
  }

  const handleReset = () => {
    const next = createInitialFilters()
    setFilters(next)
    setForm(next)
    setPageNumber(1)
    setQueryTrigger((v) => v + 1)
  }

  const handleRefresh = () => {
    setQueryTrigger((v) => v + 1)
  }

  const getTime = (time: number) => {
    return dayjs.duration(time, "seconds").format("HH:mm:ss")
  }

  const columns = useMemo(() => {
    const createSortableSizeColumn = ({
      accessor,
      title,
      width,
    }: {
      accessor: SortableTaskSizeAccessor
      title: string
      width: number
    }): DataTableColumn<Task.DataProps> => ({
      accessor,
      title,
      width,
      sortable: true,
      render: (record) => record.label_object_size?.[accessor] ?? "-",
      footer: totalSize[accessor] ?? 0,
    })

    const cols: DataTableColumn<Task.DataProps>[] = [
      {
        accessor: "id",
        title: "任务ID",
        width: 90,
        footer: "总计",
        render: (record) => (
          <Button
            variant="transparent"
            size="xs"
            style={{ paddingLeft: 6, paddingRight: 6 }}
            onClick={async () => {
              const backUrl = type
                ? `/project/detail?id=${projectId}&type=${type}`
                : `/project/detail?id=${projectId}`
              setBackProps(backUrl, "all", "/image")

              if (info && [4, 5, 6, 7].includes(info.label_type)) {
                router.push(
                  `/label?project_id=${projectId}&task_id=${record.id}`
                )
              } else {
                // await runCommand(
                //   String(record.id),
                //   user_name ?? "",
                //   user_password ?? ""
                // )
              }
            }}>
            {record.id}
          </Button>
        ),
      },
      {
        accessor: "label_status",
        title: "状态",
        width: 150,
        render: (record) => (
          <TaskStatusTag
            status={record.label_status}
            rejected={record.rejected}
          />
        ),
      },
      {
        accessor: "current_username",
        title: "当前负责人",
        width: 120,
        render: (record) => record.current_username ?? "-",
      },
      {
        accessor: "label_username",
        title: "标注员",
        width: 120,
        render: (record) => record.label_username ?? "-",
      },
      {
        accessor: "review1_username",
        title: "审核员",
        width: 120,
        render: (record) => record.review1_username ?? "-",
      },
      {
        accessor: "review2_username",
        title: "复审员",
        width: 120,
        render: (record) => record.review2_username ?? "-",
      },
      ...SORTABLE_TASK_SIZE_COLUMNS.map(createSortableSizeColumn),
      {
        accessor: "first_commit_label_time",
        title: "标注首次提交时间",
        width: 180,
        render: (record) => record.first_commit_label_time ?? "-",
      },
      {
        accessor: "first_commit_review1_time",
        title: "审核首次提交时间",
        width: 180,
        render: (record) => record.first_commit_review1_time ?? "-",
      },
      {
        accessor: "reject_times",
        title: "驳回次数",
        width: 120,
        render: (record) => record.reject_times ?? "-",
      },
      {
        accessor: "work_time.label_work_time",
        title: "标注总耗时",
        width: 120,
        render: (record) =>
          record.work_time?.label_work_time
            ? getTime(record.work_time?.label_work_time)
            : "-",
      },
      {
        accessor: "work_time.first_review_work_time",
        title: "审核总耗时",
        width: 120,
        render: (record) =>
          record.work_time?.first_review_work_time
            ? getTime(record.work_time?.first_review_work_time)
            : "-",
      },
      {
        accessor: "work_time.second_review_work_time",
        title: "复审总耗时",
        width: 120,
        render: (record) =>
          record.work_time?.second_review_work_time
            ? getTime(record.work_time?.second_review_work_time)
            : "-",
      },
      {
        accessor: "label_first_work_time",
        title: "标注首次耗时",
        width: 120,
        render: (record) =>
          record.label_first_work_time
            ? getTime(record.label_first_work_time)
            : "-",
      },
      {
        accessor: "review1_first_work_time",
        title: "审核首次耗时",
        width: 120,
        render: (record) =>
          record.review1_first_work_time
            ? getTime(record.review1_first_work_time)
            : "-",
      },
      {
        accessor: "review2_first_work_time",
        title: "复审首次耗时",
        width: 120,
        render: (record) =>
          record.review2_first_work_time
            ? getTime(record.review2_first_work_time)
            : "-",
      },
      {
        accessor: "first_reject_label_time",
        title: "审核首次驳回时间",
        width: 180,
        render: (record) => record.first_reject_label_time ?? "-",
      },
      {
        accessor: "operation",
        title: "操作",
        width: 140,
        textAlign: "center",
        render: (record) => (
          <Flex gap={6} justify="space-around" wrap="nowrap">
            {hasRolePermissions ? (
              <Button
                px={0}
                variant="transparent"
                onClick={() => {
                  setDispatchModalConfig({
                    open: true,
                    dispatchData: {
                      status: record.label_status,
                      uid: record.current_uid || null,
                      reject: record.rejected,
                    },
                    task_ids: [record],
                  })
                }}>
                调度
              </Button>
            ) : null}
            <Button
              px={0}
              variant="transparent"
              onClick={() => setWorkflowTaskId(record.id)}>
              流转记录
            </Button>
          </Flex>
        ),
      },
    ]
    return cols
  }, [
    hasRolePermissions,
    info,
    projectId,
    router,
    setBackProps,
    totalSize,
    type,
  ])

  return (
    <>
      <Stack gap="sm" style={{ flex: 1, minHeight: 0 }}>
        <SettingFilterPanel>
          <Group justify="space-between" wrap="wrap" gap="sm">
            <Group gap="xs">
              <Text fw={700}>筛选条件</Text>
              <Button
                variant="transparent"
                rightSection={
                  searchExpanded ? (
                    <IconChevronUp size={16} />
                  ) : (
                    <IconChevronDown size={16} />
                  )
                }
                onClick={() => setSearchExpanded((v) => !v)}>
                {searchExpanded ? "收起筛选" : "展开筛选"}
              </Button>
            </Group>
          </Group>
          <Collapse
            in={searchExpanded}
            transitionDuration={250}
            transitionTimingFunction="ease"
            animateOpacity>
            <Stack gap="md" mt="md">
              <SimpleGrid
                cols={{ base: 1, sm: 2, md: 3, lg: 4 }}
                spacing="md"
                verticalSpacing="md">
                <TextInput
                  label="任务ID"
                  placeholder="请输入任务 ID"
                  value={filters.search_id}
                  onChange={(e) =>
                    setFilters((s) => ({
                      ...s,
                      search_id: e.target.value,
                    }))
                  }
                />
                <Select
                  label="任务状态"
                  data={Object.entries(TaskStatusOpts).map(
                    ([value, label]) => ({
                      value,
                      label,
                    })
                  )}
                  value={filters.search_status}
                  onChange={(v) =>
                    setFilters((s) => ({ ...s, search_status: v ?? "0" }))
                  }
                  allowDeselect={false}
                />
                <Select
                  label="是否返工"
                  data={[
                    { label: "全部", value: "" },
                    { label: "是", value: "1" },
                    { label: "否", value: "0" },
                  ]}
                  value={filters.rejected}
                  onChange={(v) =>
                    setFilters((s) => ({ ...s, rejected: v ?? "" }))
                  }
                  allowDeselect={false}
                />
                <MultiSelect
                  label="当前负责人"
                  data={Array.from(userEnums.allEnum.entries()).map(
                    ([x, y]) => ({ label: y, value: x.toString() })
                  )}
                  searchable
                  clearable
                  value={filters.current_uid}
                  onChange={(v) =>
                    setFilters((s) => ({ ...s, current_uid: v }))
                  }
                />
                <MultiSelect
                  label="标注员"
                  data={Array.from(userEnums.labelEnum.entries()).map(
                    ([x, y]) => ({ label: y, value: x.toString() })
                  )}
                  searchable
                  clearable
                  value={filters.label_user}
                  onChange={(v) => setFilters((s) => ({ ...s, label_user: v }))}
                />
                <MultiSelect
                  label="审核员"
                  data={Array.from(userEnums.review1Enum.entries()).map(
                    ([x, y]) => ({ label: y, value: x.toString() })
                  )}
                  searchable
                  clearable
                  value={filters.review_user1}
                  onChange={(v) =>
                    setFilters((s) => ({ ...s, review_user1: v }))
                  }
                />
                <MultiSelect
                  label="复审员"
                  data={Array.from(userEnums.review2Enum.entries()).map(
                    ([x, y]) => ({ label: y, value: x.toString() })
                  )}
                  searchable
                  clearable
                  value={filters.review_user2}
                  onChange={(v) =>
                    setFilters((s) => ({ ...s, review_user2: v }))
                  }
                />
                <DatePickerInput
                  type="range"
                  label="标注首次提交时间"
                  placeholder="请选择时间范围"
                  valueFormat="YYYY-MM-DD"
                  locale="zh-cn"
                  clearable
                  value={filters.first_commit_label_time}
                  onChange={(value: DatesRangeValue) =>
                    setFilters((s) => ({
                      ...s,
                      first_commit_label_time: value,
                    }))
                  }
                />
                <DatePickerInput
                  type="range"
                  label="审核首次提交时间"
                  placeholder="请选择时间范围"
                  valueFormat="YYYY-MM-DD"
                  locale="zh-cn"
                  clearable
                  value={filters.first_commit_review1_time}
                  onChange={(value: DatesRangeValue) =>
                    setFilters((s) => ({
                      ...s,
                      first_commit_review1_time: value,
                    }))
                  }
                />
              </SimpleGrid>
            </Stack>
          </Collapse>
          <SettingFilterActions>
            <Button
              variant="default"
              leftSection={<IconRefresh size={16} />}
              onClick={handleReset}>
              重置
            </Button>
            <Button
              leftSection={<IconSearch size={16} />}
              onClick={handleSearch}
              loading={loading}>
              查询
            </Button>
          </SettingFilterActions>
        </SettingFilterPanel>
        <SettingContentPanel
          style={{
            flex: 1,
            minHeight: 0,
            display: "flex",
            flexDirection: "column",
          }}>
          <Stack gap="sm" align="stretch" style={{ flex: 1, minHeight: 0 }}>
            <SettingListHeader
              title="任务列表"
              count={
                selectedRecords.length
                  ? `${total} 条 / 已选 ${selectedRecords.length}`
                  : `${total} 条`
              }
              actions={
                <SettingHeaderActions>
                  {hasRolePermissions ? (
                    <Button
                      variant="default"
                      leftSection={<IconRefresh size={16} />}
                      onClick={handleRefresh}
                      loading={loading}>
                      刷新
                    </Button>
                  ) : null}
                  <Button
                    variant="default"
                    disabled={!selectedRecords.length}
                    onClick={handleExport}>
                    下载选中项
                  </Button>
                  {hasRolePermissions ? (
                    <Button
                      variant="default"
                      disabled={!selectedRecords.length}
                      onClick={clickDispatchTask}>
                      调度选中项
                    </Button>
                  ) : null}
                  {hasRolePermissions ? (
                    <Button
                      variant="default"
                      disabled={!selectedRecords.length}
                      onClick={clickReleaseTask}>
                      释放选中项
                    </Button>
                  ) : null}
                </SettingHeaderActions>
              }
            />
            <SettingDataTable<Task.DataProps>
              width="100%"
              minHeight={0}
              style={{ width: "100%", flex: 1 }}
              pinFirstColumn
              pinLastColumn
              scrollAreaProps={{ type: "auto" }}
              fetching={loading}
              records={records}
              columns={columns}
              sortStatus={sortStatus}
              onSortStatusChange={(
                nextSortStatus: DataTableSortStatus<Task.DataProps>
              ) => {
                setPageNumber(1)
                setSortStatus(nextSortStatus)
              }}
              totalRecords={total}
              recordsPerPage={pageSize}
              page={pageNumber}
              onPageChange={(p) => setPageNumber(p)}
              onRecordsPerPageChange={(s) => {
                setPageSize(s)
                setPageNumber(1)
              }}
              selectedRecords={selectedRecords}
              onSelectedRecordsChange={setSelectedRecords}
              recordsPerPageOptions={recordsPerPageOptions}
              renderPagination={({ Controls }) => (
                <Group
                  justify="space-between"
                  align="center"
                  w="100%"
                  gap="sm"
                  wrap="wrap">
                  <Group gap="xs" align="center" wrap="wrap">
                    <Controls.Text />
                    <Controls.PageSizeSelector />
                    <Button
                      variant="light"
                      color="gray"
                      size="xs"
                      onClick={openCustomPageSizeModal}>
                      自定义每页条数
                    </Button>
                  </Group>
                  <Controls.Pagination />
                </Group>
              )}
            />
          </Stack>
        </SettingContentPanel>
      </Stack>

      <Modal
        opened={customPageSizeModalOpened}
        onClose={closeCustomPageSizeModal}
        title="添加每页条数"
        centered>
        <Stack gap="sm">
          <TextInput
            data-autofocus
            label="每页条数"
            placeholder="请输入大于 0 的整数，例如 99"
            value={customPageSizeInput}
            onChange={(event) =>
              setCustomPageSizeInput(event.currentTarget.value)
            }
            onKeyDown={handleCustomPageSizeEnter}
          />
          <Group justify="flex-end">
            <Button variant="default" onClick={closeCustomPageSizeModal}>
              取消
            </Button>
            <Button onClick={handleAddCustomPageSize}>添加</Button>
          </Group>
        </Stack>
      </Modal>

      <WorkflowModal
        opened={workflowTaskId !== null}
        taskId={workflowTaskId}
        onCloseAction={() => setWorkflowTaskId(null)}
      />
      <DispatchModal
        opened={dispatchRecordModal.open}
        dispatchData={dispatchRecordModal.dispatchData}
        task_ids={dispatchRecordModal.task_ids}
        userOptions={userOptions}
        onCloseAction={(refresh) => {
          setDispatchModalConfig({
            open: false,
            task_ids: [],
          })
          if (refresh) setQueryTrigger((v) => v + 1)
        }}
      />
      <ReleaseModal
        opened={releaseRecord !== null}
        record={releaseRecord}
        onCloseAction={(refresh) => {
          setReleaseRecord(null)
          if (refresh) setQueryTrigger((v) => v + 1)
        }}
      />
    </>
  )
}
