import { For, createSignal, createMemo, onCleanup, onMount } from "solid-js";
import type { DeckStore } from "../hooks/deckStore";
import {
  DragDropProvider,
  DragDropSensors,
  createSortable,
  maybeTransformStyle,
  closestCenter,
} from "@thisbeyond/solid-dnd";
import alignLeftIcon from "./icons/align-left.png";
import alignCenterIcon from "./icons/align-center.png";
import alignRightIcon from "./icons/align-right.png";

export interface LayerEditorPanelProps {
  store: DeckStore;
}

const ORIENTATION_OPTIONS = [
  { value: "n", label: "↑ 北" },
  { value: "e", label: "→ 东" },
  { value: "s", label: "↓ 南" },
  { value: "w", label: "← 西" },
] as const;

const ALIGN_OPTIONS = [
  { value: "", label: "默认", icon: alignCenterIcon },
  { value: "l", label: "左对齐", icon: alignLeftIcon },
  { value: "c", label: "居中", icon: alignCenterIcon },
  { value: "r", label: "右对齐", icon: alignRightIcon },
] as const;

const FONT_PRESETS = [3, 5, 8, 12] as const;

function OrientationIcon(value: string): string {
  switch (value) {
    case "n":
      return "↑";
    case "e":
      return "→";
    case "s":
      return "↓";
    case "w":
      return "←";
    default:
      return "↑";
  }
}

function AlignIconSrc(value: string): string {
  switch (value) {
    case "l":
      return alignLeftIcon;
    case "r":
      return alignRightIcon;
    default:
      return alignCenterIcon;
  }
}

function LayerEditorPanel(props: LayerEditorPanelProps) {
  const { store } = props;
  const [openDropdown, setOpenDropdown] = createSignal<string | null>(null);
  const [hoveredIndex, setHoveredIndex] = createSignal<number | null>(null);
  const [addMenuOpen, setAddMenuOpen] = createSignal(false);
  let addMenuRef: HTMLDivElement | undefined;

  const side = () => store.state.activeSide;

  const currentLayerConfigs = () =>
    side() === "front"
      ? store.state.frontLayerConfigs
      : store.state.backLayerConfigs;

  // Available CSV fields not yet used in the current side
  const availableFields = createMemo(() => {
    const cards = store.state.cards;
    if (!cards || cards.length === 0) return [];
    const usedProps = new Set(currentLayerConfigs().map((l) => l.prop));
    return Object.keys(cards[0]).filter(
      (k) => k !== "label" && !usedProps.has(k),
    );
  });

  const updateFn = () =>
    side() === "front"
      ? store.actions.updateFrontLayerConfig
      : store.actions.updateBackLayerConfig;

  const updateLayerOrientation = (
    index: number,
    orientation: "n" | "s" | "e" | "w",
  ) => {
    updateFn()(index, { orientation });
    setOpenDropdown(null);
  };

  const updateLayerFontSize = (index: number, fontSize?: number) => {
    updateFn()(index, { fontSize });
  };

  const updateLayerAlign = (index: number, align?: "l" | "c" | "r") => {
    updateFn()(index, { align });
    setOpenDropdown(null);
  };

  const selectLayer = (index: number) => {
    store.actions.setSelectedLayer(
      store.state.selectedLayer === index ? null : index,
    );
  };

  const handleClickOutside = (e: MouseEvent) => {
    if (addMenuRef && !addMenuRef.contains(e.target as Node)) {
      setAddMenuOpen(false);
    }
  };

  onMount(() => {
    document.addEventListener("click", handleClickOutside);
  });

  onCleanup(() => {
    document.removeEventListener("click", handleClickOutside);
  });

  const onDragEnd: import("@thisbeyond/solid-dnd").DragEventHandler = ({
    draggable,
    droppable,
  }) => {
    if (droppable) {
      const fromIndex = draggable.id as number;
      const toIndex = droppable.id as number;
      if (fromIndex !== toIndex) {
        store.actions.reorderLayers(side(), fromIndex, toIndex);
      }
    }
  };

  return (
    <div class="w-64 flex-shrink-0">
      <h3 class="font-bold mb-2 mt-0">
        图层 ({side() === "front" ? "正面" : "背面"})
      </h3>

      {/* Add layer dropdown */}
      <div class="relative mb-2" ref={addMenuRef}>
        <button
          onClick={() => setAddMenuOpen(!addMenuOpen())}
          class="w-full flex items-center gap-2 px-3 py-1.5 text-sm rounded cursor-pointer border border-dashed border-gray-300 bg-gray-50 hover:bg-gray-100 text-gray-600"
        >
          <span class="text-lg leading-none">+</span>
          <span>添加图层</span>
        </button>
        {addMenuOpen() && (
          <div
            class="absolute top-full left-0 mt-1 w-full bg-white border border-gray-300 rounded shadow-lg z-20 max-h-48 overflow-y-auto"
            onClick={(e) => e.stopPropagation()}
          >
            {availableFields().length === 0 ? (
              <div class="px-3 py-2 text-sm text-gray-400">所有字段已添加</div>
            ) : (
              <For each={availableFields()}>
                {(field) => (
                  <button
                    onClick={() => {
                      store.actions.addLayer(side(), field);
                      setAddMenuOpen(false);
                    }}
                    class="block w-full text-left px-3 py-1.5 text-sm hover:bg-blue-50 hover:text-blue-600 cursor-pointer"
                  >
                    {field}
                  </button>
                )}
              </For>
            )}
          </div>
        )}
      </div>

      {/* Drag and drop list */}
      <DragDropProvider onDragEnd={onDragEnd} collisionDetector={closestCenter}>
        <DragDropSensors>
          <For each={currentLayerConfigs()}>
            {(layer, index) => (
              <LayerRow
                store={store}
                index={index()}
                layer={layer}
                hovered={hoveredIndex() === index()}
                setHoveredIndex={setHoveredIndex}
                openDropdown={openDropdown()}
                setOpenDropdown={setOpenDropdown}
                updateOrientation={(o) => updateLayerOrientation(index(), o)}
                updateFontSize={(fs) => updateLayerFontSize(index(), fs)}
                updateAlign={(a) => updateLayerAlign(index(), a)}
                onSelect={() => selectLayer(index())}
                onRemove={() => store.actions.removeLayer(side(), index())}
              />
            )}
          </For>
        </DragDropSensors>
      </DragDropProvider>

      <hr class="my-4" />

      <button
        onClick={() => store.actions.copyCode()}
        class="w-full bg-blue-600 hover:bg-blue-700 text-white px-3 py-2 rounded text-sm font-medium cursor-pointer flex items-center gap-2 justify-center"
      >
        <span>📋</span>
        <span>复制代码</span>
      </button>
    </div>
  );
}

// --- Sortable layer row ---

interface LayerRowProps {
  store: DeckStore;
  index: number;
  layer: import("../types").LayerConfig;
  hovered: boolean;
  setHoveredIndex: (idx: number | null) => void;
  openDropdown: string | null;
  setOpenDropdown: (val: string | null) => void;
  updateOrientation: (o: "n" | "s" | "e" | "w") => void;
  updateFontSize: (fs?: number) => void;
  updateAlign: (a?: "l" | "c" | "r") => void;
  onSelect: () => void;
  onRemove: () => void;
}

function LayerRow(props: LayerRowProps) {
  const sortable = createSortable(props.index);
  const [fontOpen, setFontOpen] = createSignal(false);
  let fontDropdownRef: HTMLDivElement | undefined;

  const selected = () => props.store.state.selectedLayer === props.index;

  const handleFontClickOutside = (e: MouseEvent) => {
    if (fontDropdownRef && !fontDropdownRef.contains(e.target as Node)) {
      setFontOpen(false);
    }
  };

  onMount(() => {
    document.addEventListener("click", handleFontClickOutside);
  });

  onCleanup(() => {
    document.removeEventListener("click", handleFontClickOutside);
  });

  return (
    <div
      ref={sortable.ref}
      style={maybeTransformStyle(sortable.transform)}
      class={`flex items-center gap-1 py-1.5 px-1 relative group border-b border-gray-100 ${
        selected() ? "bg-blue-50" : ""
      }`}
      onMouseEnter={() => props.setHoveredIndex(props.index)}
      onMouseLeave={() => props.setHoveredIndex(null)}
    >
      {/* Drag handle */}
      <button
        {...sortable.dragActivators}
        class="cursor-grab text-gray-400 hover:text-gray-600 text-sm px-0.5 select-none shrink-0"
        title="拖动排序"
      >
        ⠿
      </button>

      {/* Visibility toggle */}
      <button
        onClick={() => {
          const toggleFn =
            props.store.state.activeSide === "front"
              ? props.store.actions.toggleFrontLayerVisible
              : props.store.actions.toggleBackLayerVisible;
          toggleFn(props.index);
        }}
        class="shrink-0 text-sm cursor-pointer select-none"
        title={props.layer.visible ? "隐藏" : "显示"}
      >
        {props.layer.visible ? "👁" : "👁‍🗨"}
      </button>

      {/* Layer name */}
      <span
        class="text-sm flex-1 truncate cursor-pointer hover:text-blue-600 select-none"
        onClick={props.onSelect}
      >
        {props.layer.prop}
      </span>

      {/* Orientation */}
      <div class="relative">
        <button
          onClick={(e) => {
            e.stopPropagation();
            props.setOpenDropdown(
              props.openDropdown === `orient-${props.index}`
                ? null
                : `orient-${props.index}`,
            );
          }}
          class={`w-7 h-7 text-sm rounded cursor-pointer flex items-center justify-center bg-gray-200 text-gray-700 hover:bg-gray-300 ${
            !props.layer.visible ? "invisible pointer-events-none" : ""
          }`}
          title="方向"
        >
          {OrientationIcon(props.layer.orientation || "n")}
        </button>
        {props.openDropdown === `orient-${props.index}` && (
          <div
            class="absolute top-full right-0 mt-1 bg-white border border-gray-300 rounded shadow-lg z-10"
            onClick={(e) => e.stopPropagation()}
          >
            <For each={ORIENTATION_OPTIONS}>
              {(opt) => (
                <button
                  onClick={() => props.updateOrientation(opt.value)}
                  class="block w-full text-left px-3 py-1.5 text-sm hover:bg-gray-100 cursor-pointer whitespace-nowrap"
                >
                  {opt.label}
                </button>
              )}
            </For>
          </div>
        )}
      </div>

      {/* Align */}
      <div class="relative">
        <button
          onClick={(e) => {
            e.stopPropagation();
            props.setOpenDropdown(
              props.openDropdown === `align-${props.index}`
                ? null
                : `align-${props.index}`,
            );
          }}
          class={`w-7 h-7 rounded cursor-pointer flex items-center justify-center bg-gray-200 hover:bg-gray-300 ${
            !props.layer.visible ? "invisible pointer-events-none" : ""
          }`}
          title="对齐"
        >
          <img
            src={AlignIconSrc(props.layer.align || "")}
            alt="align"
            class="w-5 h-5 not-prose"
          />
        </button>
        {props.openDropdown === `align-${props.index}` && (
          <div
            class="absolute top-full right-0 mt-1 bg-white border border-gray-300 rounded shadow-lg z-10"
            onClick={(e) => e.stopPropagation()}
          >
            <For each={ALIGN_OPTIONS}>
              {(opt) => (
                <button
                  onClick={() =>
                    props.updateAlign(
                      (opt.value as "l" | "c" | "r" | undefined) || undefined,
                    )
                  }
                  class="flex items-center gap-2 w-full px-3 py-1.5 text-sm hover:bg-gray-100 cursor-pointer whitespace-nowrap"
                >
                  <img
                    src={opt.icon}
                    alt=""
                    class="w-4 h-4 not-prose max-w-none"
                  />
                </button>
              )}
            </For>
          </div>
        )}
      </div>

      {/* Font size */}
      <div class="relative" ref={fontDropdownRef}>
        <button
          onClick={(e) => {
            e.stopPropagation();
            setFontOpen(!fontOpen());
          }}
          class={`w-7 h-7 text-xs rounded cursor-pointer flex items-center justify-center bg-gray-200 text-gray-700 hover:bg-gray-300 ${
            !props.layer.visible ? "invisible pointer-events-none" : ""
          }`}
          title="字体大小 (mm)"
        >
          {props.layer.fontSize ?? 3}
        </button>
        {fontOpen() && (
          <div
            class="absolute top-full right-0 mt-1 bg-white border border-gray-300 rounded shadow-lg z-10 p-2"
            onClick={(e) => e.stopPropagation()}
          >
            <div class="flex items-center gap-1 mb-2">
              <input
                type="number"
                value={props.layer.fontSize ?? 3}
                onChange={(e) => {
                  const value = e.target.value;
                  props.updateFontSize(value ? Number(value) : undefined);
                }}
                class="w-14 text-xs px-1.5 py-1 rounded border border-gray-300"
                step="0.1"
                min="0.1"
              />
              <span class="text-xs text-gray-500">mm</span>
            </div>
            <div class="flex gap-1">
              <For each={FONT_PRESETS}>
                {(preset) => (
                  <button
                    onClick={() => props.updateFontSize(preset)}
                    class={`px-2 py-1 text-xs rounded cursor-pointer ${
                      (props.layer.fontSize ?? 3) === preset
                        ? "bg-blue-500 text-white"
                        : "bg-gray-100 hover:bg-gray-200 text-gray-700"
                    }`}
                  >
                    {preset}
                  </button>
                )}
              </For>
            </div>
            <button
              onClick={() => props.updateFontSize(undefined)}
              class="mt-2 w-full text-xs text-gray-500 hover:text-gray-700 cursor-pointer"
            >
              重置
            </button>
          </div>
        )}
      </div>

      {/* Delete (visible on hover) */}
      <button
        onClick={(e) => {
          e.stopPropagation();
          props.onRemove();
        }}
        class={`shrink-0 w-5 h-5 text-xs rounded cursor-pointer flex items-center justify-center text-red-400 hover:text-red-600 hover:bg-red-50 transition-opacity ${
          props.hovered ? "opacity-100" : "opacity-0"
        }`}
        title="删除图层"
      >
        ✕
      </button>
    </div>
  );
}

export { LayerEditorPanel };
