<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { useSearchDataStore } from '@/stores/searched-data'
import { useFileInfoStore } from '@/stores/file-info-data'
import { useTreeDataStore } from '@/stores/tree-data'

import DialogDelete from './DialogDelete.vue'
import UploadExistDialog from './UploadExistDialog.vue'
import FileForm from './FileForm.vue'
import FileItemAction from '@/components/FileItemAction.vue'
import FileIcon from '@/components/FileIcon.vue'

import type { QTableProps } from 'quasar'
import { onMounted, ref, watch } from 'vue'

const props = withDefaults(
  defineProps<{
    action: boolean
    viewMode: 'view_list' | 'view_module'
  }>(),
  {
    action: false,
  },
)
const { foundFile, isActFoundFile } = storeToRefs(useSearchDataStore())
const { getFileInfo, getSize, getType } = useFileInfoStore()
const { updateFile, deleteFile, checkFile } = useTreeDataStore()
const keywordList = ref<string[]>([])
const categoryList = ref<string[]>([])
const selectKeyword = ref<string[]>([])
const selectCategory = ref<string[]>([])
const filterFoundFile = ref<any>()

const fileExistNotification = ref<boolean>(false)
const fileFormError = ref<{ fileExist?: boolean }>({})
const deleteFormType = ref<'deleteFile'>('deleteFile')
const dialogDeleteState = ref<boolean>(false)
const deleteFormPath = ref<string>('')

const fileFormType = ref<'edit'>('edit')
const fileFormState = ref<boolean>(false)
const fileFormPath = ref<string>('')
const fileFormData = ref<{
  file?: File
  title?: string
  description?: string
  keyword?: string[]
  category?: string[]
}>({})

const columns: QTableProps['columns'] = [
  {
    name: 'name',
    required: true,
    label: 'ชื่อไฟล์',
    align: 'left',
    field: (row) => row.fileName,
    format: (val) => `${val}`,
    sortable: true,
    style: 'width: 200px',
  },
  {
    name: 'title',
    align: 'center',
    label: 'ชื่อเรื่อง',
    field: 'title',
    style: 'width: 200px',
    sortable: true,
  },
  {
    name: 'fileType',
    align: 'center',
    label: 'ประเภทของไฟล์',
    field: 'fileType',
    sortable: true,
    style: 'width: 200px',
  },
  {
    name: 'actions',
    align: 'center',
    label: '',
    field: '',
    style: 'width: 20px',
  },
]

const currentParam = ref<Parameters<typeof submitFileForm>[0]>()

async function submitFileForm(
  value: {
    mode: 'create' | 'edit'
    file?: File
    title: string
    description: string
    keyword: string[]
    category: string[]
  },
  force = false,
) {
  currentParam.value = value
  if (value.file && checkFile(value.file.name) && !force) {
    fileExistNotification.value = true
    return
  }

  if (value.mode === 'edit') {
    await updateFile(
      fileFormPath.value,
      {
        title: value.title,
        description: value.description,
        keyword: value.keyword,
        category: value.category,
      },
      value.file,
    )
    setTimeout(() => {
      isActFoundFile.value = true
    }, 300)
  }

  fileFormData.value = {}
  fileFormState.value = false
  currentParam.value = undefined
}

function triggerFileEdit(
  value: {
    title: string
    description: string
    keyword: string[]
    category: string[]
  },
  pathname: string,
) {
  fileFormState.value = true
  fileFormType.value = 'edit'
  fileFormPath.value = pathname
  fileFormData.value = {
    title: value.title,
    description: value.description,
    keyword: value.keyword,
    category: value.category,
  }
}

function triggerFileDelete(pathname: string) {
  deleteFormType.value = 'deleteFile'
  deleteFormPath.value = pathname
  dialogDeleteState.value = !dialogDeleteState.value
}

function confirmDelete() {
  if (deleteFormType) {
    deleteFile(deleteFormPath.value)

    setTimeout(() => {
      isActFoundFile.value = true
    }, 300)
  }
}

function filterSearch() {
  function updateList() {
    keywordList.value = []
    categoryList.value = []
    foundFile.value.forEach((obj) => {
      obj.keyword.forEach((keyword) => {
        if (!keywordList.value.includes(keyword)) {
          keywordList.value.push(keyword)
        }
      })
      obj.category.forEach((category) => {
        if (!categoryList.value.includes(category)) {
          categoryList.value.push(category)
        }
      })
    })
  }

  function filterArray() {
    if (!(selectKeyword.value.length || selectCategory.value.length)) {
      filterFoundFile.value = foundFile.value
    } else {
      filterFoundFile.value = foundFile.value.filter(
        (entry) =>
          entry.keyword.some((kw) => selectKeyword.value.includes(kw)) ||
          entry.category.some((kw) => selectCategory.value.includes(kw)),
      )
    }
  }
  updateList()
  filterArray()
}

watch(
  [
    () => foundFile.value,
    () => selectKeyword.value,
    () => selectCategory.value,
  ],
  filterSearch,
)

onMounted(() => {
  filterSearch()
})
</script>

<template>
  <div class="row grid q-py-md q-gutter-sm">
    <q-select
      outlined
      dense
      multiple
      use-chips
      v-model="selectKeyword"
      :options="keywordList"
      style="width: 100%"
      label="คำสำคัญ"
      class="custom-selection"
    />
    <q-select
      outlined
      dense
      multiple
      use-chips
      v-model="selectCategory"
      :options="categoryList"
      style="width: 100%"
      label="กลุ่ม/หมวดหมู่"
    />
  </div>

  <div v-if="props.viewMode === 'view_list' && foundFile.length > 0">
    <div class="grid q-mt-md">
      <div v-for="(value, index) in filterFoundFile" :key="value.title">
        <div
          :style="{
            position: 'relative',
            display: 'flex',
            gap: '0.5rem',
            flexDirection: 'column',
            alignItems: 'center',
            padding: '1rem',
            maxWidth: '100%',
          }"
          class="box"
          @click="() => getFileInfo(foundFile[index])"
          :id="`getFileInfoFileSearched${index}`"
        >
          <div class="q-px-md flex items-center justify-center">
            <file-icon
              size="preview"
              :fileMimeType="value.fileType ? value.fileType : 'unknow'"
            />
          </div>
          <div
            class="absolute"
            style="top: 0.5rem; right: 0.5rem"
            v-if="props.action"
          >
            <file-item-action
              :nameId="value.pathname"
              @edit="
                () =>
                  triggerFileEdit(
                    {
                      title: value.title,
                      description: value.description,
                      keyword: value.keyword,
                      category: value.category,
                    },
                    value.pathname,
                  )
              "
              @delete="() => triggerFileDelete(value.pathname)"
            />
          </div>
          <div
            class="text-overflow-handle block q-px-md text-center"
            style="max-width: 100%"
          >
            {{ value.title }}
          </div>
        </div>
      </div>
    </div>
  </div>

  <div
    v-if="props.viewMode === 'view_module' && foundFile.length > 0"
    class="q-gutter-sm"
  >
    <q-table
      flat
      bordered
      :rows="filterFoundFile"
      :columns="columns"
      row-key="name"
      hide-bottom
      :rows-per-page-options="[0]"
      class="cursor"
    >
      <template v-slot:body-cell-name="nameData">
        <q-td style="width: 50%" @click="() => getFileInfo(nameData.row)">
          <file-icon size="list" :fileMimeType="nameData.row.fileType" />
          {{ nameData.row.fileName }}
        </q-td>
      </template>

      <template v-slot:body-cell-fileType="typeData">
        <q-td>
          <div class="justify-center">
            {{ getType(typeData.row.fileType) }}
          </div>
        </q-td>
      </template>

      <template v-slot:body-cell-actions="actionData">
        <q-td class="justify-center">
          <div>
            <q-icon class="q-ma-sm" name="info" size="2em" color="primary" />
            <q-tooltip
              anchor="center left"
              self="center right"
              :offset="[5, 1]"
            >
              {{ getSize(actionData.row.fileSize) }}
            </q-tooltip>
          </div>
          <div v-if="props.action">
            <q-btn
              flat
              color="positive"
              dense
              icon="edit"
              @click="
                () => triggerFileEdit(actionData.row, actionData.row.pathname)
              "
              id="listViewFileEdit"
            />
            <q-btn
              flat
              color="negative"
              dense
              icon="delete"
              @click="() => triggerFileDelete(actionData.row.pathname)"
              id="listViewFileDelete"
            />
          </div>
        </q-td>
      </template>
    </q-table>
  </div>

  <div class="q-mt-md" v-if="foundFile.length == 0">
    <span>ไม่พบรายการที่ค้นหา</span>
  </div>

  <file-form
    :mode="fileFormType"
    :error="fileFormError"
    v-model:open="fileFormState"
    v-model:title="fileFormData.title"
    v-model:description="fileFormData.description"
    v-model:keyword="fileFormData.keyword"
    v-model:category="fileFormData.category"
    @filechange="(name: string) => (fileFormError.fileExist = checkFile(name))"
    @submit="submitFileForm"
  />

  <upload-exist-dialog
    v-model:notification="fileExistNotification"
    @confirm="() => currentParam && submitFileForm(currentParam, true)"
    @cancel="() => (currentParam = undefined)"
  />

  <dialog-delete v-model:open="dialogDeleteState" @confirm="confirmDelete" />
</template>

<style scoped lang="scss">
.box {
  border: 2px solid $separator-color;
  border-radius: 8px;
  cursor: pointer;
}

.cursor {
  cursor: pointer;
}

.text-overflow-handle {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.grid {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

@media (min-width: $breakpoint-md-min) {
  .grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.grid .box {
  position: relative;
}

.justify-center {
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
