import { FooterSetting } from '@/api/type';
import {
  closestCenter,
  DndContext,
  DragEndEvent,
  DragOverlay,
  DragStartEvent,
  MouseSensor,
  TouchSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import {
  rectSortingStrategy,
  SortableContext,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { Box, Button, IconButton, Stack, TextField } from '@mui/material';
import { Icon } from '@ctzhian/ui';
import {
  CSSProperties,
  forwardRef,
  HTMLAttributes,
  useCallback,
  useState,
} from 'react';
import {
  Control,
  Controller,
  FieldErrors,
  useFieldArray,
} from 'react-hook-form';

export type ItemProps = HTMLAttributes<HTMLDivElement> & {
  groupIndex: number;
  withOpacity?: boolean;
  isDragging?: boolean;
  dragHandleProps?: any;
  control: Control<FooterSetting>;
  errors: FieldErrors<FooterSetting>;
  setIsEdit: (value: boolean) => void;
  handleRemove?: () => void;
};

interface LinkItemProps extends HTMLAttributes<HTMLDivElement> {
  linkId: string;
  linkIndex: number;
  groupIndex: number;
  control: Control<FooterSetting>;
  errors: FieldErrors<FooterSetting>;
  setIsEdit: (value: boolean) => void;
  onRemove: () => void;
  withOpacity?: boolean;
  isDragging?: boolean;
  dragHandleProps?: any;
}

const LinkItem = forwardRef<HTMLDivElement, LinkItemProps>(
  (
    {
      linkIndex,
      groupIndex,
      control,
      errors,
      setIsEdit,
      onRemove,
      withOpacity,
      isDragging,
      dragHandleProps,
      style,
      ...props
    },
    ref,
  ) => {
    const inlineStyles: CSSProperties = {
      opacity: withOpacity ? '0.5' : '1',
      cursor: isDragging ? 'grabbing' : 'grab',
      ...style,
    };

    return (
      <Box ref={ref} style={inlineStyles} {...props}>
        <Stack gap={1} alignItems='center' direction='row'>
          <IconButton
            size='small'
            sx={{
              cursor: 'grab',
              color: 'text.secondary',
              '&:hover': { color: 'primary.main' },
              flexShrink: 0,
            }}
            {...dragHandleProps}
          >
            <Icon type='icon-drag' />
          </IconButton>
          <Box
            sx={{
              color: 'text.secondary',
              flexShrink: 0,
              fontSize: 12,
              width: 20,
            }}
          >
            {linkIndex + 1}.
          </Box>
          <Controller
            control={control}
            name={`brand_groups.${groupIndex}.links.${linkIndex}.name`}
            rules={{ required: '请输入链接文字' }}
            render={({ field }) => (
              <TextField
                {...field}
                sx={{ width: 300 }}
                label='链接文字'
                placeholder='链接文字'
                onChange={e => {
                  field.onChange(e.target.value);
                  setIsEdit(true);
                }}
                error={
                  !!errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.name
                }
                helperText={
                  errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.name
                    ?.message
                }
              />
            )}
          />
          <Controller
            control={control}
            name={`brand_groups.${groupIndex}.links.${linkIndex}.url`}
            rules={{ required: '请输入链接地址' }}
            render={({ field }) => (
              <TextField
                {...field}
                fullWidth
                label='链接地址'
                placeholder='链接地址'
                onChange={e => {
                  field.onChange(e.target.value);
                  setIsEdit(true);
                }}
                error={
                  !!errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.url
                }
                helperText={
                  errors.brand_groups?.[groupIndex]?.links?.[linkIndex]?.url
                    ?.message
                }
              />
            )}
          />
          <IconButton size='small' sx={{ flexShrink: 0 }} onClick={onRemove}>
            <Icon type='icon-icon_tool_close' />
          </IconButton>
        </Stack>
      </Box>
    );
  },
);

const SortableLinkItem: React.FC<LinkItemProps> = ({ linkId, ...rest }) => {
  const {
    isDragging,
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({ id: linkId });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition: transition || undefined,
  };

  return (
    <LinkItem
      ref={setNodeRef}
      style={style}
      withOpacity={isDragging}
      dragHandleProps={{
        ...attributes,
        ...listeners,
      }}
      linkId={linkId}
      {...rest}
    />
  );
};

const Item = forwardRef<HTMLDivElement, ItemProps>(
  (
    {
      groupIndex,
      withOpacity,
      isDragging,
      style,
      dragHandleProps,
      handleRemove,
      control,
      errors,
      setIsEdit,
      ...props
    },
    ref,
  ) => {
    const [activeId, setActiveId] = useState<string | null>(null);
    const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor));

    const {
      fields: linkFields,
      append: appendLink,
      remove: removeLink,
      move: moveLink,
    } = useFieldArray({
      control,
      name: `brand_groups.${groupIndex}.links`,
    });

    const inlineStyles: CSSProperties = {
      opacity: withOpacity ? '0.5' : '1',
      borderRadius: '10px',
      cursor: isDragging ? 'grabbing' : 'grab',
      backgroundColor: '#ffffff',
      width: '100%',
      ...style,
    };

    const handleLinkDragStart = useCallback((event: DragStartEvent) => {
      setActiveId(event.active.id as string);
    }, []);

    const handleLinkDragEnd = useCallback(
      (event: DragEndEvent) => {
        const { active, over } = event;
        if (active.id !== over?.id) {
          const oldIndex = linkFields.findIndex(
            (_, index) => `link-${groupIndex}-${index}` === active.id,
          );
          const newIndex = linkFields.findIndex(
            (_, index) => `link-${groupIndex}-${index}` === over!.id,
          );
          moveLink(oldIndex, newIndex);
          setIsEdit(true);
        }
        setActiveId(null);
      },
      [linkFields, moveLink, setIsEdit, groupIndex],
    );

    const handleLinkDragCancel = useCallback(() => {
      setActiveId(null);
    }, []);

    const handleAddLink = () => {
      appendLink({ name: '', url: '' });
      setIsEdit(true);
    };

    const handleRemoveLink = (linkIndex: number) => {
      removeLink(linkIndex);
      setIsEdit(true);
    };

    return (
      <Box ref={ref} style={inlineStyles} {...props}>
        <Box
          sx={{
            border: '1px solid',
            borderColor: 'divider',
            borderRadius: '10px',
            p: 2,
            mb: 1,
            pb: 1,
          }}
        >
          <Stack direction='row' alignItems='center' gap={1} sx={{ mb: 1 }}>
            <IconButton
              size='small'
              sx={{
                cursor: 'grab',
                color: 'text.secondary',
                '&:hover': { color: 'primary.main' },
                flexShrink: 0,
              }}
              {...dragHandleProps}
            >
              <Icon type='icon-drag' />
            </IconButton>
            <Controller
              control={control}
              name={`brand_groups.${groupIndex}.name`}
              rules={{ required: '请输入链接组名称' }}
              render={({ field }) => (
                <TextField
                  {...field}
                  fullWidth
                  placeholder='输入链接组名称'
                  label='链接组名称'
                  onChange={e => {
                    field.onChange(e.target.value);
                    setIsEdit(true);
                  }}
                  error={!!errors.brand_groups?.[groupIndex]?.name}
                  helperText={errors.brand_groups?.[groupIndex]?.name?.message}
                />
              )}
            />
            <IconButton size='small' onClick={handleRemove}>
              <Icon type='icon-icon_tool_close' />
            </IconButton>
          </Stack>

          {/* 链接拖拽区域 */}
          {linkFields.length > 0 && (
            <Box
              sx={{
                border: '1px dashed',
                borderColor: 'divider',
                borderRadius: '10px',
                py: 1,
                pl: 2,
              }}
            >
              <DndContext
                sensors={sensors}
                collisionDetection={closestCenter}
                onDragStart={handleLinkDragStart}
                onDragEnd={handleLinkDragEnd}
                onDragCancel={handleLinkDragCancel}
              >
                <SortableContext
                  items={linkFields.map(
                    (_, index) => `link-${groupIndex}-${index}`,
                  )}
                  strategy={rectSortingStrategy}
                >
                  <Stack gap={1}>
                    {linkFields.map((link, linkIndex) => (
                      <SortableLinkItem
                        key={link.id}
                        linkId={`link-${groupIndex}-${linkIndex}`}
                        linkIndex={linkIndex}
                        groupIndex={groupIndex}
                        control={control}
                        errors={errors}
                        setIsEdit={setIsEdit}
                        onRemove={() => handleRemoveLink(linkIndex)}
                      />
                    ))}
                  </Stack>
                </SortableContext>
                <DragOverlay adjustScale style={{ transformOrigin: '0 0' }}>
                  {activeId ? (
                    <LinkItem
                      isDragging
                      linkId={activeId}
                      linkIndex={parseInt(activeId.split('-')[2])}
                      groupIndex={groupIndex}
                      control={control}
                      errors={errors}
                      setIsEdit={setIsEdit}
                      onRemove={() => {}}
                    />
                  ) : null}
                </DragOverlay>
              </DndContext>
            </Box>
          )}

          <Button
            size='small'
            startIcon={
              <Icon type='icon-add' sx={{ fontSize: '12px !important' }} />
            }
            onClick={handleAddLink}
            sx={{ mt: 1 }}
          >
            添加一个链接
          </Button>
        </Box>
      </Box>
    );
  },
);

export default Item;
