import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';
import { ComponentProps, ReactNode, useState } from 'react';

import DragAndDropContext, {
  DraggedObject,
  DraggedObjectType,
} from '@/app/(root)/dragAndDrop/DragAndDropContext';
import Droppable from '@/app/(root)/dragAndDrop/Droppable';
import { useContextSelector } from '@/hooks/useContextSelector';

const SpacerAnimation = keyframes`
  from {
    height: 0px;
  }
  to {
    height: 157px;
  }
`;

const Spacer = styled.div`
  animation: ${SpacerAnimation} 0.2s ease-in-out both;
`;

const BorderlessOverlay = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
`;

const DropOverlay = styled.div<{ isDraggedOver: boolean }>`
  position: absolute;
  top: 2px;
  left: 2px;
  right: 2px;
  bottom: 2px;
  border: 2px dashed
    ${({ isDraggedOver }) =>
      isDraggedOver
        ? 'rgb(var(--rgb-strawberry-600))'
        : 'var(--color-foreground-inactive)'};
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-family: 'PP Neue Montreal', sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  letter-spacing: 0.28px;
  color: ${({ isDraggedOver }) =>
    isDraggedOver
      ? 'rgb(var(--rgb-strawberry-600))'
      : 'var(--color-foreground-inactive)'};
  text-align: center;
  padding: 20px;
  transition:
    border-color 0.2s ease,
    color 0.2s ease;
`;

type CreateClipArrayDropzoneProps = Pick<
  ComponentProps<typeof Droppable>,
  'accept' | 'onDrop' | 'onDragMove' | 'onDragLeave'
> & {
  currentCount: number;
  maxCount: number;
  icon: ReactNode;
  emptyMessage: string;
  addMessage: (remainingSlots: number, isMultiple: boolean) => string;
};

export default function CreateClipArrayDropzone(
  props: CreateClipArrayDropzoneProps
) {
  const {
    currentCount,
    maxCount,
    icon,
    emptyMessage,
    addMessage,
    onDragMove,
    onDragLeave,
    ...droppableProps
  } = props;
  const [isDraggedOver, setIsDraggedOver] = useState(false);

  const hasValidDraggableObject = useContextSelector(
    DragAndDropContext,
    (ctx) =>
      ctx.draggedObject?.type === 'clip' ||
      ctx.draggedObject?.type === 'studio-timeline'
  );

  // Don't show if no valid object is being dragged
  if (!hasValidDraggableObject) {
    return null;
  }

  // Don't show if already at max capacity
  if (currentCount >= maxCount) {
    return null;
  }

  const remainingSlots = maxCount - currentCount;
  const isMultiple = remainingSlots > 1;

  const handleDragMove = (
    draggedObject: DraggedObject<DraggedObjectType>,
    event: React.MouseEvent<HTMLDivElement>
  ) => {
    setIsDraggedOver(true);
    onDragMove?.(draggedObject, event);
  };

  const handleDragLeave = (
    draggedObject: DraggedObject<DraggedObjectType>,
    event: React.MouseEvent<HTMLDivElement>
  ) => {
    setIsDraggedOver(false);
    onDragLeave?.(draggedObject, event);
  };

  return (
    <Droppable
      {...droppableProps}
      onDragMove={handleDragMove}
      onDragLeave={handleDragLeave}
      overlay={
        <BorderlessOverlay>
          <DropOverlay isDraggedOver={isDraggedOver}>
            {icon}
            {currentCount === 0
              ? emptyMessage
              : addMessage(remainingSlots, isMultiple)}
          </DropOverlay>
        </BorderlessOverlay>
      }
    >
      <Spacer />
    </Droppable>
  );
}
