<script setup>
import { ref, watch, onMounted } from "vue";
import BaseInput from "@/components/common/BaseInput.vue";
import DateInput from "@/components/common/DateInput.vue";
import { useRoute, useRouter } from "vue-router";
import { getOptions } from "@/api/default_api_promises";

let route = useRoute()
let router = useRouter()
let commonSearchInput = ref(route.query.common_search_query)
let advancedSearchOn = ref(false)
let dateRangeFrom = ref(route.query.creation_date__gte?.split("-").reverse().join("."))
let dateRangeTo = ref(route.query.creation_date__lte?.split("-").reverse().join("."))
let formData = ref({
  persons: route.query.persons__icontains,
  author: route.query.author__icontains,
  keywords: route.query.keywords__icontains,
  annotation: route.query.annotation__icontains,
  shooting_location: route.query.creation_place__icontains,
  archive_number: route.query.archive_number,
  name: route.query.name,
  personalities: route.query.persons__icontains
})
let metadata = ref({})

// Окна расширенного поиска
const typesOfSearch = [
  {common: "Общий поиск"},
  {image: "Поиск фотодокументов"},
  {audio: "Поиск фонодокументов"},
  {video: "Поиск киновидеодокументов" },
]
let currentSearchWindow = ref(route.query.material_type || "common")

function loadMetadata() {
  if (currentSearchWindow.value === 'common') return;

  getOptions({ url: `/api/${currentSearchWindow.value}-materials/` })()
    .then(res => metadata.value = res.data.actions.filter_fields || {});
}
function stringToDate(dateString) {
  if (!dateString) return null;
  const [day, month, year] = dateString.split(".");
  return `${year}-${month}-${day}`;
}

const handleSubmit = () => {
  const keyMap = { shooting_location: "creation_place", authors: "author", personalities: "persons" };

  const query = {
    page: 1,
    page_size: 5,
    material_type: currentSearchWindow.value,
  };

  if (commonSearchInput.value) {
    query.common_search_query = commonSearchInput.value;
  }

  Object.entries(formData.value).forEach(([key, value]) => {
    if (value) {
      const mappedKey = keyMap[key] || key;
      query[`${mappedKey}${key in metadata.value ? '__icontains' : ''}`] = value;
    }
  });

  const dateFrom = stringToDate(dateRangeFrom.value);
  const dateTo = stringToDate(dateRangeTo.value);

  if (dateFrom) {
    query.creation_date__gte = dateFrom;
  }
  if (dateTo) {
    query.creation_date__lte = dateTo;
  }

  router.replace({ name: "search", query });
};

function scrollToOneThirdHeight() {
  const height = window.innerHeight;
  window.scrollTo({
    top: height / 2,
    behavior: 'smooth',
  });
}

watch([advancedSearchOn, currentSearchWindow], ([newVal]) => {
  if (newVal) {
    scrollToOneThirdHeight();
    loadMetadata();
  }
});

onMounted(() => {
  advancedSearchOn.value = route.query.material_type && route.query.material_type !== 'common';
});
</script>

<template>
  <div class="home">
    <div id="datepicker-container" />
    <div class="wrapper wrapper__indent">
      <div class="search-box">
        <base-input @keyup.enter="handleSubmit" v-model="commonSearchInput" :value="commonSearchInput" style="width: 400px; padding: 24px;" placeholder="Я ищу" />
        <v-btn @click="handleSubmit" variant="outlined" class="search-button">
          <v-icon size="28" class="search-icon" color="primary">mdi-magnify</v-icon>
        </v-btn>
      </div>
      <div class="search-switch">
        <v-switch v-model="advancedSearchOn" label="Расширенный поиск" color="primary-blue" />
      </div>
      <div v-if="advancedSearchOn" class="advanced-search-box">
        <v-window v-model="currentSearchWindow" show-arrows :continuous="true" style="width: 1000px;">
          <template v-slot:prev="{ props }">
            <button @click="props.onClick" class="arrow-button prev-arrow">
              <v-icon size="36" color="primary">mdi-chevron-left</v-icon>
            </button>
          </template>
          <template v-slot:next="{ props }">
            <button @click="props.onClick" class="arrow-button next-arrow">
              <v-icon size="36" color="primary">mdi-chevron-right</v-icon>
            </button>
          </template>
          <v-window-item v-for="(item, index) in typesOfSearch" :key="Object.keys(item)[0]" :value="Object.keys(item)[0]">
            <v-card class="d-flex justify-center">
              <div class="search-window">
                <p class="d-block ml-10 mt-2 fs-18 fw-regular color-primary-blue">{{ Object.values(item)[0] }}</p>
                <v-divider class="mx-10 mt-3" />
                <template v-if="Object.keys(item)[0] === 'image'">
                  <div class="mt-5 px-10">
                    <div class="d-flex">
                      <div class="left-column mr-4">
                        <template v-for="(field, key) in metadata" :key="key">
                          <template v-if="key === 'author' || key === 'persons'">
                            <base-input data-field-type="image-search" class="base-input-size mb-4" :placeholder="field.label" v-model="formData[key]" :value="route.query[`${key}__icontains`]" style="display:inline-block" />
                          </template>
                        </template>
                        <div class="date-fields-container mb-4">
                          <date-input placeholder="Дата от" teleport="#datepicker-container" v-model="dateRangeFrom" data-date-field="image-search" style="width:155px;display:inline-block" />
                          <date-input placeholder="Дата до" teleport="#datepicker-container" :min-date="stringToDate(dateRangeFrom)" v-model="dateRangeTo" data-date-field="image-search" style="width:155px;display:inline-block" />
                        </div>
                      </div>
                      <div class="right-column">
                        <template v-for="(field, key) in metadata" :key="key">
                          <template v-if="!['author', 'persons', 'creation_date'].includes(key)">
                            <base-input data-field-type="image-search" class="base-input-size mb-4" :placeholder="field.label" v-model="formData[key]" :value="route.query[`${key}__icontains`]" style="display:inline-block" />
                          </template>
                        </template>
                      </div>
                    </div>
                  </div>
                </template>
                <template v-else>
                  <div class="mt-5 px-10">
                    <div class="d-flex justify-space-between">
                      <base-input class="base-input-size" placeholder="Название" v-model="formData.name" />
                      <base-input class="base-input-size" placeholder="Аннотация" v-model="formData.annotation" />
                    </div>
                    <div class="d-flex justify-space-between mt-5">
                      <div class="date-fields-container">
                        <date-input placeholder="Дата от" teleport="#datepicker-container" v-model="dateRangeFrom" style="width: 155px" />
                        <date-input placeholder="Дата до" teleport="#datepicker-container" :min-date="stringToDate(dateRangeFrom)" v-model="dateRangeTo" style="width: 155px" />
                      </div>
                      <base-input class="base-input-size" placeholder="Архивный номер" v-model="formData.archive_number" />
                    </div>
                    <div class="d-flex justify-space-between mt-5">
                      <base-input class="base-input-size" placeholder="Авторы" v-model="formData.authors" />
                      <base-input class="base-input-size" placeholder="Персоналии" v-model="formData.personalities" />
                    </div>
                  </div>
                </template>
              </div>
            </v-card>
          </v-window-item>
        </v-window>
      </div>
      <router-view :key="route.fullPath" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.search-box {
  display: flex;
  justify-content: center;
  align-items: center;
}

.search-icon {
  height: 60px;
  width: 60px;
  border-radius: 8px;
}

.search-button {
  height: 60px;
  width: 60px;
  border: solid 1px darkgray;
  margin-left: 10px;
}

.search-switch {
  display: flex;
  justify-content: left;
  margin-left: 310px;
}

.advanced-search-box {
  display: flex;
  justify-content: center;
}

.search-window {
  width: 800px;
  height: 250px;
  margin-top: 15px;
}

.base-input-size {
  width: 340px!important;
  height: 20px!important;
  padding: 15px;
}

.date-fields-container {
  display: flex;
  gap: 20px;
}

.left-column,
.right-column {
  flex: 1;
}
v-window-item {
  border: none;
  box-shadow: none;
}
v-window {
  overflow: hidden;
  border: none;
}

.arrow-button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  opacity: 0;
  transition: opacity 0.4s ease;
  border: none;
  background: transparent;
}

.arrow-button.prev-arrow {
  left: 10px;
}

.arrow-button.next-arrow {
  right: 10px;
}

.advanced-search-box:hover .arrow-button {
  opacity: 1;
}

.item {
  width: 900px;
  padding: 15px;
  margin-top: 15px;
  margin-bottom: 15px;
  border: 1px solid darkgray;
  border-radius: 8px;
  display: flex;
  justify-content: left;
}

.item-label {
  display: block;
  font-size: 12px;
}
</style><script setup>
import { ref, watch } from "vue";
import BaseInput from "@/components/common/BaseInput.vue";
import DateInput from "@/components/common/DateInput.vue";
import { useRoute, useRouter } from "vue-router";

let route = useRoute()
let router = useRouter()
let commonSearchInput = ref(route.query.common_search_query)
let advancedSearchOn = ref(false)
let dateRangeFrom = ref(null)
let dateRangeTo = ref(null)

const typesOfSearch = [
  {image: "Поиск фотодокументов"},
  {audio: "Поиск фонодокументов"},
  {video: "Поиск киновидеодокументов"}
]
let currentSearchWindow = ref("image")

function handleSubmit() {
  const minInputLength = 3
  if (commonSearchInput.value.length >= minInputLength) {
    const query = {
      page: 1,
      page_size: 5,
      material_type: route.query.material_type || "image",
      common_search_query: commonSearchInput.value,
      is_advanced_search: advancedSearchOn.value
    }

    if (advancedSearchOn.value) {
      // Add advanced search parameters if they exist
      if (dateRangeFrom.value) query.creation_date_gte = dateRangeFrom.value
      if (dateRangeTo.value) query.creation_date_lte = dateRangeTo.value
      // Add other advanced search fields as needed
    }

    router.push({
      name: "search",
      query: query
    })
  }
}

function stringToDate(dateString) {
  if (dateString) {
    const [day, month, year] = dateString.split('.')
    return new Date(year, month - 1, day)
  }
}

function scrollToOneThirdHeight() {
  const height = window.innerHeight
  window.scrollTo({
    top: height / 2,
    behavior: 'smooth'
  });
}

watch(advancedSearchOn, (newVal) => {
  if (newVal) {
    scrollToOneThirdHeight()
  }
})
</script>

<template>
  <div class="home">
    <div id="datepicker-container"/>
    <div class="wrapper wrapper__indent">
      <div class="search-box">
        <base-input @keyup.enter="handleSubmit" v-model="commonSearchInput" :value="commonSearchInput" style="width: 400px; padding: 24px;" placeholder="Я ищу"/>
        <v-btn @click="handleSubmit" variant="outlined" class="search-button">
          <v-icon size="28" class="search-icon" color="primary">mdi-magnify</v-icon>
        </v-btn>
      </div>
      <div class="search-switch">
        <v-switch v-model="advancedSearchOn" label="Расширенный поиск" color="primary-blue"/>
      </div>
      <div v-if="advancedSearchOn" class="advanced-search-box">
        <v-window
          v-model="currentSearchWindow"
          show-arrows
          :continuous="true"
          style="width: 1000px;"
        >
          <template v-slot:prev="{ props }">
            <button @click="props.onClick" class="arrow-button prev-arrow">
              <v-icon size="36" color="primary">mdi-chevron-left</v-icon>
            </button>
          </template>
          <template v-slot:next="{ props }">
            <button @click="props.onClick" class="arrow-button next-arrow">
              <v-icon size="36" color="primary">mdi-chevron-right</v-icon>
            </button>
          </template>
          <v-window-item
            v-for="(item, index) in typesOfSearch"
            :key="Object.keys(item)[0]"
            :value="Object.keys(item)[0]"
          >
            <v-card class="d-flex justify-center">
              <div class="search-window">
                <p class="d-block ml-10 mt-2 fs-18 fw-regular color-primary-blue">{{ Object.values(item)[0] }}</p>
                <div class="pl-10 pr-10 pt-3">
                  <v-divider/>
                </div>
                <div class="d-flex justify-space-between mt-5">
                  <base-input class="base-input-size ml-10" placeholder="Название"/>
                  <base-input class="base-input-size mr-10" placeholder="Описание"/>
                </div>
                <div class="d-flex justify-space-between mt-5 pl-10 pr-10" style="height: 30px;">
                  <div class="d-flex justify-space-between">
                    <date-input
                      placeholder="Дата от"
                      teleport="#datepicker-container"
                      v-model="dateRangeFrom"
                      style="width: 155px; margin-right: 13px"
                    />
                    <date-input
                      placeholder="Дата до"
                      teleport="#datepicker-container"
                      :min-date="stringToDate(dateRangeFrom)"
                      v-model="dateRangeTo"
                      style="width: 155px; margin-left: 13px"
                    />
                  </div>
                  <base-input class="base-input-size" placeholder="Архивный номер"/>
                </div>
                <div class="d-flex justify-space-between mt-5" style="height: 30px;">
                  <base-input class="base-input-size ml-10" placeholder="Авторы"/>
                  <base-input class="base-input-size mr-10" placeholder="Персоналии"/>
                </div>
              </div>
            </v-card>
          </v-window-item>
        </v-window>
      </div>
      <router-view :key="route.fullPath" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.search-box {
  display: flex;
  justify-content: center;
  align-items: center;
}

.search-icon {
  height: 60px;
  width: 60px;
  border-radius: 8px;
}

.search-button {
  height: 60px;
  width: 60px;
  border: solid 1px darkgray;
  margin-left: 10px;
}

.search-switch {
  display: flex;
  justify-content: left;
  margin-left: 310px;
}

.advanced-search-box {
  display: flex;
  justify-content: center;
}

.search-window {
  width: 800px;
  height: 250px;
  padding: 15px;
}

.base-input-size {
  width: 340px!important;
  height: 20px!important;
  padding: 15px;
}

v-window-item {
  border: none;
  box-shadow: none;
}
v-window {
  overflow: hidden;
  border: none;
}

.arrow-button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  opacity: 0;
  transition: opacity 0.4s ease;
  border: none;
  background: transparent;
}

.arrow-button.prev-arrow {
  left: 10px;
}

.arrow-button.next-arrow {
  right: 10px;
}

.advanced-search-box:hover .arrow-button {
  opacity: 1;
}

.item {
  width: 900px;
  padding: 15px;
  margin-top: 15px;
  margin-bottom: 15px;
  border: 1px solid darkgray;
  border-radius: 8px;
  display: flex;
  justify-content: left;
}

.item-label {
  display: block;
  font-size: 12px;
}
</style>from django_filters import rest_framework as filters
from django.db.models import Q
from .models import ImageMaterial

class ImageMaterialFilter(filters.FilterSet):


    class Meta:
        model = ImageMaterial
        fields = {
            'keywords': ['icontains'],
            'persons': ['icontains'],
            'annotation': ['icontains'],
            'creation_date': ['gte', 'lte'],
            'creation_place': ['icontains'],
            'author': ['icontains'],
        }

    def filter_search(self, queryset, value):
        return queryset.filter(
            Q(keywords__icontains=value) |
            Q(annotation__icontains=value) |
            Q(persons__icontains=value) |
            Q(author__icontains=value)
        )from django.db.models import Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from backend.apps.core import metadata as core_metadata
from backend.apps.core import views as core_views
from . import models, serializers, filters


class BaseMaterialViewSet(core_views.BaseReadOnlyModelViewSet):
    metadata_class = core_metadata.MaterialGetRequestMetadata

    def get_common_search_lookup(self, common_search_value):
        lookup = Q()
        for field in self.common_search_fields:
            lookup |= Q(**{f"{field}__icontains": common_search_value})
        return lookup

    def get_queryset(self):
        queryset = super().get_queryset()
        is_advanced_search = self.request.GET.get("is_advanced_search") == "true"

        if is_advanced_search:
            return self.filter_queryset(queryset)

        common_search_query = self.request.GET.get("common_search_query")
        if common_search_query:
            query_lookup = self.get_common_search_lookup(common_search_query)
            return queryset.filter(query_lookup)
        return queryset

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class ImageMaterialViewSet(BaseMaterialViewSet):
    queryset = models.ImageMaterial.objects.all()
    serializer_class = serializers.ImageMaterialListSerializer
    filterset_class = filters.ImageMaterialFilter
    serializer_classes = {
        "retrieve": serializers.ImageMaterialDetailSerializer,
    }
    common_search_fields = ["keywords", "annotation", "persons", "author"]

class AudioMaterialViewSet(BaseMaterialViewSet):
    queryset = models.AudioMaterial.objects.all()
    serializer_class = serializers.AudioMaterialListSerializer
    serializer_classes = {
        "retrieve": serializers.AudioMaterialDetailSerializer,
    }
    common_search_fields = ["keywords", "annotation", "persons", "title"]



class VideoMaterialViewSet(BaseMaterialViewSet):
    queryset = models.VideoMaterial.objects.all()
    serializer_class = serializers.VideoMaterialListSerializer
    serializer_classes = {
        "retrieve": serializers.VideoMaterialDetailSerializer,
    }
    common_search_fields = ["keywords", "annotation", "persons", "title", "description"]


def get_video_url(request, video_id):
    video = get_object_or_404(models.VideoFile, id=video_id)
    return JsonResponse({"url": video.file_path.url})


def get_audio_url(request, audio_id):
    audio = get_object_or_404(models.AudioFile, id=audio_id)
    return JsonResponse({"url": audio.file_path.url})


def get_image_url(request, image_id):
    image = get_object_or_404(models.ImageFile, id=image_id)
    return JsonResponse({"url": image.file_path.url}) С ПЕРВЫМ VUE КОДОМ МЕХАНИЗМ ФИЛЬТРАЦИИ РАБОТАЕТ А СО ВТОРЫМ НЕТ ИСПРАВЬ ЭТО