<template>
  <UPopover v-model:open="isOpen">
    <UChip
      :ui="{ base: 'z-1 size-3' }"
      :show="hiddenColumnsCount > 0"
      :text="hiddenColumnsCount"
      size="xl"
    >
      <UButton
        variant="subtle"
        color="neutral"
        label="Колонки"
        :icon="appConfig.ui.icons.columns"
      />
    </UChip>

    <template #content>
      <div class="p-3 min-w-64">
        <h3 class="text-sm mb-2 text-muted">
          Настройка колонок:
        </h3>

        <div ref="container">
          <div
            v-for="column in sortedItems"
            v-show="column.label"
            :key="column.id"
            class="flex items-center gap-2 rounded hover:bg-elevated"
          >
            <UIcon
              :name="appConfig.ui.icons.drag"
              class="w-4 h-7 text-dimmed cursor-move shrink-0 handle"
            />

            <UCheckbox
              class="flex-1 py-1"
              :model-value="column.visible"
              :label="column.label"
              :disabled="!column.canHide"
              @update:model-value="toggleColumnVisibility(column.id, $event)"
            />
          </div>
        </div>
      </div>
    </template>
  </UPopover>
</template>

<script setup>
import { getCmsStorageKey, useAppConfig, useRoute } from "#imports";
import { syncRef, useLocalStorage } from "@vueuse/core";
import { useSortable } from "@vueuse/integrations/useSortable";
import { computed, ref, useTemplateRef, watch } from "vue";
const props = defineProps({
  storageKey: { type: String, required: false, default: () => useRoute().name },
  table: { type: Object, required: false }
});
const visibility = defineModel("visibility", { type: Object, ...{ default: {} } });
const storedVisibility = useLocalStorage(getCmsStorageKey(`column-visibility:${props.storageKey}`), visibility.value);
syncRef(storedVisibility, visibility, {
  transform: { ltr: (value) => value }
});
const order = defineModel("order", { type: Array, ...{ default: [] } });
const storedOrder = useLocalStorage(getCmsStorageKey(`column-order:${props.storageKey}`), order.value);
syncRef(storedOrder, order, {
  transform: { ltr: (value) => value }
});
const appConfig = useAppConfig();
const isOpen = ref(false);
const columns = computed(() => {
  if (!props.table) {
    return [];
  }
  return props.table.getAllColumns().map((column) => {
    const label = column.columnDef.meta?.headerLabel ?? (typeof column.columnDef.header === "string" ? column.columnDef.header : void 0);
    return {
      id: column.id,
      label,
      visible: column.getIsVisible(),
      canHide: column.getCanHide(),
      onUpdateChecked: (checked) => toggleColumnVisibility(column.id, checked)
    };
  });
});
const sortedItems = computed(() => {
  const sortOrder = Object.fromEntries(order.value.map((id, index) => [id, index]));
  return columns.value.toSorted((a, b) => sortOrder[a.id] - sortOrder[b.id]);
});
const hiddenColumnsCount = computed(() => {
  return columns.value.filter((column) => !column.visible).length;
});
function toggleColumnVisibility(columnId, visible) {
  visibility.value = { ...visibility.value, [columnId]: !!visible };
}
const containerRef = useTemplateRef("container");
const { start: startSortable, stop: stopSortable } = useSortable(containerRef, order, {
  handle: ".handle",
  animation: 150,
  onUpdate: (e) => {
    const newColumnOrder = order.value.length !== sortedItems.value.length ? sortedItems.value.map((column) => column.id) : [...order.value];
    newColumnOrder.splice(
      e.newIndex,
      0,
      newColumnOrder.splice(e.oldIndex, 1)[0]
    );
    order.value = newColumnOrder;
  }
});
watch(containerRef, (value) => value ? startSortable() : stopSortable());
</script>
