<!-- Селекты фильтров моделей с выпадающими слайдерами -->
<template>
  <div class="filter-selects">
    <template
      v-for="(item, index) in mainFilters"
      :key="`filter-selects-${index}`"
    >
      <div
        v-if="item.kind==='select'"
        :class="{'_from-sm': !desktopOnlyFilters.includes(item.name)}"
        class="filter-selects__wrapper"
      >
        <!-- Прозрачный select -->
        <select
          v-model="selectValues[item.name]"
          :name="item.name"
          :aria-label="item.title"
          class="filter-selects__select-hidden"
          @change="() => onChange(item.name)"
        >
          <template
            v-for="(option, subIndex) in item.options"
            :key="`s-filters-main-option-${index}${subIndex}`"
          >
            <hr v-if="option.name === 'unspecified' && item.options.length > 1">
            <option :value="option.name">
              {{ `${capitalize(option.title)} (${option.quantity})` }}
            </option>
          </template>
        </select>

        <UiBtn
          :class="{'--active-select': isActive(item.name)}"
          class="filter-selects__select-button"
          size="s"
          theme="secondary"
        >
          {{ getSelectLabel(item) }}
          <UiIcon
            name="angle-down"
            size="16"
          />
        </UiBtn>
      </div>

      <div
        v-if="item.kind==='range'"
        :ref="el => sliderRefs[index] = el"
        :class="{'_from-sm': !desktopOnlyFilters.includes(item.name)}"
        class="filter-selects__wrapper"
      >
        <UiBtn
          :class="{'--active-select': isActive(item.name)}"
          class="filter-selects__select-button"
          size="s"
          theme="secondary"
          @click="toggleSlider(item.name)"
        >
          {{ item.title }}
          <UiIcon
            name="angle-down"
            size="16"
          />
        </UiBtn>
        <ClientOnly>
          <UiPopup
            v-if="isMobile && popupShow && activeSliderName === item.name"
            v-model="popupShow"
            sheet
          >
            <template #title>{{ item.title }}</template>
            <div class="filter-selects__slider-popup">
              <FilterSlider
                :key="item.name"
                :item="item"
                :group-name="item.group.name"
                :index="index"
                class="filter-selects__slider"
              />
              <UiBtn
                wide
                theme="primary"
                @click="() => popupShow = false"
              >{{ $t('show_results') }}
              </UiBtn>
            </div>
          </UiPopup>
          <template v-else-if="!isMobile">
            <div
              v-show="activeSliderName === item.name"
              :class="sliderEdgeClass[index]"
              class="filter-selects__slider-wrapper"
            >
              <FilterSlider
                :item="item"
                :group-name="item.group.name"
                :index="index"
                class="filter-selects__slider"
              />
            </div>
          </template>
        </ClientOnly>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import type { IModelFilter } from '../../types';
import { onClickOutside } from '@vueuse/core';
import { convertString, checkDeviceWidth } from '../../runtime';
import { CSS_BREAKPOINTS } from '../../config/css-breakpoints';

const props = defineProps<{
  filters: IModelFilter[]
}>();

const route = useRoute();
const router = useRouter();

const desktopOnlyFilters = ['guy_type', 'body_build', 'ethnicity'];

const mainFilters = computed(() => {
  return props.filters.filter(item => item.group.name === 'quick');
});

const selectItems = computed(() => mainFilters.value.filter(item => item.kind === 'select'));

const selectValues = ref<Record<string, string>>({});
const sliderRefs = ref<(HTMLDivElement | null)[]>([]);

function getSelectValue(name: string, query: Record<string, any>) {
  const item = selectItems.value.find(i => i.name === name);
  if (!item) return '';
  const value = query[`filter_${name}`] as string | undefined;
  return value ?? item.options[0]?.name ?? '';
}

onMounted(() => {
  selectItems.value.forEach(item => {
    selectValues.value[item.name] = getSelectValue(item.name, route.query);
  });
});

// Проверка, активен ли фильтр
function isActive(name: string) {
  const baseName = name.replace(/_(from|to)$/, '');
  return Object.keys(route.query).some(key => key.startsWith(`filter_${baseName}`));
}

// Хендлер изменения select
function onChange(name: string) {
  const val = selectValues.value[name];
  const query = { ...route.query };

  if (!val || val === 'all') {
    delete query[`filter_${name}`];
    selectValues.value[name] = getSelectValue(name, query);
  } else {
    query[`filter_${name}`] = val;
  }

  router.replace({ query });
}

// Активный слайдер
const activeSliderName = ref<null | string>(null);
const popupShow = ref(false);

// Открытие / закрытие слайдера по кнопке
function toggleSlider(name: string) {
  if (activeSliderName.value === name) {
    activeSliderName.value = null;
    popupShow.value = false;
  } else {
    activeSliderName.value = name;
    popupShow.value = true;
  }
}

// Следим за активным слайдером и навешиваем onClickOutside
watch(activeSliderName, (newName) => {
  if (!newName) return;
  const index = mainFilters.value.findIndex(f => f.name === newName);
  if (index !== -1 && sliderRefs.value[ index ]) {
    const cleanup = onClickOutside(sliderRefs.value[ index ]!, () => {
      activeSliderName.value = null;
      cleanup();
    });
  }
});

const { isMobile } = checkDeviceWidth(CSS_BREAKPOINTS);

const sliderEdgeClass = ref<Record<number, string>>({});

// Функция проверки позиции слайдера
function checkSliderEdge(index: number) {
  nextTick(() => {
    requestAnimationFrame(() => {
      const slider = sliderRefs.value[ index ];
      if (!slider) return;

      const rect = slider.getBoundingClientRect();
      const threshold = 100; // px от края экрана

      if (rect.left < threshold) {
        sliderEdgeClass.value[ index ] = '--left';
      } else if ((import.meta.client ? window.innerWidth : 0) - rect.right < threshold) {
        sliderEdgeClass.value[ index ] = '--right';
      } else {
        sliderEdgeClass.value[ index ] = '';
      }
    });
  });
}

// Смотрим за открытием слайдера
watch(activeSliderName, (name) => {
  if (!name) return;
  const index = mainFilters.value.findIndex(f => f.name === name);
  if (index !== -1) {
    checkSliderEdge(index);
  }
});

// Смотрим за изменением filters
watch(
    () => props.filters.length,
    () => {
      if (!activeSliderName.value) return;
      const index = mainFilters.value.findIndex(f => f.name === activeSliderName.value);
      if (index !== -1) {
        nextTick(() => {
          checkSliderEdge(index);
        });
      }
    },
);

let resizeHandler: (() => void) | null = null;
onMounted(() => {
  resizeHandler = () => {
    if (!activeSliderName.value) return;
    const index = mainFilters.value.findIndex(f => f.name === activeSliderName.value);
    if (index !== -1) {
      checkSliderEdge(index);
    }
  };
  window.addEventListener('resize', resizeHandler);
});
onBeforeUnmount(() => {
  if (resizeHandler) {
    window.removeEventListener('resize', resizeHandler);
  }
});

watch(
  () => route.query,
  (query) => {
    selectItems.value.forEach(item => {
      selectValues.value[item.name] = getSelectValue(item.name, query);
    });
  },
  { deep: true }
);


function capitalize(text: string) {
  if (!text) return '';
  return convertString().toCapitalize(text);
}

function getSelectLabel(item: IModelFilter) {
  const current = route.query[`filter_${item.name}`] as string | undefined;
  if (!current) return item.title;
  const opt = item.options.find(o => o.name === current);
  return opt ? capitalize(opt.title) : item.title;
}
</script>

<style lang="scss">
.filter-selects {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.filter-selects__wrapper {
  position: relative;
}

.filter-selects__slider-wrapper {
  position: absolute;
  padding: 12px;
  bottom: -10px;
  left: 50%;
  z-index: $z-index-tooltip;
  transform: translate(-50%, 100%);
  border-radius: $radius-xl;
  background-color: $filters-main-slider-bg;
  border: 1px solid $filters-main-slider-border;
  min-width: 254px;
}

.filter-selects__slider-wrapper.--left {
  left: 0;
  transform: translate(0, 100%);
}

.filter-selects__slider-wrapper.--right {
  right: 0;
  left: unset;
  transform: translate(0, 100%);
}

.filter-selects__select-hidden {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  cursor: pointer;
  width: 100%;
  height: 100%;
}

.ui-btn.filter-selects__select-button {
  text-transform: none;
}

.filter-selects__select-button.--active-select {
  padding: 6px 14px;
  border: 1px solid $filters-main-select-border--active;
  color: $filters-main-select-text--active;
  background-color: $filters-main-select-bg--active;
}

.filter-selects__slider-popup {
  display: grid;
  row-gap: 16px;
  padding: 8px 16px;
}

.filter-selects__slider-wrapper .ui-slider__wrapper {
  background-color: $filters-main-slider-content-bg;
}

.filter-selects__wrapper:is(:hover, :focus-visible) .filter-selects__select-button:not(.--active-select) {
  @media (hover: hover) {
    background: $filters-main-bg--hover;
  }
}
</style>
