<!-- Контейнер фильтра моделей с отложенным применением (pending) перед навигацией -->
<template>
  <div class="filter-model">
    <FilterChips
      :items="chipsItems"
      @click="onChipsClick"
    >
      <button
        v-if="chipsItems.length > 1"
        class="filter-model__clear"
        type="button"
        @click="onClearAllClick"
      >{{ t('reset_all') }}</button>
    </FilterChips>
    <transition appear>
      <FilterPopup
        v-model="model"
        :title="t('filter')"
        :active-count="pendingChipsItems.length"
        :active-chips="pendingChipsItems"
        :quick="quickFields"
        :groups="groupItems"
        models-page
        :loading="status === 'pending'"
        @chip-click="onPendingChipsClick"
        @field-update="onFieldUpdate"
      >
        <template #quick-field="{ item, index }">
          <FilterModelField
            v-if="quickFilter(item as { name: string })"
            :field="quickFilter(item as { name: string }) as IModelFilter"
            :index="index"
            :pending-query="pendingQuery"
            :units="units"
            :unit-items="unitItems"
            @update:pending-query="onQueryUpdate"
            @update:units="units = $event"
          />
        </template>

        <template #field="{ field, index }">
          <FilterModelField
            :field="field as IModelFilter"
            :index="index"
            :pending-query="pendingQuery"
            :units="units"
            :unit-items="unitItems"
            @update:pending-query="onQueryUpdate"
            @update:units="units = $event"
          />
        </template>

        <template #footer>
          <div class="filter-model__footer-buttons">
            <UiBtn
              :disabled="!isPendingFiltered"
              class="filter-model__reset"
              theme="secondary"
              @click="onResetClick"
            >{{ t('reset_all') }}
            </UiBtn>
            <UiBtn
              theme="primary"
              @click="onApplyClick"
            >{{ t('apply') }}{{ pendingChipsItems.length ? ` (${pendingChipsItems.length})` : '' }}
            </UiBtn>
          </div>
        </template>
      </FilterPopup>
    </transition>
  </div>
</template>

<script setup lang="ts">
import type { IChipsItem, IModelCard, IModelFilter, PaginatedResponse } from '../../types';
import type { LocationQuery } from '#vue-router';
import { getSortedFilterGroups } from '../../utils/get-sorted-filter-groups';

const props = defineProps<{
  data: PaginatedResponse<IModelCard>,
  status: string,
}>();

const model = defineModel<boolean>();

const { t, locale } = useI18n();
const route = useRoute();
const router = useRouter();

const { units, hiddenByUnits } = useUnits();

const EXCLUDED_GROUP_NAMES = ['tags', 'quick'];

const filters = computed<IModelFilter[]>(() => (props.data as any).filters ?? []);

const pendingQuery = ref<LocationQuery>({ ...route.query });

watch(() => model.value, (open) => {
  if (open) {
    pendingQuery.value = { ...route.query };
  }
});

const pendingRouteLike = reactive({
  get query() {
    return pendingQuery.value;
  },
});

const { chipsItems } = useFilterChipsItems(filters, route, t, locale);
const { chipsItems: pendingChipsItems } = useFilterChipsItems(filters, pendingRouteLike, t, locale);

const isPendingFiltered = computed(() => Object.keys(pendingQuery.value).some(item => item.startsWith('filter')));

const quickFilters = computed(() =>
  filters.value
    .filter((f): f is IModelFilter => f.group.name === 'quick'),
);

const quickFields = computed(() =>
  quickFilters.value.map(filter => ({
    name: filter.name,
    title: filter.title,
    label: filter.title,
    value: getPendingValue(filter.name) as string,
    items: selectItems(filter),
    active: isPendingActive(filter.name),
    icon: filter.icon
  })),
);

const groupedFilters = computed(() =>
  filters.value.filter(
    f => !EXCLUDED_GROUP_NAMES.includes(f.group.name),
  ),
);

const groupsList = computed(() => getSortedFilterGroups(groupedFilters.value));

const groupItems = computed(() =>
  groupsList.value.map(group => {
    const fields = groupedFilters.value.filter(
      f => f.group.name === group.name && !hiddenByUnits.value.has(f.name),
    );
    return {
      key: group.name,
      title: group.title,
      description: group.description,
      count: fields.length,
      fields,
    };
  }),
);

const unitItems = computed(() => [
  { name: 'metric', title: t('units_metric'), quantity: 0 },
  { name: 'imperial', title: t('units_imperial'), quantity: 0 },
]);

watch(units, () => {
  const next = { ...pendingQuery.value };
  const unitFields = ['height_cm', 'height_in', 'weight_kg', 'weight_lb'];
  for (const field of unitFields) {
    delete next[`filter_${field}_from`];
    delete next[`filter_${field}_to`];
  }
  pendingQuery.value = next;
});

/** Быстрые поля в модалку приходят уже маппингом — исходный фильтр ищем по имени. */
function quickFilter(item: { name: string }) {
  return quickFilters.value.find(filter => filter.name === item.name);
}

function selectItems(item: IModelFilter) {
  return item.options.map(option => ({
    value: option.name,
    title: `${option.title} (${option.quantity})`,
  }));
}

function onQueryUpdate(newQuery: LocationQuery) {
  pendingQuery.value = { ...newQuery };
}

function updatePendingFilter(name: string, val: any) {
  const next = { ...pendingQuery.value };
  if (!val || val === 'all') {
    delete next[`filter_${name}`];
  } else {
    next[`filter_${name}`] = val;
  }
  pendingQuery.value = next;
}

function isPendingActive(name: string) {
  const baseName = name.replace(/_(from|to)$/, '');
  return Object.keys(pendingQuery.value).some(key => key.startsWith(`filter_${baseName}`));
}

function getPendingValue(name: string) {
  const value = pendingQuery.value[`filter_${name}`];
  if (value) {
    return value;
  }
  const filter = filters.value.find(f => f.name === name);
  if (filter && filter.options.length > 0) {
    return filter.options[0].name;
  }
  return null;
}


function onChipsClick(item: IChipsItem) {
  const query = { ...route.query };
  if (Array.isArray(item.value) && item.value.length > 1) {
    item.value.forEach((text: string) => {
      delete query[`${text}`];
    });
  } else {
    delete query[`${item.value}`];
  }
  router.replace({ query });
}

function onPendingChipsClick(item: IChipsItem) {
  const next = { ...pendingQuery.value };
  if (Array.isArray(item.value) && item.value.length > 1) {
    item.value.forEach((text: string) => {
      delete next[`${text}`];
    });
  } else {
    delete next[`${item.value}`];
  }
  pendingQuery.value = next;
}

function onFieldUpdate({ name, value }: { name: string, value: any }) {
  updatePendingFilter(name, value);
}

function onResetClick() {
  pendingQuery.value = {};
}

/** «Сбросить всё» в облаке чипсов: снимает фильтры, сортировку не трогает. */
function onClearAllClick() {
  const query = { ...route.query };
  Object.keys(query)
    .filter(key => key.startsWith('filter_'))
    .forEach(key => delete query[key]);
  delete query['page'];

  router.replace({ query });
}

function onApplyClick() {
  model.value = false;
  router.replace({ query: pendingQuery.value });
}
</script>

<style lang="scss">
.filter-model {
  margin-top: 8px;
}

// в облаке чипсов кнопка идёт последней, а слот `FilterChips` кладёт её первой
.filter-model__clear {
  @include font-sm;

  order: 1;
  padding: 6px 8px;
  color: $filter-model-clear-text;

  &:is(:hover, :focus) {
    color: $filter-model-clear-text--hover;
  }
}

// диапазон в сетке быстрых фильтров занимает обе колонки: слайдеру нужна вся
// ширина под шкалу и подписи границ
.filter-popup__grid > .filter-model-field__slider {
  grid-column: 1 / -1;
}

.filter-model__footer-buttons {
  display: flex;
  justify-content: space-between;
  column-gap: 8px;
}

.filter-model__units {
  margin-left: 8px;
}

.filter-model__reset {
  @include button-variant(filter-reset);
}
</style>
