<script setup lang="ts">
import { ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import axiosClient from '@/services/HttpService'
import mime from 'mime'
import io from 'socket.io-client'

import type { StorageFile } from '@/stores/storage'
import { useSearchDataStore } from '@/stores/searched-data'
import { useLoader } from '@/stores/loader'
import { useFileInfoStore } from '@/stores/file-info-data'

import AdvancedSearch from '@/modules/01_user/components/AdvancedSearch.vue'

const loaderStore = useLoader()
const { isFilePreview } = storeToRefs(useFileInfoStore())
const {
  foundFile,
  isSearch,
  isAdvSearchCall,
  isActFoundFile,
  searchData,
  advSearchDataField,
  advSearchDataRow,
} = storeToRefs(useSearchDataStore())
const { getFoundFile } = useSearchDataStore()
const optionsField = [
  { label: 'ชื่อเรื่อง (title)', value: 'title' },
  { label: 'คำสำคัญ (keyword)', value: 'keyword' },
  { label: 'หมวดหมู่ (category)', value: 'category' },
  { label: 'เนื้อหาในไฟล์ (content)', value: 'attachment.content' },
]
const submitSearchData = ref<{
  AND: { field: string; value: string }[]
  OR: { field: string; value: string }[]
}>({
  AND: [],
  OR: [],
})
const props = defineProps<{
  mode: 'admin' | 'user'
}>()

const socket = io(import.meta.env.VITE_API_HOST)

socket.on('FileUpdate', (data: StorageFile) =>
  replaceSearchItem(data.pathname, data),
)
socket.on('FileUpload', (data: StorageFile) =>
  replaceSearchItem(data.pathname, data),
)
socket.on('FileUpdateMove', (data: { from: StorageFile; to: StorageFile }) =>
  replaceSearchItem(data.from.pathname, data.to),
)

function replaceSearchItem(pathname: string, data: StorageFile) {
  const idx = foundFile.value.findIndex((v) => v.pathname === pathname)

  if (idx !== -1) foundFile.value[idx] = data
}

async function submitSearch() {
  isFilePreview.value = false
  if (searchData.value.value.trim() !== '') {
    submitSearchData.value = { AND: [], OR: [] }
    if (props.mode === 'admin') {
      optionsField.forEach((option) => {
        submitSearchData.value.OR.push({
          field: option.value,
          value: searchData.value.value,
        })
      })
      submitSearchData.value.OR.push({
        field: 'fileName',
        value: searchData.value.value,
      })
      submitSearchData.value.OR.push({
        field: 'fileType',
        value: mime.getType(searchData.value.value) || '',
      })
    } else {
      submitSearchData.value.OR.push({
        field: searchData.value.field,
        value: searchData.value.value,
      })
      if (isAdvSearchCall.value) {
        let advField = advSearchDataField.value
        let advRow = advSearchDataRow.value

        advRow.forEach((d: { field: string; value: string; op: string }) => {
          if (d.field && d.value.trim() !== '') {
            const op = d.op === 'AND' ? 'AND' : 'OR'
            submitSearchData.value[op].push({ field: d.field, value: d.value })
          }
        })
        if (advField.keyword.length > 0) {
          for (let i = 0; i < advField.keyword.length; i++) {
            submitSearchData.value.AND.push({
              field: 'keyword',
              value: advField.keyword[i],
            })
          }
        }
        if (advField.description.trim() !== '') {
          submitSearchData.value.AND.push({
            field: 'description',
            value: advField.description,
          })
        }
      }
    }

    try {
      loaderStore.show()
      const res = await axiosClient.post<StorageFile[]>(
        `${import.meta.env.VITE_API_ENDPOINT}/search`,
        submitSearchData.value,
      )
      getFoundFile(res.data)
      isSearch.value = true
    } catch (error) {
      console.error('Error during the request', error)
    } finally {
      loaderStore.hide()
    }
  }
}

watch(
  () => isActFoundFile.value,
  (edited) => {
    if (edited === true) {
      submitSearch()
      setTimeout(() => {
        isActFoundFile.value = false
      }, 300)
    }
  },
)

watch(
  () => searchData.value.value,
  (search) => {
    if (search.length === 0) {
      isSearch.value = false
    }
  },
)
</script>

<template>
  <div class="col-3" v-if="mode === 'admin'">
    <q-input
      rounded
      outlined
      dense
      label="ค้นหา"
      debounce="500"
      bg-color="white"
      v-model="searchData.value"
      id="inputSearch"
      @update:model-value="submitSearch"
      @keydown.enter.prevent="submitSearch"
      data-testid="searchAdmin"
    >
      <template v-slot:prepend />
      <template v-slot:append
        ><q-icon name="search" class="pointer" @click="submitSearch"
      /></template>
    </q-input>
  </div>

  <div v-if="mode === 'user'">
    <div class="q-pa-md bg-grey-1">
      <div class="row items-center q-col-gutter-md">
        <div class="col-12 col-md-3">
          <q-select
            id="searchField"
            dense
            outlined
            emit-value
            map-options
            class="bg-white"
            v-model="searchData.field"
            :options="optionsField"
          />
        </div>
        <div class="col-12 col-md-grow">
          <q-input
            id="searchValue"
            class="bg-white"
            dense
            outlined
            v-model="searchData.value"
            placeholder="เอกสาร"
            @keydown.enter.prevent="submitSearch"
          >
            <template v-slot:append>
              <q-icon
                v-if="searchData.value"
                name="close"
                @click="() => ((searchData.value = ''), (isSearch = false))"
                class="cursor-pointer"
                id="clearSearchData"
              />
            </template>
          </q-input>
        </div>
      </div>

      <div class="column">
        <div class="row items-center justify-between q-gutter-y-md q-pt-sm">
          <div class="column col-grow">
            <advanced-search
              :submitSearch="submitSearch"
              :submit-search-data="submitSearchData"
            />
          </div>
          <div v-if="isAdvSearchCall === false">
            <q-btn
              style="width: 150px"
              color="primary"
              label="ค้นหา"
              icon="mdi-magnify"
              @click="submitSearch"
              id="submitSearch"
            />
          </div>
        </div>
      </div>
    </div>
    <q-separator />
  </div>
</template>

<style scoped>
.pointer {
  cursor: pointer;
}
</style>
