<template>
  <div class="store">
    <store-filter
        v-if="filters.length"
        :filterableAttributes="filters"
        :isOpen="showFilter"
        @update:selected="onFiltersChange"
        @close="showFilter = false"
    />
    <store-top
        v-model="orderBy"
        @toggle-filter="onFilterToggle"
        :isFiltersVisible="filters.length > 0"
    />
    <client-only>
      <div
          class="store__list"
          :class="[
            { 'store__list-grid': productView === 'grid' },
            { 'store__list-list': productView === 'list' }
        ]"
      >
        <cards-product
            v-if="products.length && !pending"
            v-for="product in products"
            :key="product.node.uuid"
            :product="product.node"
            :isList="productView === 'list'"
        />
        <skeletons-cards-product
            v-if="pending"
            v-for="idx in 12"
            :key="idx"
            :isList="productView === 'list'"
        />
      </div>
    </client-only>
    <div class="store__list-observer" ref="observer"></div>
  </div>
</template>

<script setup lang="ts">
import {useFilters, useStore} from "~/composables/store";
import {useRouteQuery} from "@vueuse/router";
import {useRouteParams} from "@vueuse/router";
import {useCategoryBySlug} from "~/composables/categories";
import {useAppConfig} from '~/composables/config';
import {useDefaultSeo} from "~/composables/seo";

const { locale } = useI18n();

const { COOKIES_PRODUCT_VIEW_KEY, APP_NAME } = useAppConfig();
const productView = useCookie<string>(
  COOKIES_PRODUCT_VIEW_KEY as string,
  {
    default: () => 'grid',
    path: '/',
  }
);

const slug = useRouteParams<string>('slug');
const attributes = useRouteQuery<string>('attributes', '');
const orderBy = useRouteQuery<string>('orderBy', 'created');
const minPrice = useRouteQuery<number>('minPrice', 0);
const maxPrice = useRouteQuery<number>('maxPrice', 50000);
const observer = ref(null);

const { category, seoMeta, filters } = await useCategoryBySlug(slug.value);

const meta = useDefaultSeo(seoMeta.value || null);

if (meta) {
  useSeoMeta({
    title: meta.title || APP_NAME,
    description: meta.description || meta.title || APP_NAME,
    ogTitle: meta.og.title || undefined,
    ogDescription: meta.og.description || meta.title || APP_NAME,
    ogType: meta.og.type || undefined,
    ogUrl: meta.og.url || undefined,
    ogImage: meta.og.image || undefined,
    twitterCard: meta.twitter.card || undefined,
    twitterTitle: meta.twitter.title || undefined,
    twitterDescription: meta.twitter.description || undefined,
    robots: meta.robots,
  });

  useHead({
    link: [
      meta.canonical ? { rel: 'canonical', href: meta.canonical } : {},
    ].filter(Boolean) as any,
    meta: [{ property: 'og:locale', content: locale.value }],
    script: meta.jsonLd.map((obj: any) => ({
      type: 'application/ld+json',
      innerHTML: JSON.stringify(obj),
    })),
    __dangerouslyDisableSanitizersByTagID: Object.fromEntries(
        meta.jsonLd.map((_, i: number) => [`ldjson-${i}`, ['innerHTML']])
    ),
  });
}

watch(
  () => category.value,
  (cat) => {
    if (cat && !useRoute().query.maxPrice) {
      maxPrice.value = cat.minMaxPrices.maxPrice;
    }
  },
  { immediate: true }
);

const { pending, products, pageInfo, variables } = useStore(
  slug.value,
  attributes.value,
  orderBy.value,
  minPrice.value,
  maxPrice.value,
  ''
);

const { buildAttributesString } = useFilters(filters);
const showFilter = ref<boolean>(false);

function onFilterToggle() {
  showFilter.value = true;
}

function onFiltersChange(newFilters: Record<string, string[]>) {
  const attrString = buildAttributesString(newFilters);
  attributes.value = attrString;
  variables.attributes = attrString;
}

useIntersectionObserver(
  observer,
  async ([{ isIntersecting }]) => {
    if (isIntersecting && pageInfo.value?.hasNextPage && !pending.value) {
      variables.productAfter = pageInfo.value.endCursor;
    }
  },
);

watch(orderBy, newVal => {
  variables.orderBy = newVal || '';
});
watch(attributes, newVal => {
  variables.attributes = newVal;
});
watch(minPrice, newVal => {
  variables.minPrice = newVal || 0;
});
watch(maxPrice, newVal => {
  variables.maxPrice = newVal || 500000;
});
</script>

<style scoped lang="scss">
.store {
  position: relative;

  &__inner {
    width: 100%;
  }

  &__list {
    margin-top: 50px;

    &-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
      gap: 25px;
    }

    &-list {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 20px;
    }

    &-observer {
      background-color: transparent;
      width: 100%;
      height: 10px;
    }
  }
}
</style>