<template>
  <div class="cpTableColumnEditor">
    <v-dropdown
      v-model:shown="isDropdownVisible"
      :aria-id="ariaId"
      :delay="0"
      placement="bottom-end"
      popper-class="cpTableColumnEditor__dropdown"
      @apply-show="handleDropdownShown"
    >
      <cp-button
        appearance="minimal"
        class="cpTableColumnEditor__trigger"
        :class="triggerDynamicClass"
        is-square
        size="xs"
      >
        <template #leading-icon>
          <cp-icon size="16" type="more-vertical" />
        </template>
      </cp-button>
      <template #popper>
        <div class="cpTableColumnEditor__inner">
          <div class="cpTableColumnEditor__header">
            <cp-input
              ref="searchInputRef"
              v-model="searchQuery"
              class="cpTableColumnEditor__search"
              is-search
              placeholder="Search for a column..."
              size="sm"
            />
          </div>
          <div v-if="hasProtectedColumns" class="cpTableColumnEditor__row">
            <div class="cpTableColumnEditor__heading">Fixed columns</div>
            <div v-for="column in protectedColumns" :key="column.id" class="cpTableColumnEditor__column">
              <span>{{ column.name }}</span>
            </div>
          </div>
          <div class="cpTableColumnEditor__divider" />
          <div class="cpTableColumnEditor__row">
            <div class="cpTableColumnEditor__heading">Shown in table</div>
            <div class="cpTableColumnEditor__column">
              <template v-if="hasFilteredVisibleColumns">
                <cp-checkbox
                  v-for="column in filteredVisibleColumns"
                  :key="column.id"
                  v-model="selectedColumnIds"
                  :checkbox-label="column.name"
                  :checkbox-value="column.id"
                  class="cpTableColumnEditor__checkbox"
                  color="purple"
                  :value="column.id"
                />
              </template>
              <span v-else class="cpTableColumnEditor__empty">No columns found</span>
            </div>
          </div>
          <template v-if="hasHiddenColumns">
            <div class="cpTableColumnEditor__divider" />
            <div class="cpTableColumnEditor__row">
              <div class="cpTableColumnEditor__heading">Hidden in table</div>
              <div class="cpTableColumnEditor__column">
                <cp-checkbox
                  v-for="column in hiddenColumns"
                  :key="column.id"
                  v-model="selectedColumnIds"
                  :checkbox-label="column.name"
                  :checkbox-value="column.id"
                  class="cpTableColumnEditor__checkbox"
                  color="purple"
                  :value="column.id"
                />
              </div>
            </div>
          </template>
        </div>
      </template>
    </v-dropdown>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, useId, useTemplateRef } from 'vue'

import type { CpTableColumnObject } from '@/constants/CpTableColumn'

import CpInput from '@/components/CpInput.vue'

import { focusOnDOMElement } from '@/helpers/dom'

interface Props {
  columns: CpTableColumnObject[]
}

const props = defineProps<Props>()

const ariaId = useId()

const selectedColumnIds = defineModel<string[]>({ required: true })

const isDropdownVisible = ref(false)

const searchQuery = ref('')
const searchInputRef = useTemplateRef<InstanceType<typeof CpInput>>('searchInputRef')

const triggerDynamicClass = computed(() => {
  return {
    'cpTableColumnEditor__trigger--isOpen': isDropdownVisible.value,
  }
})

const protectedColumns = computed(() => {
  const filteredProtectedColumns = props.columns.filter((column) => isColumnProtected(column))

  if (filteredProtectedColumns.length) return filteredProtectedColumns

  const firstColumn = props.columns[0]

  return [firstColumn]
})

const hasProtectedColumns = computed(() => !!protectedColumns.value.length)

const filteredVisibleColumns = computed(() => {
  return props.columns.filter((column) => {
    const isMatchingSearch = column.name.toLowerCase().includes(searchQuery.value.toLowerCase())
    const isProtected = protectedColumns.value.some(({ id }) => id === column.id)
    const conditions = [isMatchingSearch, isColumnSelected(column), !isProtected]

    return conditions.every((condition) => condition)
  })
})

const hasFilteredVisibleColumns = computed(() => !!filteredVisibleColumns.value.length)

const hiddenColumns = computed(() => props.columns.filter((column) => !isColumnSelected(column)))
const hasHiddenColumns = computed(() => !!hiddenColumns.value.length)

const isColumnProtected = (column: CpTableColumnObject) => column.isProtected || false
const isColumnSelected = (column: CpTableColumnObject) => selectedColumnIds.value?.includes(column.id)

const handleDropdownShown = () => {
  const root = searchInputRef.value?.$el
  if (!root || !(root instanceof HTMLElement)) return
  setTimeout(() => focusOnDOMElement(root), 50)
}
</script>

<style lang="scss">
.cpTableColumnEditor {
  padding-bottom: var(--cp-spacing-xs);
  text-align: right;

  &__trigger {
    @extend %u-focus-outline;

    border-radius: var(--cp-radius-md);
    color: var(--cp-text-secondary);

    &--isOpen,
    &:hover,
    &:focus-within {
      background-color: var(--cp-background-primary-hover);
      outline-offset: 0;
      transform: none;
    }
  }

  &__dropdown {
    @include mx.hide-tooltip-arrow;
    @include mx.v-dropdown-transition;
  }

  &__inner {
    display: flex;
    flex-direction: column;
    gap: var(--cp-spacing-md);
    padding-block: var(--cp-spacing-md);
  }

  &__header {
    padding-inline: var(--cp-spacing-lg);
  }

  &__column,
  &__empty {
    font-size: var(--cp-text-size-sm);
  }

  &__column {
    text-transform: capitalize;
  }

  &__heading,
  &__column:not(:has(.cpTableColumnEditor__checkbox)) {
    padding: var(--cp-spacing-sm) var(--cp-spacing-lg);
  }

  &__heading {
    color: var(--cp-text-secondary);
    font-size: var(--cp-text-size-xs);
    line-height: var(--cp-line-height-md);
  }

  &__empty {
    text-transform: initial;
  }

  &__divider {
    height: var(--cp-dimensions-0_25);
    background-color: var(--cp-border-soft);
  }

  &__checkbox {
    padding: var(--cp-spacing-sm) var(--cp-spacing-md);
    color: var(--cp-text-primary);
  }
}
</style>
