'use client';

import { useState, useCallback, useMemo } from 'react';
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
  DragStartEvent,
  DragOverlay,
} from '@dnd-kit/core';
import {
  arrayMove,
  SortableContext,
  rectSortingStrategy,
  useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { GripVertical, Image as ImageIcon, Maximize2, Save } from 'lucide-react';
import toast from 'react-hot-toast';
import api from '@/lib/api';
import { EventGalleryItem } from '@/types';
import Button from '@/components/ui/Button';

type CardSize = 'small' | 'wide' | 'tall' | 'large';

const SIZE_CYCLE: CardSize[] = ['small', 'wide', 'tall', 'large'];

const SIZE_META: Record<CardSize, { label: string; dim: string; cls: string; badgeCls: string }> = {
  small: { label: 'Regular', dim: '1×1', cls: '', badgeCls: 'bg-gray-600' },
  wide:  { label: 'Wide',    dim: '2×1', cls: 'col-span-2', badgeCls: 'bg-sky-600' },
  tall:  { label: 'Tall',    dim: '1×2', cls: 'row-span-2', badgeCls: 'bg-violet-600' },
  large: { label: 'Featured', dim: '2×2', cls: 'col-span-2 row-span-2', badgeCls: 'bg-amber-600' },
};

const MIN_H: Record<CardSize, number> = { small: 120, wide: 130, tall: 260, large: 260 };

interface LayoutEvent {
  _id: string;
  title: { en: string; zh: string };
  coverImage?: string;
  cardSize: CardSize;
  order: number;
  status: 'draft' | 'published';
}

interface LayoutPreviewProps {
  events: EventGalleryItem[];
  onSaved: () => void;
}

// --- Sortable Card ---

function SortableCard({
  item,
  isDirty,
  onCycleSize,
}: {
  item: LayoutEvent;
  isDirty: boolean;
  onCycleSize: (id: string) => void;
}) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id: item._id,
  });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    minHeight: MIN_H[item.cardSize],
    opacity: isDragging ? 0.4 : 1,
  };

  const meta = SIZE_META[item.cardSize];

  return (
    <div
      ref={setNodeRef}
      style={style}
      className={`relative rounded-lg overflow-hidden select-none group ${meta.cls} ${
        isDirty ? 'ring-2 ring-blue-400' : ''
      }`}
    >
      {/* Background */}
      {item.coverImage ? (
        <img
          src={item.coverImage}
          alt=""
          className="absolute inset-0 w-full h-full object-cover"
          draggable={false}
        />
      ) : (
        <div className="absolute inset-0 bg-gradient-to-br from-gray-600 to-gray-800 flex items-center justify-center">
          <ImageIcon className="h-8 w-8 text-gray-400/40" />
        </div>
      )}

      {/* Dark overlay */}
      <div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-black/30" />

      {/* Drag handle */}
      <button
        {...attributes}
        {...listeners}
        className="absolute top-2 left-1/2 -translate-x-1/2 z-20 p-1 rounded bg-black/40 backdrop-blur-sm text-white/70 hover:text-white hover:bg-black/60 cursor-grab active:cursor-grabbing transition-colors"
        title="Drag to reorder"
      >
        <GripVertical size={14} />
      </button>

      {/* Size badge */}
      <span className={`absolute top-2 left-2 z-10 text-[10px] font-semibold text-white px-1.5 py-0.5 rounded ${meta.badgeCls}`}>
        {meta.dim}
      </span>

      {/* Cycle size button */}
      <button
        onClick={(e) => {
          e.stopPropagation();
          onCycleSize(item._id);
        }}
        className="absolute top-2 right-2 z-10 p-1 rounded bg-black/40 backdrop-blur-sm text-white/70 hover:text-white hover:bg-black/60 transition-colors"
        title={`Current: ${meta.label}. Click to change size.`}
      >
        <Maximize2 size={12} />
      </button>

      {/* Draft badge */}
      {item.status === 'draft' && (
        <span className="absolute top-8 right-2 z-10 text-[9px] font-medium text-orange-300 bg-black/40 px-1.5 py-0.5 rounded">
          Draft
        </span>
      )}

      {/* Title overlay */}
      <div className="absolute bottom-0 left-0 right-0 p-2.5 z-10">
        <p className="text-white text-xs font-semibold leading-snug line-clamp-2 drop-shadow-sm">
          {item.title?.en || item.title?.zh || 'Untitled'}
        </p>
      </div>
    </div>
  );
}

// --- Overlay card (shown while dragging) ---

function OverlayCard({ item }: { item: LayoutEvent }) {
  const meta = SIZE_META[item.cardSize];
  return (
    <div
      className={`relative rounded-lg overflow-hidden shadow-2xl ring-2 ring-blue-500 ${meta.cls}`}
      style={{ minHeight: MIN_H[item.cardSize], width: 200, opacity: 0.9 }}
    >
      {item.coverImage ? (
        <img src={item.coverImage} alt="" className="absolute inset-0 w-full h-full object-cover" />
      ) : (
        <div className="absolute inset-0 bg-gradient-to-br from-gray-600 to-gray-800" />
      )}
      <div className="absolute inset-0 bg-black/50" />
      <div className="absolute bottom-0 left-0 right-0 p-2 z-10">
        <p className="text-white text-xs font-semibold line-clamp-1">
          {item.title?.en || item.title?.zh || 'Untitled'}
        </p>
      </div>
    </div>
  );
}

// --- Main Component ---

export default function LayoutPreview({ events, onSaved }: LayoutPreviewProps) {
  const initial = useMemo(
    () =>
      events
        .map((e) => ({
          _id: e._id,
          title: { en: e.title?.en || '', zh: e.title?.zh || '' },
          coverImage: e.coverImage,
          cardSize: (e.cardSize || 'small') as CardSize,
          order: e.order ?? 0,
          status: e.status,
        }))
        .sort((a, b) => a.order - b.order),
    [events]
  );

  const [items, setItems] = useState<LayoutEvent[]>(initial);
  const [activeId, setActiveId] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState(false);

  // Track which items have changed vs original
  const changes = useMemo(() => {
    const diffs: Array<{ id: string; order?: number; cardSize?: string }> = [];
    const origMap = new Map(initial.map((e) => [e._id, e]));
    items.forEach((item, idx) => {
      const orig = origMap.get(item._id);
      if (!orig) return;
      const orderChanged = idx !== initial.indexOf(orig);
      const sizeChanged = item.cardSize !== orig.cardSize;
      if (orderChanged || sizeChanged) {
        diffs.push({
          id: item._id,
          ...(orderChanged && { order: idx }),
          ...(sizeChanged && { cardSize: item.cardSize }),
        });
      }
    });
    return diffs;
  }, [items, initial]);

  const dirtyIds = useMemo(() => new Set(changes.map((c) => c.id)), [changes]);

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

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

  const handleDragEnd = useCallback(
    (event: DragEndEvent) => {
      setActiveId(null);
      const { active, over } = event;
      if (!over || active.id === over.id) return;

      setItems((prev) => {
        const oldIdx = prev.findIndex((i) => i._id === active.id);
        const newIdx = prev.findIndex((i) => i._id === over.id);
        return arrayMove(prev, oldIdx, newIdx);
      });
    },
    []
  );

  const cycleSize = useCallback((id: string) => {
    setItems((prev) =>
      prev.map((item) => {
        if (item._id !== id) return item;
        const curIdx = SIZE_CYCLE.indexOf(item.cardSize);
        const next = SIZE_CYCLE[(curIdx + 1) % SIZE_CYCLE.length];
        return { ...item, cardSize: next };
      })
    );
  }, []);

  const handleSave = async () => {
    if (changes.length === 0) return;
    setIsSaving(true);
    try {
      const updates = items.map((item, idx) => ({
        id: item._id,
        order: idx,
        cardSize: item.cardSize,
      }));
      await api.batchUpdateEventGallery(updates);
      toast.success(`Layout saved (${changes.length} changes)`);
      onSaved();
    } catch {
      toast.error('Failed to save layout');
    } finally {
      setIsSaving(false);
    }
  };

  const activeItem = activeId ? items.find((i) => i._id === activeId) : null;

  return (
    <div className="space-y-4">
      {/* Toolbar */}
      <div className="flex items-center justify-between">
        <div className="text-sm text-gray-500">
          {items.length} events &middot; Drag to reorder, click{' '}
          <Maximize2 size={11} className="inline -mt-0.5" /> to cycle card size
        </div>
        {changes.length > 0 && (
          <Button onClick={handleSave} isLoading={isSaving} size="sm">
            <Save size={14} />
            Save Layout ({changes.length} {changes.length === 1 ? 'change' : 'changes'})
          </Button>
        )}
      </div>

      {/* Size legend */}
      <div className="flex flex-wrap gap-3 text-[11px]">
        {SIZE_CYCLE.map((s) => (
          <span key={s} className="flex items-center gap-1.5">
            <span className={`inline-block w-3 h-3 rounded ${SIZE_META[s].badgeCls}`} />
            {SIZE_META[s].label} ({SIZE_META[s].dim})
          </span>
        ))}
      </div>

      {/* Grid */}
      <DndContext
        sensors={sensors}
        collisionDetection={closestCenter}
        onDragStart={handleDragStart}
        onDragEnd={handleDragEnd}
      >
        <SortableContext items={items.map((i) => i._id)} strategy={rectSortingStrategy}>
          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 md:gap-3 auto-rows-[minmax(120px,auto)] bg-gray-100 rounded-xl p-3">
            {items.map((item) => (
              <SortableCard
                key={item._id}
                item={item}
                isDirty={dirtyIds.has(item._id)}
                onCycleSize={cycleSize}
              />
            ))}
          </div>
        </SortableContext>

        <DragOverlay>
          {activeItem ? <OverlayCard item={activeItem} /> : null}
        </DragOverlay>
      </DndContext>
    </div>
  );
}
