'use client';

import { ReactNode, useState, useCallback } from 'react';
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
  DragStartEvent,
  DragOverlay,
} from '@dnd-kit/core';
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  rectSortingStrategy,
} from '@dnd-kit/sortable';
import { motion, AnimatePresence } from 'framer-motion';
import { useTranslations } from 'next-intl';

import { cn } from '@/lib/utils';

export interface WidgetItem {
  id: string;
  type: string;
  colSpan?: number;
  rowSpan?: number;
  settings?: Record<string, unknown>;
}

export interface WidgetGridProps {
  /** Array of widget items to render */
  widgets: WidgetItem[];
  /** Callback when widget order changes */
  onWidgetsChange: (widgets: WidgetItem[]) => void;
  /** Whether the grid is in edit mode */
  isEditing?: boolean;
  /** Function to render a widget by its item */
  renderWidget: (item: WidgetItem, isEditing: boolean) => ReactNode;
  /** Additional CSS classes */
  className?: string;
  /** Number of grid columns */
  columns?: number;
}

/**
 * Widget Grid - Drag and drop grid layout for dashboard widgets
 * Uses dnd-kit for drag and drop functionality
 */
export function WidgetGrid({
  widgets,
  onWidgetsChange,
  isEditing = false,
  renderWidget,
  className,
  columns = 4,
}: WidgetGridProps) {
  const [activeId, setActiveId] = useState<string | null>(null);

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8, // Prevent accidental drags
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

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

  const handleDragEnd = useCallback(
    (event: DragEndEvent) => {
      const { active, over } = event;

      if (over && active.id !== over.id) {
        const oldIndex = widgets.findIndex((w) => w.id === active.id);
        const newIndex = widgets.findIndex((w) => w.id === over.id);

        const newWidgets = arrayMove(widgets, oldIndex, newIndex);
        onWidgetsChange(newWidgets);
      }

      setActiveId(null);
    },
    [widgets, onWidgetsChange]
  );

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

  const activeWidget = activeId ? widgets.find((w) => w.id === activeId) : null;

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragStart={handleDragStart}
      onDragEnd={handleDragEnd}
      onDragCancel={handleDragCancel}
    >
      <SortableContext items={widgets.map((w) => w.id)} strategy={rectSortingStrategy}>
        <motion.div
          className={cn(
            'grid gap-4',
            // Responsive grid columns
            'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
            className
          )}
          style={{
            // Allow custom column count on larger screens
            gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
          }}
          layout
        >
          <AnimatePresence mode="popLayout">
            {widgets.map((item) => (
              <motion.div
                key={item.id}
                layout
                initial={{ opacity: 0, scale: 0.8 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.8 }}
                transition={{ duration: 0.2 }}
                style={{
                  gridColumn: item.colSpan ? `span ${item.colSpan}` : undefined,
                  gridRow: item.rowSpan ? `span ${item.rowSpan}` : undefined,
                }}
              >
                {renderWidget(item, isEditing)}
              </motion.div>
            ))}
          </AnimatePresence>
        </motion.div>
      </SortableContext>

      {/* Drag overlay for visual feedback */}
      <DragOverlay adjustScale>
        {activeWidget ? (
          <div className="opacity-80">{renderWidget(activeWidget, false)}</div>
        ) : null}
      </DragOverlay>
    </DndContext>
  );
}

/**
 * Empty state component for when no widgets are added
 */
export function WidgetGridEmpty({ onAddWidget }: { onAddWidget?: () => void }) {
  const t = useTranslations('widgets');

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      className="flex min-h-[300px] flex-col items-center justify-center rounded-lg border-2 border-dashed border-muted-foreground/25 p-8 text-center"
    >
      <div className="mx-auto flex max-w-[420px] flex-col items-center justify-center text-center">
        <div className="flex h-20 w-20 items-center justify-center rounded-full bg-muted">
          <svg
            className="h-10 w-10 text-muted-foreground"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={1.5}
              d="M4 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1V5zM4 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1v-4zM14 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z"
            />
          </svg>
        </div>

        <h3 className="mt-4 text-lg font-semibold">{t('noWidgets')}</h3>
        <p className="mt-2 text-sm text-muted-foreground">
          {t('noWidgetsDescription')}
        </p>

        {onAddWidget && (
          <button
            onClick={onAddWidget}
            className="mt-4 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors"
          >
            <svg
              className="h-4 w-4"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
            </svg>
            {t('addWidgetButton')}
          </button>
        )}
      </div>
    </motion.div>
  );
}
