<!-- Страница видео модели: инфо, теги, грид видео, пагинация, похожие -->
<template>
  <div class="view-model-videos _page _container">
    <InfoMain
      v-if="cardInfo && isFirstPage && !isFilteredPage"
      :key="`info-${cardInfo.title}`"
      :card="cardInfo"
      :title="title"
      :videos-count="infoVideosCount"
      class="view-model-videos__info"
      type="model"
    />

    <UiSectionTitle
      v-else-if="isFilteredPage"
      :count="data?.total ? $n(data.total, 'compact') : 0"
      :title="title"
      class="view-model-videos__title _title"
      icon="video-camera"
    />

    <LazyUiExpandRow
      v-if="modelChips && modelChips.length > 0"
      :items="modelChips"
      :pre-text="`${t(modelChipsLabel)}:`"
      class="view-model-videos__top-chips"
      hydrate-on-idle
    />

    <LazySectionToolbar
      class="view-model-videos__options"
      hydrate-on-idle
    />

    <GridVideos
      v-if="data && data.items && data.items?.length > 0"
      :items="data.items"
      :class="{'_loading': status === 'pending'}"
      id="anchor"
      priority
    >
      <template #grid-end>
        <LazyAdvNativeBottom
          v-if="featureFlags.AdsNativeEnabled"
          hydrate-on-visible
        />
      </template>
    </GridVideos>
    <div
      v-else-if="status === 'pending'"
      class="view-model-videos__loading _loading"
    />
    <UiEmptyState v-else/>

    <LazyUiPagination
      v-if="data"
      arrow-icon
      :key="`pagination-${data.allPages}`"
      :total="data.allPages"
      class="view-model-videos__pagination _pagination"
      hydrate-on-visible
    />

    <div
      v-if="otherItems.length > 0"
      class="view-model-videos__other"
    >
      <UiSectionTitle
        :count="props.dataOther ? $n(props.dataOther?.total, 'compact') : 0"
        :title="otherItemsTitle"
        class="view-model-videos__other-title"
        title-tag="h2"
        icon="video-camera"
      />

      <LazyGridVideos
        :items="otherItems"
        :class="{'_loading': statusOther === 'pending'}"
        :hydrate-on-visible="HYDRATE_MARGIN"
        class="view-model-videos__grid"
      />
      <UiLink
        v-if="dataOther && dataOther?.total > 12"
        :to="otherMoreLink"
        class="view-model-videos__other-more"
        theme="primary"
      >{{ moreVideosButton }}
      </UiLink>
    </div>

    <LazySectionSwiperCards
      v-if="similarModels && similarModels.length > 0"
      :items="modelsRoundCards"
      placeholder-avatar="/img/model-placeholder.webp"
      class="view-model-videos__other-models"
      hydrate-on-visible
    >{{ $t('similar_models' )}}</LazySectionSwiperCards>

    <LazyUiFullDescr
      v-if="isFirstPage && cardInfo?.fullDescription && !isFilteredPage"
      :text="cardInfo.fullDescription"
      hydrate-on-visible
    />
  </div>
</template>

<script setup lang="ts">
import type {
  ICardInfo,
  IChannelCard,
  IChipsItem,
  IModelCard,
  IPopularTags,
  IVideoCard,
  PaginatedResponse
} from '../../types';
import type { AsyncDataRequestStatus } from '#app';
import { convertString, convertModelToRoundCard } from '../../runtime';
import { computed } from 'vue';

const featureFlags = useRuntimeConfig().public.featureFlags;

/** Запас гидрации грида: без него тап по карточке у нижнего края экрана уходит по негидрированной разметке. */
const HYDRATE_MARGIN = { rootMargin: '300px' };

const props = defineProps<{
  title: string
  data: PaginatedResponse<IVideoCard> | null
  dataOther?: PaginatedResponse<IVideoCard> | null
  status: AsyncDataRequestStatus
  statusOther?: AsyncDataRequestStatus
  cardInfo: ICardInfo | null
  dataModels: PaginatedResponse<IModelCard> | null
  modelTags: IPopularTags[] | null
  modelChannels: PaginatedResponse<IChannelCard> | null
  similarModels?: IModelCard[] | undefined

}>();
const route = useRoute();

const { t } = useI18n();

const modelsRoundCards = computed(() =>
    props.similarModels?.map(convertModelToRoundCard) || []
);

const activeFilterSlug = computed(() => {
  const entry = Object.entries(route.params)
      .find(([key]) => key !== 'slug');

  return convertString().fromSlug(String(entry?.[ 1 ]));
});

const hasTags = computed(() => props.modelTags && Array.isArray(props.modelTags) && props.modelTags.length > 0);
const hasChannels = computed(() => props.modelChannels?.items && Array.isArray(props.modelChannels.items) && props.modelChannels.items.length > 0);

const modelChipsLabel = computed(() => {
  if (hasTags.value && hasChannels.value) return 'model_tags_and_channels';
  if (hasChannels.value) return 'model_channels';
  return 'model_tags';
});

const otherItemsTitle = computed(() => {
  if (hasTags.value) {
    return t('other_videos_you_might_like_tags', { slug: activeFilterSlug.value || '' });
  }
  return t('other_videos_you_might_like_channel', { slug: activeFilterSlug.value || '' });
});

const moreVideosButton = computed(() => {
  if (hasTags.value) {
    return t('more_videos_tag', { slug: activeFilterSlug.value || '' });
  }
  return t('more_videos_channel', { slug: activeFilterSlug.value || '' });
});

const modelChips = computed(() => {
  const tagsChips: IChipsItem[] = props.modelTags && Array.isArray(props.modelTags)
      ? props.modelTags.map((item: IPopularTags) => ({
        title: item.title,
        value: item.title,
        prefix: `models/${route.params[ 'slug' ]}/tag`,
        resetPath: `models/${route.params[ 'slug' ]}`
      }))
      : [];

  const channelsChips: IChipsItem[] = props.modelChannels?.items && Array.isArray(props.modelChannels.items)
      ? props.modelChannels.items.map((item: IChannelCard) => ({
        title: item.name,
        value: item.name,
        prefix: `models/${route.params[ 'slug' ]}/channel`,
        resetPath: `models/${route.params[ 'slug' ]}`,
        image: item.avatarUrl || '/img/logo-placeholder.svg',
      }))
      : [];

  const activeTagSlug = convertString().fromSlug(String(route.params[ 'tag' ]));
  const activeChannelSlug = convertString().fromSlug(String(route.params[ 'channel' ]));

  // Helper function to find active chip
  function findActiveChip(chips: IChipsItem[], slug: string | undefined, type: 'tag' | 'channel') {
    if (!slug) return null;
    return chips.find(chip => String(chip.value).toLowerCase() === slug.toLowerCase() && chip.prefix?.includes(type));
  }

  const activeTagChip = findActiveChip(tagsChips, activeTagSlug, 'tag');
  const activeChannelChip = findActiveChip(channelsChips, activeChannelSlug, 'channel');

  const filteredTags = tagsChips.filter(chip => chip !== activeTagChip);
  const filteredChannels = channelsChips.filter(chip => chip !== activeChannelChip);

  const result: IChipsItem[] = [];

  // Active chip(s) always first
  const activeChips = [activeChannelChip, activeTagChip].filter(Boolean) as IChipsItem[];
  result.push(...activeChips);

  // Then the rest: channels first, then tags (excluding active ones)
  result.push(...filteredChannels);
  result.push(...filteredTags);

  return result;
});

const otherItems = computed<IVideoCard[]>(() => {
  return props.dataOther?.items?.slice(0, 12) ?? [];
});

const { generateLink } = useGenerateLink();

const otherMoreLink = computed(() => {
  const key = Object.keys(route.params)
      .find((item) => item !== 'slug');

  const slug = convertString().toSlug(activeFilterSlug.value);
  return generateLink(`/${key}/${slug}`);
});

const isFirstPage = computed(() => !route.query[ 'page' ] || route.query[ 'page' ] === '1');

const isFilteredPage = computed(() => Boolean(route.params[ 'tag' ] || route.params[ 'channel' ]));

const infoVideosCount = computed(() => (props.dataOther && props.dataOther.items) ? props.data?.items.length : 0);
</script>

<style lang="scss">
.view-model-videos__info {
  margin-bottom: 24px;
}

.view-model-videos__top-chips {
  margin-bottom: 24px;
}

.view-model-videos__options {
  margin-bottom: 24px;
}

.view-model-videos__options:has(.ui-expand-row) {
  margin-bottom: 16px;
}

.view-model-videos__wrapper {
  display: grid;
  gap: 8px;

  @include from-br(sm) {
    row-gap: 16px;
  }
}

.view-model-videos__filter-button {
  grid-row: 3;
  grid-column: 2;

  @include from-br(sm) {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }
}

.view-model-videos__breadcrumbs:deep(.ui-breadcrumbs__item) {
  text-transform: capitalize;
}

.view-model-videos__loading {
  height: 100%;
  min-height: 30vh;
}

.view-model-videos__options {
  grid-row: 2;
  grid-column: 1/-1;
}

.view-model-videos__other-more {
  @include from-br(sm) {
    margin: 0 auto;
  }

  @include to-br(sm) {
    width: 100%;
  }
}

.view-model-videos__other-models {
  padding-top: 32px;
  border-top: 1px solid $page-model-videos-section-border;
  margin-top: 48px;
}

.view-model-videos__other {
  display: grid;
  row-gap: 16px;
  margin-top: 32px;
  margin-bottom: 32px;
}

.view-model-videos__pagination {
  margin-top: auto;
  padding-top: 32px;
}

.view-models__footer-categories {
  padding-top: 32px;
  margin-top: auto;
  margin-bottom: 32px;
}
</style>
