"use client"

import { TimeFilter } from "@/components/label/api/workload/typing"
import {
  SettingContentPanel,
  SettingDataTable,
  SettingFilterActions,
  SettingFilterPanel,
  SettingHeaderActions,
  SettingInlineFilterField,
  SettingListHeader,
  settingSurfaceClassNames,
} from "@/components/setting/PageSurface"
import { Button, Collapse, Stack, TextInput } from "@mantine/core"
import { DateInput } from "@mantine/dates"
import { notifications } from "@mantine/notifications"
import {
  IconChevronDown,
  IconChevronUp,
  IconDownload,
  IconRefresh,
  IconSearch,
} from "@tabler/icons-react"
import dayjs from "dayjs"
import "dayjs/locale/zh-cn"
import { DataTableColumn, DataTableSortStatus } from "mantine-datatable"
import { useEffect, useMemo, useState } from "react"
import * as XLSX from "xlsx-js-style"
import { DimensionType, GroupedData, MetricColumn } from "./config"

function emptyGroupedData(): GroupedData {
  return {
    all: [],
    order_by_group_name: [],
    order_by_project_name: [],
    order_by_project_type: [],
    order_by_user_name: [],
  }
}

function createInitialFilters() {
  const currentDate = dayjs().subtract(1, "day").format("YYYY-MM-DD")
  return {
    startDate: currentDate,
    endDate: currentDate,
    dimension: "all" as DimensionType,
    projectName: "",
    projectType: "",
    userName: "",
    groupName: "",
  }
}

export default function WorkloadMetricsTable(props: {
  title: string
  sheetName: string
  fileName: string
  metrics: MetricColumn[]
  fetchData: (params: TimeFilter) => Promise<GroupedData>
}) {
  const { title, sheetName, fileName, metrics, fetchData } = props

  const [filters, setFilters] = useState(() => createInitialFilters())
  const [appliedFilters, setAppliedFilters] = useState(() =>
    createInitialFilters()
  )
  const [data, setData] = useState<GroupedData>(emptyGroupedData())
  const [loading, setLoading] = useState(false)

  const [sortStatus, setSortStatus] = useState<DataTableSortStatus>({
    columnAccessor: "work_time",
    direction: "desc",
  })

  const refresh = async (nextFilters = appliedFilters) => {
    if (!nextFilters.startDate || !nextFilters.endDate) {
      notifications.show({
        color: "yellow",
        title: "参数不完整",
        message: "请选择起止日期",
      })
      return
    }
    try {
      setLoading(true)
      const res = await fetchData({
        start_date: nextFilters.startDate,
        end_date: nextFilters.endDate,
      })
      setData({
        ...emptyGroupedData(),
        ...(res ?? {}),
      })
    } catch (e) {
      notifications.show({
        color: "red",
        title: "加载失败",
        message: e instanceof Error ? e.message : "请求失败",
      })
      setData(emptyGroupedData())
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    const initialFilters = createInitialFilters()
    queueMicrotask(() => refresh(initialFilters))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const filteredRecords = useMemo(() => {
    let records = [...(data[appliedFilters.dimension] ?? [])]
    if (appliedFilters.projectName.trim()) {
      records = records.filter((item) =>
        String(item.project_name ?? "")
          .toLowerCase()
          .includes(appliedFilters.projectName.trim().toLowerCase())
      )
    }
    if (appliedFilters.projectType.trim()) {
      records = records.filter((item) =>
        String(item.project_type ?? "")
          .toLowerCase()
          .includes(appliedFilters.projectType.trim().toLowerCase())
      )
    }
    if (appliedFilters.userName.trim()) {
      records = records.filter((item) =>
        String(item.user_name ?? "")
          .toLowerCase()
          .includes(appliedFilters.userName.trim().toLowerCase())
      )
    }
    if (appliedFilters.groupName.trim()) {
      records = records.filter((item) =>
        String(item.group_name ?? "")
          .toLowerCase()
          .includes(appliedFilters.groupName.trim().toLowerCase())
      )
    }
    return records
  }, [appliedFilters, data])

  const sortedRecords = useMemo(() => {
    const list = [...filteredRecords]
    const accessor = sortStatus.columnAccessor
    const dir = sortStatus.direction === "asc" ? 1 : -1
    list.sort((a, b) => {
      const av = a?.[accessor as string]
      const bv = b?.[accessor as string]
      const an = Number(av)
      const bn = Number(bv)
      if (Number.isFinite(an) && Number.isFinite(bn)) {
        return (an - bn) * dir
      }
      return String(av ?? "").localeCompare(String(bv ?? "")) * dir
    })
    return list
  }, [filteredRecords, sortStatus.columnAccessor, sortStatus.direction])

  const baseColumns = useMemo(() => {
    const allCols: Record<DimensionType, DataTableColumn<any>[]> = {
      all: [
        { accessor: "project_name", title: "项目名称", width: 180 },
        { accessor: "project_type", title: "项目类型", width: 280 },
        { accessor: "user_name", title: "用户名", width: 120 },
        { accessor: "group_name", title: "用户组", width: 160 },
      ],
      order_by_group_name: [
        { accessor: "group_name", title: "用户组", width: 180 },
      ],
      order_by_project_name: [
        { accessor: "project_name", title: "项目名称", width: 220 },
      ],
      order_by_project_type: [
        { accessor: "project_type", title: "项目类型", width: 320 },
      ],
      order_by_user_name: [
        { accessor: "user_name", title: "用户名", width: 180 },
      ],
    }
    return allCols[appliedFilters.dimension]
  }, [appliedFilters.dimension])

  const columns = useMemo(() => {
    const totalsByKey = Object.fromEntries(
      metrics.map((metric) => {
        const sum = sortedRecords.reduce((acc, item) => {
          const value = Number(item?.[metric.key] ?? 0)
          return acc + (Number.isFinite(value) ? value : 0)
        }, 0)
        return [metric.key, sum]
      })
    ) as Record<string, number>

    const metricCols = metrics.map((metric) => {
      return {
        accessor: metric.key,
        title: metric.title,
        width: 140,
        sortable: true,
        footer: totalsByKey[metric.key] ?? 0,
      } as DataTableColumn<any>
    })
    return [
      {
        accessor: "index",
        title: "序号",
        width: 80,
        footer: "总计",
        render: (_record: any, index: number) => index + 1,
      } as DataTableColumn<any>,
      ...baseColumns,
      ...metricCols,
    ]
  }, [baseColumns, metrics, sortedRecords])

  const handleExport = () => {
    if (!sortedRecords.length) {
      notifications.show({
        color: "yellow",
        title: "暂无数据",
        message: "当前筛选条件下无可导出数据",
      })
      return
    }
    const baseHeaders = baseColumns.map((c) => String(c.title ?? c.accessor))
    const metricHeaders = metrics.map((m) => m.title)
    const header = ["序号", ...baseHeaders, ...metricHeaders]

    const baseAccessors = baseColumns.map((c) => String(c.accessor))
    const rows = sortedRecords.map((item, index) => {
      return [
        index + 1,
        ...baseAccessors.map((key) => item?.[key] ?? "-"),
        ...metrics.map((m) => item?.[m.key] ?? 0),
      ]
    })

    const wb = XLSX.utils.book_new()
    const ws = XLSX.utils.aoa_to_sheet([header, ...rows])
    XLSX.utils.book_append_sheet(wb, ws, sheetName)
    XLSX.writeFile(wb, fileName)
  }

  const rowKey = useMemo(() => {
    if (appliedFilters.dimension === "all") {
      return (record: any) =>
        `${record.project_id ?? "p"}_${record.uid ?? "u"}_${record.project_name ?? ""}_${record.user_name ?? ""}`
    }
    if (appliedFilters.dimension === "order_by_group_name") return "group_name"
    if (appliedFilters.dimension === "order_by_project_name")
      return "project_name"
    if (appliedFilters.dimension === "order_by_project_type")
      return "project_type"
    return "user_name"
  }, [appliedFilters.dimension])

  const handleSearch = () => {
    setAppliedFilters(filters)
    void refresh(filters)
  }

  const handleReset = () => {
    const nextFilters = createInitialFilters()
    setFilters(nextFilters)
    setAppliedFilters(nextFilters)
    void refresh(nextFilters)
  }

  const [searchExpanded, setSearchExpanded] = useState(false)

  return (
    <Stack h="100%" gap={12} style={{ minWidth: 0 }}>
      <SettingFilterPanel>
        <Stack gap={12}>
          <div className={settingSurfaceClassNames.filterTopRow}>
            <SettingInlineFilterField label="开始日期">
              <DateInput
                locale="zh-cn"
                value={filters.startDate}
                onChange={(e) =>
                  setFilters((s) => ({
                    ...s,
                    startDate: dayjs(e).format("YYYY-MM-DD"),
                  }))
                }
              />
            </SettingInlineFilterField>
            <SettingInlineFilterField label="结束日期">
              <DateInput
                locale="zh-cn"
                value={filters.endDate}
                onChange={(e) =>
                  setFilters((s) => ({
                    ...s,
                    endDate: dayjs(e).format("YYYY-MM-DD"),
                  }))
                }
              />
            </SettingInlineFilterField>
            <SettingInlineFilterField label="项目名称">
              <TextInput
                placeholder="请输入项目名称"
                value={filters.projectName}
                onChange={(e) =>
                  setFilters((prev) => ({
                    ...prev,
                    projectName: e.target.value,
                  }))
                }
              />
            </SettingInlineFilterField>

            <SettingFilterActions
              mt={0}
              className={settingSurfaceClassNames.filterActions}>
              <Button
                variant="transparent"
                className={settingSurfaceClassNames.collapseToggle}
                rightSection={
                  searchExpanded ? (
                    <IconChevronUp size={16} />
                  ) : (
                    <IconChevronDown size={16} />
                  )
                }
                onClick={() => setSearchExpanded((v) => !v)}>
                {searchExpanded ? "收起" : "展开"}
              </Button>
              <Button
                variant="default"
                leftSection={<IconRefresh size={16} />}
                onClick={handleReset}>
                重置
              </Button>
              <Button
                leftSection={<IconSearch size={16} />}
                onClick={handleSearch}
                loading={loading}>
                查询
              </Button>
            </SettingFilterActions>
          </div>
          <Collapse in={searchExpanded} transitionDuration={150} animateOpacity>
            <div className={settingSurfaceClassNames.filterExpandedGrid}>
              <SettingInlineFilterField label="项目类型">
                <TextInput
                  placeholder="请输入项目类型"
                  value={filters.projectType}
                  onChange={(e) =>
                    setFilters((prev) => ({
                      ...prev,
                      projectType: e.target.value,
                    }))
                  }
                />
              </SettingInlineFilterField>
            </div>
          </Collapse>
        </Stack>
      </SettingFilterPanel>

      <SettingContentPanel
        style={{ flex: 1, minHeight: 0, minWidth: 0, display: "flex" }}>
        <Stack gap={12} style={{ flex: 1, minHeight: 0, minWidth: 0 }}>
          <SettingListHeader
            title={title}
            count={`${sortedRecords.length} 条`}
            actions={
              <SettingHeaderActions>
                <Button
                  variant="default"
                  leftSection={<IconRefresh size={16} />}
                  onClick={() => void refresh(appliedFilters)}
                  loading={loading}>
                  刷新
                </Button>
                <Button
                  variant="default"
                  leftSection={<IconDownload size={16} />}
                  onClick={handleExport}>
                  下载数据
                </Button>
              </SettingHeaderActions>
            }
          />
          <SettingDataTable<any>
            fetching={loading}
            records={sortedRecords}
            columns={columns}
            idAccessor={rowKey as any}
            minHeight={0}
            scrollAreaProps={{ type: "auto" }}
            style={{ width: "100%", flex: 1, minWidth: 0, minHeight: 0 }}
            sortStatus={sortStatus}
            onSortStatusChange={setSortStatus}
          />
        </Stack>
      </SettingContentPanel>
    </Stack>
  )
}
