<script lang="ts" setup>
import type { ColumnType, GalleryType, KanbanType, LookupType } from 'nocodb-sdk'
import { ProjectRoles, UITypes, ViewTypes, isLinksOrLTAR, isSystemColumn } from 'nocodb-sdk'
import Draggable from 'vuedraggable'

import type { SelectProps } from 'ant-design-vue'

const activeView = inject(ActiveViewInj, ref())

const meta = inject(MetaInj, ref())

const reloadViewDataHook = inject(ReloadViewDataHookInj, undefined)!

const { isMobileMode, user } = useGlobal()

const { isUIAllowed } = useRoles()

const isLocked = inject(IsLockedInj, ref(false))

const isPublic = inject(IsPublicInj, ref(false))

const readOnly = inject(ReadonlyInj, ref(false))

const isToolbarIconMode = inject(
  IsToolbarIconMode,
  computed(() => false),
)

const { $e } = useNuxtApp()

const { t } = useI18n()

const { metas, getMeta, getMetaByKey } = useMetas()

const {
  showSystemFields,
  fields,
  filteredFieldList,
  hasViewFieldDataEditPermission,
  searchBasisIdMap,
  numberOfHiddenFields,
  filterQuery,
  showAll,
  hideAll,
  saveOrUpdate,
  metaColumnById,
  loadViewColumns,
  toggleFieldStyles,
  toggleFieldVisibility,
  isLocalMode,
} = useViewColumnsOrThrow()

const { eventBus, isDefaultView, isSqlView, isViewOperationsAllowed } = useSmartsheetStoreOrThrow()

const isFieldsMenuReadOnly = computed(() => {
  return isLocked.value || !isViewOperationsAllowed.value || (isLocalMode.value && hasViewFieldDataEditPermission.value)
})

const isAddingColumnAllowed = computed(() => !readOnly.value && isUIAllowed('fieldAdd') && !isSqlView.value)

const { addUndo, defineViewScope } = useUndoRedo()

const viewStore = useViewsStore()

const { updateViewMeta } = viewStore

const eventBusHandler = async (event: SmartsheetStoreEvents, payload?: any) => {
  if (event === SmartsheetStoreEvents.FIELD_RELOAD) {
    try {
      await loadViewColumns()
    } finally {
      payload?.callback?.()
    }
  } else if (event === SmartsheetStoreEvents.MAPPED_BY_COLUMN_CHANGE) {
    loadViewColumns()
  }
}

eventBus.on(eventBusHandler)

onBeforeUnmount(() => {
  eventBus.off(eventBusHandler)
})

const gridDisplayValueField = computed(() => {
  if (activeView.value?.type !== ViewTypes.GRID && activeView.value?.type !== ViewTypes.CALENDAR) return null

  const pvCol = Object.values(metaColumnById.value)?.find((col) => col?.pv)

  return filteredFieldList.value?.find((field) => field.fk_column_id === pvCol?.id)
})

const localFilteredFieldList = computed(() => {
  return filteredFieldList.value.filter((el) =>
    activeView.value?.type !== ViewTypes.CALENDAR ? el !== gridDisplayValueField.value : true,
  )
})

const onMove = async (_event: { moved: { newIndex: number; oldIndex: number } }, undo = false) => {
  try {
    // todo : sync with server
    if (!fields.value) return

    if (!undo) {
      addUndo({
        undo: {
          fn: () => {
            if (!fields.value) return
            const temp = fields.value[_event.moved.newIndex]
            fields.value[_event.moved.newIndex] = fields.value[_event.moved.oldIndex]
            fields.value[_event.moved.oldIndex] = temp
            onMove(
              {
                moved: {
                  newIndex: _event.moved.oldIndex,
                  oldIndex: _event.moved.newIndex,
                },
              },
              true,
            )
          },
          args: [],
        },
        redo: {
          fn: () => {
            if (!fields.value) return
            const temp = fields.value[_event.moved.oldIndex]
            fields.value[_event.moved.oldIndex] = fields.value[_event.moved.newIndex]
            fields.value[_event.moved.newIndex] = temp
            onMove(_event, true)
          },
          args: [],
        },
        scope: defineViewScope({ view: activeView.value }),
      })
    }

    if (fields.value.length < 2) return

    const movedField = fields.value[_event.moved.newIndex]
    if (!movedField) return
    let newOrder

    if (_event.moved.newIndex === 0) {
      // Moving to first position
      const nextField = fields.value[1]
      newOrder = nextField.order / 2 // Half of next field's order
    } else if (_event.moved.newIndex === fields.value.length - 1) {
      // Moving to last position
      const prevField = fields.value[fields.value.length - 2]
      newOrder = prevField.order + 1000 // Add buffer to previous field's order
    } else {
      // Moving somewhere in the middle
      const prevField = fields.value[_event.moved.newIndex - 1]
      const nextField = fields.value[_event.moved.newIndex + 1]
      newOrder = (prevField.order + nextField.order) / 2 // Average between neighbors
    }

    // Update only the moved field
    movedField.order = newOrder
    await saveOrUpdate(movedField, _event.moved.newIndex, true, !!isDefaultView.value)

    await loadViewColumns()
    reloadViewDataHook.trigger()
    $e('a:fields:reorder')
  } catch (e) {
    message.error(await extractSdkResponseErrorMsg(e))
  }
}

const coverOptions = ref<SelectProps['options']>([])

const updateCoverImage = async (val?: string | null) => {
  if (
    (activeView.value?.type === ViewTypes.GALLERY ||
      activeView.value?.type === ViewTypes.KANBAN ||
      activeView.value?.type === ViewTypes.CALENDAR) &&
    activeView.value?.id &&
    activeView.value?.view
  ) {
    await updateViewMeta(activeView.value?.id, activeView.value?.type, {
      fk_cover_image_col_id: val,
    })

    // Load data only if the view column is hidden to fetch cover image column data in records.
    if (val && !fields.value?.find((f) => f.fk_column_id === val)?.show) {
      await reloadViewDataHook?.trigger({
        shouldShowLoading: false,
      })
    }
  }
}

const coverImageColumnId = computed({
  get: () => {
    const fk_cover_image_col_id =
      (activeView.value?.type === ViewTypes.GALLERY || activeView.value?.type === ViewTypes.KANBAN) && activeView.value?.view
        ? (activeView.value?.view as GalleryType | KanbanType).fk_cover_image_col_id
        : undefined

    // check if `fk_cover_image_col_id` is in `coverOptions`
    // e.g. in share view, users may not share the cover image column
    if (coverOptions.value?.find((o) => o.value === fk_cover_image_col_id)) return fk_cover_image_col_id
    // set to `No Image` if fk_cover_image_col_id is null else undefiend (This will help to change value to no image for user)
    return fk_cover_image_col_id === null ? null : undefined
  },
  set: async (val) => {
    if (val !== coverImageColumnId.value) {
      addUndo({
        undo: {
          fn: await updateCoverImage,
          args: [coverImageColumnId.value],
        },
        redo: {
          fn: await updateCoverImage,
          args: [val],
        },
        scope: defineViewScope({ view: activeView.value }),
      })

      await updateCoverImage(val)
    }
  },
})

const updateCoverImageObjectFit = async (val: string) => {
  if (
    ![ViewTypes.GALLERY, ViewTypes.KANBAN].includes(activeView.value?.type as ViewTypes) ||
    !activeView.value?.id ||
    !activeView.value?.view
  ) {
    return
  }

  const payload = {
    ...parseProp((activeView.value?.view as GalleryType | KanbanType)?.meta),
    fk_cover_image_object_fit: val,
  }

  await updateViewMeta(activeView.value?.id, activeView.value?.type, {
    meta: payload,
  })
}

const coverImageObjectFitOptions = [
  { value: CoverImageObjectFit.FIT, label: t('labels.fitImage') },
  { value: CoverImageObjectFit.COVER, label: t('labels.coverImageArea') },
]

const coverImageObjectFitDropdown = ref<{
  isOpen: boolean
  isSaving: keyof typeof CoverImageObjectFit | null
}>({
  isOpen: false,
  isSaving: null,
})

const coverImageObjectFit = computed({
  get: () => {
    return [ViewTypes.GALLERY, ViewTypes.KANBAN].includes(activeView.value?.type as ViewTypes) && activeView.value?.view
      ? parseProp(activeView.value?.view?.meta)?.fk_cover_image_object_fit || CoverImageObjectFit.FIT
      : undefined
  },
  set: async (val) => {
    if (val !== coverImageObjectFit.value) {
      coverImageObjectFitDropdown.value.isSaving = val

      addUndo({
        undo: {
          fn: updateCoverImageObjectFit,
          args: [coverImageObjectFit.value],
        },
        redo: {
          fn: updateCoverImageObjectFit,
          args: [val],
        },
        scope: defineViewScope({ view: activeView.value }),
      })

      await updateCoverImageObjectFit(val)
    }
    coverImageObjectFitDropdown.value.isSaving = null
    coverImageObjectFitDropdown.value.isOpen = false
  },
})

const onShowAll = async () => {
  addUndo({
    undo: {
      fn: async () => {
        await hideAll()
      },
      args: [],
    },
    redo: {
      fn: async () => {
        await showAll()
      },
      args: [],
    },
    scope: defineViewScope({ view: activeView.value }),
  })
  await showAll()
}

const onHideAll = async () => {
  addUndo({
    undo: {
      fn: async () => {
        await showAll()
      },
      args: [],
    },
    redo: {
      fn: async () => {
        await hideAll()
      },
      args: [],
    },
    scope: defineViewScope({ view: activeView.value }),
  })
  await hideAll()
}

const visibleFields = computed(
  () =>
    fields.value?.filter((field: Field) => {
      if (!field.initialShow && isLocalMode.value && !hasViewFieldDataEditPermission.value) {
        return false
      }

      if (metaColumnById?.value?.[field.fk_column_id!]?.pv) {
        return false
      }

      // hide system columns if not enabled
      if (!showSystemFields.value && isSystemColumn(metaColumnById?.value?.[field.fk_column_id!])) {
        return false
      }

      return true
    }) || [],
)

const isLoadingShowAllColumns = ref(false)

const isDisabledShowAllColumns = computed(() => {
  return (
    !searchCompare(
      fields.value?.map((f) => f.title),
      filterQuery.value,
    ) || isFieldsMenuReadOnly.value
  )
})

const showAllColumns = computed({
  get: () => {
    return visibleFields.value?.every((field) => field?.show)
  },
  set: async (val) => {
    isLoadingShowAllColumns.value = true
    try {
      if (val) {
        await onShowAll()
      } else {
        await onHideAll()
      }
    } finally {
      isLoadingShowAllColumns.value = false
    }
  },
})

const open = ref(false)

const showSystemField = computed({
  get: () => {
    return showSystemFields.value
  },
  set: (val) => {
    addUndo({
      undo: {
        fn: (v: boolean) => {
          showSystemFields.value = !v
        },
        args: [val],
      },
      redo: {
        fn: (v: boolean) => {
          showSystemFields.value = v
        },
        args: [val],
      },
      scope: defineViewScope({ view: activeView.value }),
    })
    showSystemFields.value = val
  },
})

const isDragging = ref<boolean>(false)

const fieldsMenuSearchRef = ref<HTMLInputElement>()

watch(open, (value) => {
  if (!value) return

  filterQuery.value = ''
  setTimeout(() => {
    fieldsMenuSearchRef.value?.focus()
  }, 100)
})

watch(
  fields,
  async (newValue) => {
    if (!newValue || isPublic.value || ![ViewTypes.GALLERY, ViewTypes.KANBAN].includes(activeView.value?.type as ViewTypes))
      return

    const filterFields =
      newValue
        .filter((el) => el.fk_column_id && metaColumnById.value[el.fk_column_id]?.uidt === UITypes.Attachment)
        .map((field) => {
          return {
            value: field.fk_column_id,
            label: field.title,
          }
        }) ?? []

    coverOptions.value = [{ value: null, label: t('labels.noImage') }, ...filterFields]

    const lookupColumns = newValue
      .filter((f) => f.fk_column_id && metaColumnById.value[f.fk_column_id]?.uidt === UITypes.Lookup)
      .map((f) => metaColumnById.value[f.fk_column_id!])

    const attLookupColumnIds: Set<string> = new Set()

    const loadLookupMeta = async (originalCol: ColumnType, column: ColumnType, metaId?: string): Promise<void> => {
      const relationColumn =
        metaId || meta.value?.id
          ? getMetaByKey(meta.value?.base_id, metaId || meta.value?.id)?.columns?.find(
              (c: ColumnType) => c.id === (column?.colOptions as LookupType)?.fk_relation_column_id,
            )
          : undefined

      if (relationColumn?.colOptions?.fk_related_model_id) {
        const relatedBaseId = (relationColumn.colOptions as any)?.fk_related_base_id || meta.value?.base_id
        await getMeta(relatedBaseId as string, relationColumn.colOptions.fk_related_model_id!)

        const lookupColumn = getMetaByKey(relatedBaseId, relationColumn.colOptions.fk_related_model_id)?.columns?.find(
          (c: any) => c.id === (column?.colOptions as LookupType)?.fk_lookup_column_id,
        ) as ColumnType | undefined

        if (lookupColumn && isAttachment(lookupColumn)) {
          attLookupColumnIds.add(originalCol.id)
        } else if (lookupColumn && lookupColumn?.uidt === UITypes.Lookup) {
          await loadLookupMeta(originalCol, lookupColumn, relationColumn.colOptions.fk_related_model_id)
        }
      }
    }

    await Promise.allSettled(lookupColumns.map((col) => loadLookupMeta(col, col)))

    const lookupAttColumns = lookupColumns
      .filter((column) => attLookupColumnIds.has(column?.id))
      .map((c) => {
        return {
          value: c.id,
          label: c.title,
        }
      })

    coverOptions.value = [...coverOptions.value, ...lookupAttColumns]
  },
  {
    immediate: true,
  },
)

const addColumnDropdown = ref(false)

const openSubmenusCount = ref(0)
const lookupDropdownsTickle = ref(0)

function scrollToLatestField() {
  setTimeout(() => {
    document.querySelector('.nc-fields-menu-item:last-child')?.scrollIntoView({ behavior: 'smooth' })
  }, 500)
}

const showAddLookupDropdown = (field: Field) => {
  if (!field.fk_column_id) return false

  return !!(isAddingColumnAllowed.value && !isLocalMode.value && isLinksOrLTAR(meta.value?.columnsById?.[field.fk_column_id]))
}

function conditionalToggleFieldVisibility(field: Field) {
  if (showAddLookupDropdown(field) || isFieldsMenuReadOnly.value) {
    return
  }

  // For editor role we just have to show hidden field without giving access to change field visibility
  if (!field.initialShow && isLocalMode.value && hasViewFieldDataEditPermission.value) {
    return
  }

  field.show = !field.show
  toggleFieldVisibility(field.show, field)
}

function handleFieldVisibilityClick(field: Field) {
  if (isLinksOrLTAR(meta.value?.columnsById?.[field.fk_column_id!])) {
    field.show = !field.show
    toggleFieldVisibility(field.show, field)
  }
}

function onColumnSubmitted() {
  message.success(t('msg.toast.createField'))
  addColumnDropdown.value = false
  scrollToLatestField()
}

const editOrAddProviderRef = ref()

const onFieldsMenuDropdownVisibilityChange = (value: boolean) => {
  if (!value && addColumnDropdown.value) {
    open.value = true
  }
}

const onAddColumnDropdownVisibilityChange = () => {
  addColumnDropdown.value = true

  if (editOrAddProviderRef.value && !editOrAddProviderRef.value?.shouldKeepModalOpen?.()) {
    addColumnDropdown.value = false
  }
}
</script>

<template>
  <NcDropdown
    v-model:visible="open"
    :trigger="['click']"
    class="!xs:hidden"
    overlay-class-name="nc-dropdown-fields-menu nc-toolbar-dropdown overflow-hidden"
    :auto-close="openSubmenusCount === 0"
    @visible-change="onFieldsMenuDropdownVisibilityChange"
  >
    <NcTooltip :disabled="!isMobileMode && !isToolbarIconMode" :class="{ 'nc-active-btn': numberOfHiddenFields }">
      <template #title>
        {{
          activeView?.type === ViewTypes.KANBAN || activeView?.type === ViewTypes.GALLERY
            ? $t('title.editCards')
            : $t('objects.fields')
        }}
      </template>

      <NcButton
        v-e="['c:fields']"
        class="nc-fields-menu-btn nc-toolbar-btn !h-7 !border-0"
        size="small"
        type="secondary"
        :show-as-disabled="isFieldsMenuReadOnly"
      >
        <div class="flex items-center gap-1">
          <div class="flex items-center gap-2 min-h-5">
            <GeneralIcon
              v-if="activeView?.type === ViewTypes.KANBAN || activeView?.type === ViewTypes.GALLERY"
              class="h-4 w-4"
              icon="creditCard"
            />
            <component :is="iconMap.fields" v-else class="h-4 w-4" />

            <!-- Fields -->
            <span v-if="!isMobileMode && !isToolbarIconMode" class="text-capitalize !text-small1 font-medium">
              <template v-if="activeView?.type === ViewTypes.KANBAN || activeView?.type === ViewTypes.GALLERY">
                {{ $t('title.editCards') }}
              </template>
              <template v-else>
                {{ $t('objects.fields') }}
              </template>
            </span>
          </div>
          <span v-if="numberOfHiddenFields" class="bg-nc-bg-brand text-nc-content-brand nc-toolbar-btn-chip">
            {{ numberOfHiddenFields }}
          </span>
        </div>
      </NcButton>
    </NcTooltip>

    <template #overlay>
      <div class="w-[320px] rounded-lg nc-table-toolbar-menu" data-testid="nc-fields-menu" @click.stop>
        <div
          v-if="!isPublic && (activeView?.type === ViewTypes.GALLERY || activeView?.type === ViewTypes.KANBAN)"
          class="flex items-center gap-2 p-2 w-80 border-b-1 border-nc-border-gray-light"
        >
          <div class="pl-2 flex text-sm select-none text-nc-content-gray-subtle2">{{ $t('labels.coverImageField') }}</div>

          <div
            class="flex-1 nc-dropdown-cover-image-wrapper flex items-stretch border-1 border-nc-border-gray-medium rounded-lg transition-all duration-0.3s max-w-[206px]"
            :class="{
              'nc-disabled': isFieldsMenuReadOnly,
            }"
          >
            <a-select
              v-model:value="coverImageColumnId"
              class="flex-1 max-w-[calc(100%_-_33px)]"
              dropdown-class-name="nc-dropdown-cover-image !rounded-lg"
              :bordered="false"
              :disabled="isFieldsMenuReadOnly"
              @click.stop
            >
              <template #suffixIcon><GeneralIcon class="text-nc-content-gray-subtle" icon="arrowDown" /></template>

              <a-select-option v-for="option of coverOptions" :key="option.value" :value="option.value">
                <div class="w-full flex gap-2 items-center justify-between max-w-[400px]">
                  <div
                    class="flex-1 flex items-center gap-1"
                    :class="{
                      'max-w-[calc(100%_-_20px)]': coverImageColumnId === option.value,
                      'max-w-full': coverImageColumnId !== option.value,
                    }"
                  >
                    <SmartsheetHeaderIcon
                      v-if="option.value && metaColumnById[option.value]"
                      :column="metaColumnById[option.value]"
                      class="!w-3.5 !h-3.5 !ml-0"
                      color="text-nc-content-gray-subtle"
                    />

                    <NcTooltip class="flex-1 max-w-[calc(100%_-_20px)] truncate" show-on-truncate-only>
                      <template #title>
                        {{ option.label }}
                      </template>
                      <template #default>{{ option.label }}</template>
                    </NcTooltip>
                  </div>
                  <GeneralIcon
                    v-if="coverImageColumnId === option.value"
                    id="nc-selected-item-icon"
                    icon="check"
                    class="flex-none text-nc-content-brand w-4 h-4"
                  />
                </div>
              </a-select-option>
            </a-select>
            <NcDropdown
              v-if="coverImageObjectFit"
              v-model:visible="coverImageObjectFitDropdown.isOpen"
              :disabled="isFieldsMenuReadOnly"
              placement="bottomRight"
            >
              <button
                class="flex items-center px-2 border-l-1 border-nc-border-gray-medium disabled:(cursor-not-allowed opacity-80)"
                :disabled="isFieldsMenuReadOnly"
              >
                <GeneralIcon
                  icon="settings"
                  class="h-4 w-4"
                  :class="{
                    '!text-nc-content-brand': coverImageObjectFitDropdown.isOpen,
                  }"
                />
              </button>
              <template #overlay>
                <NcMenu class="nc-cover-image-object-fit-dropdown-menu min-w-[168px]">
                  <NcMenuItem
                    v-for="option in coverImageObjectFitOptions"
                    :key="option.value"
                    class="!children:w-full"
                    @click.stop="coverImageObjectFit = option.value"
                  >
                    <span>
                      {{ option.label }}
                    </span>

                    <GeneralLoader
                      v-if="option.value === coverImageObjectFitDropdown.isSaving"
                      size="regular"
                      class="flex-none"
                    />

                    <GeneralIcon
                      v-else-if="option.value === coverImageObjectFit"
                      icon="check"
                      class="flex-none text-nc-content-brand w-4 h-4"
                    />
                  </NcMenuItem>
                </NcMenu>
              </template>
            </NcDropdown>
          </div>
        </div>

        <div class="py-2" @click.stop>
          <a-input
            ref="fieldsMenuSearchRef"
            v-model:value="filterQuery"
            :placeholder="$t('placeholder.searchFields')"
            class="nc-toolbar-dropdown-search-field-input !border-none !shadow-none !h-8"
          >
            <template #prefix> <GeneralIcon icon="search" class="nc-search-icon h-3.5 w-3.5 mr-1 ml-2" /> </template>
            <template #suffix>
              <div class="pl-2 flex items-center gap-2">
                <NcSwitch
                  v-model:checked="showAllColumns"
                  :disabled="isDisabledShowAllColumns"
                  :loading="isLoadingShowAllColumns"
                  size="xsmall"
                  class="!mr-1 nc-fields-toggle-show-all-fields"
                />
              </div>
            </template>
          </a-input>
        </div>

        <div
          class="flex flex-col nc-scrollbar-thin max-h-[315px] min-h-[240px] p-2 overflow-y-auto border-t-1 border-nc-border-gray-medium"
          style="scrollbar-gutter: stable !important"
        >
          <div class="nc-fields-list">
            <div
              v-if="!localFilteredFieldList.length"
              class="px-2 py-6 text-nc-content-gray-muted flex flex-col items-center gap-6 text-center"
            >
              <img
                src="~assets/img/placeholder/no-search-result-found.png"
                class="!w-[164px] flex-none"
                alt="No search results found"
              />

              {{ $t('title.noResultsMatchedYourSearch') }}
            </div>
            <Draggable
              v-bind="getDraggableAutoScrollOptions({ scrollSensitivity: 40 })"
              v-model="fields"
              item-key="id"
              ghost-class="nc-fields-menu-items-ghost"
              :disabled="isFieldsMenuReadOnly"
              @change="onMove($event)"
              @start="isDragging = true"
              @end="isDragging = false"
            >
              <template #item="{ element: field }">
                <div
                  v-if="localFilteredFieldList.includes(field)"
                  :key="field.id"
                  :data-testid="`nc-fields-menu-${field.title}`"
                  class="nc-fields-menu-item pl-2 flex flex-row items-center rounded-md"
                  :class="{
                    'hover:bg-nc-bg-gray-light': !isFieldsMenuReadOnly,
                  }"
                  @click.stop
                >
                  <component
                    :is="iconMap.drag"
                    class="!h-3.75 text-nc-content-gray-subtle2 mr-1"
                    :class="{
                      'cursor-not-allowed': isFieldsMenuReadOnly,
                      'cursor-move': !isFieldsMenuReadOnly,
                    }"
                  />
                  <SmartsheetToolbarAddLookupsDropdown
                    v-if="metas"
                    :key="lookupDropdownsTickle"
                    :column="meta?.columnsById?.[field.fk_column_id!]!"
                    :disabled="!showAddLookupDropdown(field)"
                    @created="lookupDropdownsTickle++"
                    @update:is-opened="openSubmenusCount += $event === true ? 1 : -1"
                  >
                    <template #default="{ isOpened }">
                      <div
                        v-e="['a:fields:show-hide']"
                        class="flex flex-row items-center w-full truncate ml-1 py-[5px] pr-2"
                        :class="{
                          'cursor-pointer': !isFieldsMenuReadOnly,
                          'is-opened-add-lookup': isOpened,
                        }"
                        @click="conditionalToggleFieldVisibility(field)"
                      >
                        <SmartsheetHeaderIcon
                          v-if="field.fk_column_id && metaColumnById[field.fk_column_id]"
                          :column="metaColumnById[field.fk_column_id]"
                          class="!w-3.5 !h-3.5"
                          color="text-nc-content-gray-subtle2"
                          @click.stop
                        />

                        <NcTooltip
                          class="pl-1 truncate"
                          :class="{
                            'mr-3 flex-1': !showAddLookupDropdown(field) && !searchBasisIdMap[field.fk_column_id!],
                          }"
                          show-on-truncate-only
                          :disabled="isDragging"
                        >
                          <template #title>
                            {{ field.title }}
                          </template>
                          <template #default>
                            {{ field.title }}
                          </template>
                        </NcTooltip>
                        <div v-if="searchBasisIdMap[field.fk_column_id!]" class="flex-1 flex ml-1 mr-3">
                          <NcTooltip :title="searchBasisIdMap[field.fk_column_id!]" class="flex cursor-help">
                            <GeneralIcon icon="info" class="h-3.5 w-3.5 opacity-80 text-nc-content-gray-muted" />
                          </NcTooltip>
                        </div>
                        <div v-if="showAddLookupDropdown(field)" class="flex-1 flex mr-3">
                          <NcTooltip :disabled="isOpened">
                            <template #title>
                              {{ $t('tooltip.addLookupFields') }}
                            </template>

                            <div class="px-1 text-nc-content-gray-subtle2">
                              <GeneralIcon icon="chevronRight" class="flex-none !w-3.5 !h-3.5" />
                            </div>
                          </NcTooltip>
                        </div>

                        <div v-if="activeView.type === ViewTypes.CALENDAR" class="flex mr-2">
                          <NcButton
                            :class="{
                              '!text-nc-content-brand !bg-nc-bg-brand hover:!bg-nc-brand-100 active:!bg-nc-brand-200': field.bold,
                              '!rounded-r-none': field.italic,
                            }"
                            class="!w-5 !h-5 hover:!bg-nc-bg-gray-medium active:!bg-nc-bg-gray-dark relative"
                            size="xsmall"
                            type="text"
                            :disabled="isFieldsMenuReadOnly"
                            @click.stop="toggleFieldStyles(field, 'bold', !field.bold)"
                          >
                            <component :is="iconMap.bold" class="!w-3.5 !h-3.5" />
                            <div
                              v-if="field.bold"
                              class="bg-primary w-1.25 h-1.25 rounded-full absolute top-0.25 right-0.5 border-1 border-base-white"
                            />
                          </NcButton>
                          <NcButton
                            :class="{
                              '!text-nc-content-brand !bg-nc-bg-brand hover:!bg-nc-brand-100 active:!bg-nc-brand-200':
                                field.italic,
                              '!rounded-l-none': field.bold,
                              '!rounded-r-none': field.underline,
                            }"
                            class="!w-5 !h-5 hover:!bg-nc-bg-gray-medium active:!bg-nc-bg-gray-dark relative"
                            size="xsmall"
                            type="text"
                            :disabled="isFieldsMenuReadOnly"
                            @click.stop="toggleFieldStyles(field, 'italic', !field.italic)"
                          >
                            <component :is="iconMap.italic" class="!w-3.5 !h-3.5" />
                            <div
                              v-if="field.italic"
                              class="bg-primary w-1.25 h-1.25 rounded-full absolute top-0.25 right-0.5 border-1 border-base-white"
                            />
                          </NcButton>
                          <NcButton
                            :class="{
                              '!text-nc-content-brand !bg-nc-bg-brand hover:!bg-nc-brand-100 active:!bg-nc-brand-200':
                                field.underline,
                              '!rounded-l-none': field.italic,
                            }"
                            class="!w-5 !h-5 hover:!bg-nc-bg-gray-medium active:!bg-nc-bg-gray-dark relative"
                            size="xsmall"
                            type="text"
                            :disabled="isFieldsMenuReadOnly"
                            @click.stop="toggleFieldStyles(field, 'underline', !field.underline)"
                          >
                            <component :is="iconMap.underline" class="!w-3.5 !h-3.5" />
                            <div
                              v-if="field.underline"
                              class="bg-primary w-1.25 h-1.25 rounded-full absolute top-0.25 right-0.5 border-1 border-base-white"
                            />
                          </NcButton>
                        </div>

                        <span class="flex children:flex-none" @click.stop="conditionalToggleFieldVisibility(field)">
                          <NcSwitch
                            :checked="field.show"
                            :disabled="field.isViewEssentialField || isFieldsMenuReadOnly || isLoadingShowAllColumns"
                            size="xxsmall"
                            @change="$e('a:fields:show-hide')"
                            @click="handleFieldVisibilityClick(field)"
                          />
                        </span>
                      </div>
                    </template>
                  </SmartsheetToolbarAddLookupsDropdown>

                  <div class="flex-1" />
                </div>
              </template>
            </Draggable>
          </div>
        </div>

        <div
          v-if="!isLocalMode && !filterQuery"
          class="flex px-2 gap-1 py-2 border-t-1 justify-between border-nc-border-gray-medium"
        >
          <NcButton
            class="nc-fields-show-system-fields !px-2 !font-semibold"
            size="small"
            type="text"
            :disabled="isFieldsMenuReadOnly"
            @click="showSystemField = !showSystemField"
          >
            <GeneralIcon :icon="showSystemField ? 'eyeSlash' : 'eye'" class="!w-4 !h-4 mr-2" />
            <span> {{ $t('title.systemFields') }} </span>
          </NcButton>
          <NcDropdown
            v-if="isAddingColumnAllowed"
            v-model:visible="addColumnDropdown"
            :trigger="['click']"
            overlay-class-name="nc-dropdown-add-column !bg-transparent !border-none !shadow-none !rounded-2xl"
            placement="right"
            :align="{
              offset: [9, -15],
            }"
            @visible-change="onAddColumnDropdownVisibilityChange"
          >
            <NcButton text-color="primary" class="nc-fields-add-new-field !font-semibold !px-2" size="small" type="text">
              <GeneralIcon icon="ncPlus" class="!w-4 !h-4 mr-1" />
              <span>{{ t('general.new') }} {{ t('objects.field') }}</span>
            </NcButton>
            <template #overlay>
              <div class="nc-edit-or-add-provider-wrapper">
                <LazySmartsheetColumnEditOrAddProvider
                  v-if="addColumnDropdown"
                  ref="editOrAddProviderRef"
                  @submit="onColumnSubmitted()"
                  @cancel="addColumnDropdown = false"
                  @click.stop
                  @keydown.stop
                />
              </div>
            </template>
          </NcDropdown>
        </div>

        <GeneralLockedViewFooter
          v-if="isFieldsMenuReadOnly"
          :show-icon="isLocked"
          :show-unlock-button="isLocked"
          @on-open="open = false"
        >
          <template v-if="!isLocked" #title> You don’t have permission to edit this view. </template>
        </GeneralLockedViewFooter>
      </div>
    </template>
  </NcDropdown>
</template>

<style lang="scss" scoped>
:deep(.nc-toolbar-dropdown-search-field-input .ant-input::placeholder) {
  @apply text-nc-content-gray-muted;
}
:deep(.xxsmall) {
  @apply !min-w-0;
}

.nc-fields-menu-item {
  &:has(.is-opened-add-lookup) {
    @apply bg-nc-bg-gray-light;
  }
}

.nc-fields-menu-items-ghost {
  @apply bg-nc-bg-gray-extralight;
}

.nc-cover-image-object-fit-dropdown-menu {
  :deep(.nc-menu-item-inner) {
    @apply !w-full flex items-center justify-between;
  }
}
.nc-dropdown-cover-image-wrapper {
  @apply h-8;

  &:not(.nc-disabled):not(:focus-within) {
    @apply shadow-default hover:shadow-hover;
  }
  &:not(.nc-disabled):focus-within {
    @apply shadow-selected border-nc-border-brand;
  }
}

:deep(.ant-input-affix-wrapper) {
  &:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-focused):not(:focus) {
    @apply shadow-default hover:(shadow-hover border-nc-border-gray-medium);
  }
  &.ant-input-affix-wrapper-focused,
  &:focus {
    @apply border-nc-border-brand shadow-selected;
  }
}
</style>
