import React, { useEffect, useMemo, useState, useContext } from 'react'
import { HolderOutlined } from '@ant-design/icons'
import { DndContext, useSensor, useSensors, PointerSensor, KeyboardSensor, DragEndEvent } from '@dnd-kit/core'
import { restrictToVerticalAxis } from '@dnd-kit/modifiers'
import { SortableContext, useSortable, verticalListSortingStrategy, arrayMove } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { Button, Flex, Modal, Form, Table, Radio } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import type { TableColumnsType } from 'antd'
import { useProcessData } from '../query'

interface DataType {
  key: number
  name: string
  raw_value: string
  new_value: string
}

interface RowContextProps {
  setActivatorNodeRef?: (element: HTMLElement | null) => void
  listeners?: any
}

const RowContext = React.createContext<RowContextProps>({})

const DragHandle: React.FC = () => {
  const { setActivatorNodeRef, listeners } = useContext(RowContext)
  return (
    <Button
      type="text"
      size="small"
      icon={<HolderOutlined />}
      style={{ cursor: 'grab' }}
      ref={setActivatorNodeRef}
      {...listeners}
    />
  )
}

export default function ButtonModal() {
  const { data: fields = [] } = useDataFieldQuery()

  const [open, setOpen] = useState(false)
  const [current, setCurrent] = useState(0)
  const [form] = Form.useForm()
  const [dataSource, setDataSource] = useState<DataType[]>([])
  const { mutate, isPending, progress, message, remove } = useProcessData()
  // 开始处理
  const handleStart = () => {
    const fields = dataSource.map((item) => {
      return { field: item.key, rule: item.new_value }
    })
    mutate({ fields: JSON.stringify(fields) })
  }

  // 关闭并重置
  const handleClose = () => {
    setOpen(false)
    setCurrent(0)
    remove()
  }

  useEffect(() => {
    if (fields?.length) {
      setDataSource(
        fields.map((item: any, index) => ({
          key: index + 1,
          ...item,
          new_value: 'default',
        }))
      )
    }
  }, [fields])

  const handleValueChange = (value: string, key: number) => {
    setDataSource((prevDataSource) =>
      prevDataSource.map((item) => (item.key === key ? { ...item, new_value: value } : item))
    )
  }

  const onDragEnd = ({ active, over }: DragEndEvent) => {
    if (active.id !== over?.id) {
      setDataSource((prevState) => {
        const activeIndex = prevState.findIndex((record) => record.key === active.id)
        const overIndex = prevState.findIndex((record) => record.key === over?.id)
        return arrayMove(prevState, activeIndex, overIndex)
      })
    }
  }

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: { distance: 5 },
    }),
    useSensor(KeyboardSensor)
  )

  const options = [
    { label: '无序', value: 'default' },
    { label: '升序', value: 'asc' },
    { label: '降序', value: 'desc' },
  ]

  const columns: TableColumnsType<DataType> = [
    { key: 'sort', align: 'center', width: 80, render: () => <DragHandle /> },
    { title: '字段名称', dataIndex: 'name', align: 'center' },
    {
      title: '排序方式',
      dataIndex: 'new_value',
      align: 'center',
      render: (_, record) => (
        <Radio.Group
          options={options}
          value={record.new_value}
          onChange={(e) => handleValueChange(e.target.value, record.key)}
        />
      ),
    },
  ]

  const steps = [
    {
      title: '请选择转换字段',
      content: (
        <Form.Item>
          <DndContext modifiers={[restrictToVerticalAxis]} sensors={sensors} onDragEnd={onDragEnd}>
            <SortableContext items={dataSource.map((i) => i.key)} strategy={verticalListSortingStrategy}>
              <Table<DataType>
                bordered
                pagination={false}
                rowKey="key"
                components={{ body: { row: DraggableRow } }}
                columns={columns}
                dataSource={dataSource}
              />
            </SortableContext>
          </DndContext>
        </Form.Item>
      ),
    },
    {
      title: '处理执行',
      content: (
        <Flex vertical align="center" style={{ marginTop: '20px' }}>
          <Button type="primary" loading={isPending} onClick={handleStart}>
            开始处理
          </Button>
          <AppProgressSteps
            style={{ margin: '80px' }}
            current={progress}
            items={[
              { title: '第一步\n开始', description: message[1] },
              { title: '第二步\n数据排序', description: message[2] },
              { title: '第三步\n处理结果', description: message[3] },
            ]}
          />
        </Flex>
      ),
    },
  ]

  return (
    <>
      <Button type="primary" onClick={() => setOpen(true)}>
        数据排序
      </Button>
      <Modal
        title={steps[current].title}
        open={open}
        footer={
          <Flex justify="center" gap={20}>
            {current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
            {current < steps.length - 1 && (
              <Button type="primary" onClick={() => setCurrent(current + 1)}>
                下一步
              </Button>
            )}
            {current === steps.length - 1 && (
              <Button type="primary" disabled={isPending} onClick={handleClose}>
                关闭
              </Button>
            )}
          </Flex>
        }
        destroyOnClose
        width={800}
        onCancel={handleClose}>
        <div style={{ minHeight: 300, padding: '20px 0' }}>
          <Form form={form} labelCol={{ span: 5 }} preserve={false}>
            {steps.map((item, index) => (
              <div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
                {item.content}
              </div>
            ))}
          </Form>
        </div>
      </Modal>
    </>
  )
}

interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
  'data-row-key': number
}

const DraggableRow: React.FC<RowProps> = (props) => {
  const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({
    id: props['data-row-key'],
  })

  const style: React.CSSProperties = {
    ...props.style,
    transform: CSS.Translate.toString(transform),
    transition,
    ...(isDragging ? { position: 'relative', zIndex: 9999 } : {}),
  }

  const contextValue = useMemo<RowContextProps>(
    () => ({ setActivatorNodeRef, listeners }),
    [setActivatorNodeRef, listeners]
  )

  return (
    <RowContext.Provider value={contextValue}>
      <tr {...props} ref={setNodeRef} style={style} {...attributes} />
    </RowContext.Provider>
  )
}
