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

export interface LayerRowProps {
  store: DeckStore;
  index: number;
  sortableId: string;
  layer: LayerConfig;
  hovered: boolean;
  onHoverChange: (idx: number | null) => void;
  openDropdown: string | null;
  setOpenDropdown: (val: string | null) => void;
  onUpdateOrientation: (o: "n" | "s" | "e" | "w") => void;
  onUpdateFontSize: (fs?: number) => void;
  onUpdateAlign: (a?: "l" | "c" | "r") => void;
  onSelect: () => void;
  onRemove: () => void;
}

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

const ALIGNS = [
  { value: "" as const, icon: alignCenterIcon },
  { value: "l" as const, icon: alignLeftIcon },
  { value: "c" as const, icon: alignCenterIcon },
  { value: "r" as const, icon: alignRightIcon },
];

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

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

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

export function LayerRow(props: LayerRowProps) {
  const sortable = createSortable(props.sortableId);
  const [dndState] = useDragDropContext()!;
  const [fontOpen, setFontOpen] = createSignal(false);
  let fontRef: HTMLDivElement | undefined;

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

  onMount(() => {
    const h = (e: MouseEvent) => {
      if (fontRef && !fontRef.contains(e.target as Node)) setFontOpen(false);
    };
    document.addEventListener("click", h);
    onCleanup(() => document.removeEventListener("click", h));
  });

  const toggleVisible = () => {
    const fn =
      props.store.state.activeSide === "front"
        ? props.store.actions.toggleFrontLayerVisible
        : props.store.actions.toggleBackLayerVisible;
    fn(props.index);
  };

  return (
    <div
      use:sortable={sortable}
      class={`flex items-center gap-1 py-1.5 px-1 relative group border-b border-gray-100 ${selected() ? "bg-blue-50" : ""}`}
      classList={{
        "opacity-25": sortable.isActiveDraggable,
        "transition-transform":
          !!dndState.active.draggable && !sortable.isActiveDraggable,
      }}
      onMouseEnter={() => props.onHoverChange(props.index)}
      onMouseLeave={() => props.onHoverChange(null)}
    >
      <button
        {...sortable.dragActivators}
        class="cursor-grab text-gray-400 hover:text-gray-600 text-sm px-0.5 select-none shrink-0"
        title="拖动排序"
      >
        ⠿
      </button>

      <button
        onClick={toggleVisible}
        class="shrink-0 text-sm cursor-pointer select-none"
        title={props.layer.visible ? "隐藏" : "显示"}
      >
        {props.layer.visible ? "👁" : "👁‍🗨"}
      </button>

      <span
        class="text-sm flex-1 truncate cursor-pointer hover:text-blue-600 select-none"
        onClick={props.onSelect}
      >
        {props.layer.prop || (props.layer.template ? "(模板)" : "")}
      </span>

      <DropdownButton
        icon={orientChar(props.layer.orientation || "n")}
        visible={props.layer.visible}
        open={props.openDropdown === `orient-${props.index}`}
        onToggle={() =>
          props.setOpenDropdown(
            props.openDropdown === `orient-${props.index}`
              ? null
              : `orient-${props.index}`,
          )
        }
        title="方向"
      >
        <For each={ORIENTATIONS}>
          {(o) => (
            <button
              onClick={() => props.onUpdateOrientation(o.value)}
              class="block w-full text-left px-3 py-1.5 text-sm hover:bg-gray-100 cursor-pointer whitespace-nowrap"
            >
              {o.label}
            </button>
          )}
        </For>
      </DropdownButton>

      <DropdownButton
        icon={
          <img
            src={alignSrc(props.layer.align || "")}
            alt="align"
            class="w-5 h-5 not-prose"
          />
        }
        visible={props.layer.visible}
        open={props.openDropdown === `align-${props.index}`}
        onToggle={() =>
          props.setOpenDropdown(
            props.openDropdown === `align-${props.index}`
              ? null
              : `align-${props.index}`,
          )
        }
        title="对齐"
      >
        <For each={ALIGNS}>
          {(o) => (
            <button
              onClick={() => props.onUpdateAlign(o.value || 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={o.icon} alt="" class="w-4 h-4 not-prose max-w-none" />
            </button>
          )}
        </For>
      </DropdownButton>

      <div class="relative" ref={fontRef}>
        <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) =>
                  props.onUpdateFontSize(
                    e.target.value ? Number(e.target.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}>
                {(p) => (
                  <button
                    onClick={() => props.onUpdateFontSize(p)}
                    class={`px-2 py-1 text-xs rounded cursor-pointer ${(props.layer.fontSize ?? 3) === p ? "bg-blue-500 text-white" : "bg-gray-100 hover:bg-gray-200 text-gray-700"}`}
                  >
                    {p}
                  </button>
                )}
              </For>
            </div>
            <button
              onClick={() => props.onUpdateFontSize(undefined)}
              class="mt-2 w-full text-xs text-gray-500 hover:text-gray-700 cursor-pointer"
            >
              重置
            </button>
          </div>
        )}
      </div>

      <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>
  );
}

function DropdownButton(props: {
  icon: import("solid-js").JSX.Element;
  visible: boolean;
  open: boolean;
  onToggle: () => void;
  title: string;
  children: import("solid-js").JSX.Element;
}) {
  return (
    <div class="relative">
      <button
        onClick={(e) => {
          e.stopPropagation();
          props.onToggle();
        }}
        class={`w-7 h-7 rounded cursor-pointer flex items-center justify-center bg-gray-200 hover:bg-gray-300 ${!props.visible ? "invisible pointer-events-none" : ""}`}
        title={props.title}
      >
        {props.icon}
      </button>
      {props.open && (
        <div
          class="absolute top-full right-0 mt-1 bg-white border border-gray-300 rounded shadow-lg z-10"
          onClick={(e) => e.stopPropagation()}
        >
          {props.children}
        </div>
      )}
    </div>
  );
}
