'use client';

/**
 * Canvas — sortable module list for the active device.
 *
 * Uses @dnd-kit/sortable SortableContext for reorder.
 * The DndContext lives in PageOrganizer (shared ancestor with Palette).
 *
 * Three onDragEnd cases (handled by makeDragEndHandler in PageOrganizer):
 *  1. Palette → Canvas: active.id starts with 'palette:' → add instance at target index.
 *  2. Canvas → Palette trash: over.id === 'palette-dropzone' → remove instance.
 *  3. Canvas reorder: both ids are instanceIds → reorder.
 *
 * The `__testOnlyMakeDragEndHandler` export allows canvas.test.tsx to test
 * all three cases without mounting DndContext.
 */

import { SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import type { DragEndEvent } from '@dnd-kit/core';
import type { ReactNode } from 'react';
import { useOrganizer } from './state';
import { CLIENT_MODULE_REGISTRY } from '@/server/page-layout/client-registry';
import { ModuleCard } from './ModuleCard';
import { useT } from '@/lib/i18n/react';
import type { LayoutModule } from '@/server/page-layout/types';

// ─── Drag-end handler (pure, exportable for tests + PageOrganizer) ────────────

export interface DragEndHandlerState {
  items: LayoutModule[];
  device: 'mobile' | 'desktop';
  add: (device: 'mobile' | 'desktop', at: number, mod: LayoutModule) => void;
  remove: (device: 'mobile' | 'desktop', instanceId: string) => void;
  reorder: (device: 'mobile' | 'desktop', from: number, to: number) => void;
}

export function makeDragEndHandler(state: DragEndHandlerState) {
  return function onDragEnd(e: DragEndEvent) {
    const { active, over } = e;
    if (!over) return;

    const activeId = String(active.id);
    const overId = String(over.id);

    // Case 1: Palette → Canvas
    if (activeId.startsWith('palette:')) {
      const type = activeId.slice('palette:'.length);
      const def = CLIENT_MODULE_REGISTRY[type];
      if (!def) return;
      const overIdx = state.items.findIndex((m) => m.instanceId === overId);
      const at = overIdx === -1 ? state.items.length : overIdx;
      state.add(state.device, at, {
        instanceId: crypto.randomUUID(),
        type,
        config: structuredClone(def.defaultConfig),
        visibility: { guests: true, loggedIn: true },
      });
      return;
    }

    // Case 2: Canvas → Palette trash
    if (overId === 'palette-dropzone') {
      state.remove(state.device, activeId);
      return;
    }

    // Case 3: Canvas reorder
    if (activeId !== overId) {
      const from = state.items.findIndex((m) => m.instanceId === activeId);
      const to = state.items.findIndex((m) => m.instanceId === overId);
      if (from !== -1 && to !== -1) {
        state.reorder(state.device, from, to);
      }
    }
  };
}

/**
 * Returns a drag-end handler for testing purposes.
 * @internal
 */
export function __testOnlyMakeDragEndHandler(state: DragEndHandlerState) {
  return makeDragEndHandler(state);
}

// ─── SortableItem wrapper ─────────────────────────────────────────────────────

function SortableItem({ id, children }: { id: string; children: ReactNode }) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id,
  });

  return (
    <li
      ref={setNodeRef}
      {...attributes}
      {...listeners}
      role={undefined}
      style={{
        transform: CSS.Transform.toString(transform),
        transition: transition ?? undefined,
      }}
      className={isDragging ? 'opacity-50' : undefined}
    >
      {children}
    </li>
  );
}

// ─── Canvas ───────────────────────────────────────────────────────────────────

export function Canvas() {
  const t = useT('page_organizer');
  const device = useOrganizer((s) => s.device);
  const body = useOrganizer((s) => s.body);
  const select = useOrganizer((s) => s.select);

  const items = body[device];

  return (
    <section
      aria-label={t('active_heading')}
      className="bg-surface-base border-border-default flex min-h-[24rem] flex-col gap-2 rounded-md border p-4"
    >
      <h2 className="text-text-primary text-sm font-semibold">{t('active_heading')}</h2>

      {items.length === 0 && (
        <p className="text-text-muted text-sm" aria-live="polite">
          {t('empty_active')}
        </p>
      )}

      <SortableContext
        items={items.map((m) => m.instanceId)}
        strategy={verticalListSortingStrategy}
      >
        <ol className="flex flex-col gap-2">
          {items.map((m) => {
            const isShared =
              body.mobile.some((x) => x.instanceId === m.instanceId) &&
              body.desktop.some((x) => x.instanceId === m.instanceId);

            return (
              <SortableItem key={m.instanceId} id={m.instanceId}>
                <ModuleCard
                  module={m}
                  showShared={isShared}
                  showHandle
                  onEdit={() => select(m.instanceId)}
                />
              </SortableItem>
            );
          })}
        </ol>
      </SortableContext>
    </section>
  );
}
