<template>
  <pn-page-card v-bind="$attrs">
    <template #card-header>
      <pn-action-bar
        v-if="files.length !== 0"
        v-model="search"
        placeholder="backup__files_search"
        :calendar-active="showCalendar"
        :filter-active="showFiltersDialog"
        :calendar-badge="!!datesRange"
        :filter-badge="!checkFiltersSelect"
        @toggle-calendar="showCalendar = !showCalendar"
        @open-filters="showFiltersDialog = true"
        style="padding-top: 0 !important;"
      />
      </template>

      <template #card-under-header>
        <transition
          enter-active-class="animated zoomIn"
          leave-active-class="animated zoomOut"
          >
          <div v-if="showCalendar" class="q-mx-md shadow-1 rounded-card">
            <q-date
              class="w100 fix-calendar rounded-card bg-grey-11"
              first-day-of-week="1"
              v-model="datesRange"
              range
              flat
              :events="filesDates"
              event-color="primary"
              today-btn
              minimal
              dense
            />
          </div>
        </transition>
    </template>

    <q-list class="w100">
      <q-item
        v-for="item in displayFiles"
        :key="item.id"
        @click="downloadFile(item.id)"
        v-ripple
        clickable
        >
        <q-item-section avatar class="items-center" >
          <q-icon
            :name="fileIcon(item.name).icon"
            :style="{ color: fileIcon(item.name).color}"
            size="md"
          />
        </q-item-section>
        <q-item-section
          :class="item.parent.type === 'chat' && item.parent.is_deleted ? 'text-strike' : ''"
          >
          <q-item-label lines="1" class="text-bold">
            <pn-cutter-long-text
              :text = item.name
              :tailLength="10" 
            />
          </q-item-label>

          <q-item-label caption lines="1">
            <pn-inline-pair
              :item1="usersStore.userNameById(item.published_by)"
              :item1Class="usersStore.userById(item.published_by)?.is_blocked ? 'text-strike' : ''"
              :item2="item.parent.name"
              :item2Icon="
                item.parent.type === 'chat'
                  ? 'mdi-chat-outline'
                  : item.parent.type === 'task'
                    ? 'mdi-clipboard-outline'
                    : 'mdi-calendar-month-outline'
              "
            />
          </q-item-label>
        </q-item-section>
        <q-item-section side class="text-caption">
          <q-item-label >
            {{ date.formatDate(item.publish_date * 1000, 'D MMM') }}
          </q-item-label>
          <q-item-label >
            {{ fileSize(item.size, $t) }}
          </q-item-label>
        </q-item-section>
      </q-item>
    </q-list>
    
    <pn-onboard-btn
      v-if="files.length === 0"
      icon="mdi-clippy"
      message1="backup__onboard_msg1"
      message2="backup__onboard_msg2"
      noBtn
    />
    
    <pn-bottom-sheet-dialog
      title="backup__filters"
      v-model="showFiltersDialog"
      >
      <template #btnSlot v-if="!checkFiltersSelect">
        <q-btn
          @click="resetFilters"
          flat
          no-caps
          dense
          color="grey-6"
          >
          {{ $t('backup__filters_reset')}}
        </q-btn>
            
        <div style="pointer-events: none; width: 0px !important; overflow: hidden;">
          <q-btn dense flat round icon="mdi-close"/>
        </div>
      </template>

      <template #footer>
        <div class="column">
          <q-btn
            rounded
            class="w100"
            color="primary"
            @click="showFiltersDialog = false"
            >
            {{$t('backup__filters_continue')}}
          </q-btn>

        </div>



      </template>

      <div class="q-px-md">
        <div class="q-pl-sm text-bold text-caption">
          {{ $t('backup__filters_extension') }}
        </div>
        <div class="flex row">
          <div
            v-for="(item,idx) in fileExtExample"
            :key="idx"
            >
            <q-icon
              :name="fileIcon(item).icon"
              :style="{ color: fileIcon(item).color }"
              @click = "updateFileExtFilters(fileIcon(item).type)"
              :class="filters.fileExt.includes(fileIcon(item).type) ? 'active' : 'inactive'"
              size="md"
              class="q-pa-sm"
            />
          </div>
        </div>

        <div class="q-pl-sm q-mt-md text-bold text-caption">
          {{ $t('backup__filters_source') }}
        </div>
        <div class="flex column">
          <div
            v-for="(item,idx) in fileSourceOptions"
            :key="idx"
            >
            <q-checkbox
              v-model="filters.fileSource"
              :val="item.value"
              >
              {{ $t(item.label) }}
            </q-checkbox>
          </div>
        </div>

        <div class="q-pl-sm q-mt-md text-bold text-caption">
          {{ $t('backup__filters_by') }}
        </div>
        <q-select
          v-model="filters.fileBy"
          :options="users"
          dense
          filled
          class="w100 q-pt-sm"
          option-value="id"
          option-label="displayName"
          emit-value
          map-options
          use-chips
          multiple
          >
          <template #option="scope">
            <q-item v-bind="scope.itemProps">
              <q-item-section avatar>
                <pn-auto-avatar
                  :img="scope.opt.photo"
                  :name="scope.opt.displayName"
                  size="md"
                />
              </q-item-section>
              <q-item-section>
                <q-item-label>{{ scope.opt.displayName }}</q-item-label>
              </q-item-section>
            </q-item>
          </template>
        </q-select>

        <div class="q-pl-sm q-mt-md text-bold text-caption">
          {{ $t('backup__filters_size') }}
        </div>
        <div class="flex column">
          <div
            v-for="(item,idx) in fileSizeOptions"
            :key="idx"
            >
            <q-checkbox
              v-model="filters.fileSize"
              :val="item.value"
              :label = "$t(item.label)"
            />
          </div>
        </div>
      </div>
    </pn-bottom-sheet-dialog>
  </pn-page-card>
</template>

<script setup lang="ts">
  import { ref, computed, inject, watch } from 'vue'
  import { storeToRefs } from 'pinia'
  import { useFilesStore } from 'stores/files'
  import { useUsersStore } from 'stores/users'
  import { useProjectsStore } from 'stores/projects'
  import pnActionBar from 'components/pnActionBar.vue'
  import pnCutterLongText from 'components/pnCutterLongText.vue'
  import pnInlinePair from 'components/pnInlinePair.vue'
  import { date } from 'quasar'
  import { fileIcon, fileSize } from 'utils/files-functions'
  import type { FileLink } from 'types/FileLink'
  import type { WebApp } from '@twa-dev/types'
     
  const tg = inject('tg') as WebApp

  const projectsStore = useProjectsStore()
  const filesStore = useFilesStore()
  const usersStore = useUsersStore()

  const files = ref<FileLink[]>([])
  const search = ref('')
  const showCalendar = ref<boolean>(false)
  const datesRange = ref<null | { from: string, to: string }>(null)
  const showFiltersDialog = ref(false)
  const { currentProjectId } = storeToRefs(projectsStore)

  const displayFiles = computed(() => {
    
    return files.value
      .filter(bySearch)
      .filter(byExt)
      .filter(bySource)
      .filter(bySize)
      .filter(byFrom)
      .filter(checkDateInterval)
      .sort((f1: FileLink, f2: FileLink) => f2.publish_date - f1.publish_date)

    function bySearch (el: FileLink) {
      if (!search.value || !(search.value && search.value.trim())) return true
      const searchValue = search.value.trim().toLowerCase()
      return el.name.toLowerCase().includes(searchValue)
    }

    function checkDateInterval (el: FileLink) {
      if (!datesRange.value) return true
      const start = (typeof datesRange.value !== 'string') ? datesRange.value.from : datesRange.value
      const end = (typeof datesRange.value !== 'string') ? datesRange.value.to : datesRange.value
      const from = date.extractDate(start, 'YYYY/MM/DD').getTime()
      const to = date.extractDate(end, 'YYYY/MM/DD').getTime() + (24 * 60 * 60 * 1000 - 1)
      return  (from < el.publish_date * 1000) && ( to >= el.publish_date * 1000)
    }

    function byExt (el: FileLink) {
      if (filters.value.fileExt.length === 0) return true
      const type = fileIcon(el.name).type
      return filters.value.fileExt.includes(type)
    }

    function bySource (el: FileLink) {
      if (filters.value.fileSource.length === 0) return true
      return filters.value.fileSource.includes(el.parent.type)
    }

    function bySize (el: FileLink) {
      if (filters.value.fileSize.length === 0) return true

      const fs = el.size
      const sortedFilters = [...filters.value.fileSize].sort((a, b) => a - b)

      const ranges = fileSizeOptions.map((option, index) => ({
        min: index === 0 ? 0 : fileSizeOptions[index - 1]!.value,
        max: option.value,
        value: option.value
      }))

      return ranges.some(range => 
        sortedFilters.includes(range.value) && 
        (fs > range.min && 
        (range.max === Infinity ? true : fs <= range.max))
      )
    }

    function byFrom (el: FileLink) {
      if (filters.value.fileBy.length === 0) return true
      return filters.value.fileBy.includes(el.published_by)
    }
  })

  interface Filters {
    fileSource: Array<'chat' | 'task' | 'meeting'>
    fileSize: number[]
    fileBy: number[]
    fileExt: string[]
  }

  const defaultFilters = {
    fileSource: [],
    fileSize: [],
    fileBy: [],
    fileExt: []
  }
  
  const filters = ref<Filters>({ ...defaultFilters })

  const checkFiltersSelect = computed(() => (
    Object.values(filters.value).every(el => el.length === 0)
  ))

  function resetFilters() {
    (Object.keys(filters.value) as (keyof Filters)[]).forEach(key => filters.value[key] = [])
  }

  const fileExtExample = [
    '1.common', '2.doc', '3.xls', '4.vsd', '5.ppt', '6.pdf', '7.png', '8.mp3', '9.mp4', '10.js', '11.txt', '12.zip', '13.skp', '14.dwg', '15.ttf'
  ]

  function updateFileExtFilters (select: string) {
    if (filters.value.fileExt.includes(select)) {
      const idx = filters.value.fileExt.indexOf(select)
      filters.value.fileExt.splice(idx, 1)
    } else filters.value.fileExt.push(select)
  }

  const fileSourceOptions = [
    { id: 1, icon: 'mdi-chat-outline', value: 'chat', label: 'backup__filters_source_chats' },
    { id: 2, icon: 'mdi-clipboard-outline', value: 'task', label: 'backup__filters_source_tasks' },
    { id: 3, icon: 'mdi-calendar-month-outline', value: 'meeting', label: 'backup__filters_source_meetings' }
  ]

  const fileSizeOptions = [
    { id: 1, value: 5242880, label: 'backup__filters_size_small' }, // 5MB
    { id: 2, value: 26214400, label: 'backup__filters_size_middle' }, // 25MB
    { id: 3, value: 104857600, label: 'backup__filters_size_big' }, // 100MB
    { id: 4, value: Infinity, label: 'backup__filters_size_very_big' } // more 100 MB
  ]
  
  const users = computed(() => usersStore.users)

  const filesDates = computed(() => displayFiles.value.map(el => date.formatDate(el.publish_date * 1000, 'YYYY/MM/DD')))

  async function downloadFile (fileId: number) {
    try {
      const fileParams = await filesStore.downloadParams(fileId)
      if (!fileParams) throw new Error('Download failed')
      tg.downloadFile(fileParams)
    } catch (error) {
      alert(error)
      console.error('Download error:', error)
    }
  }

  watch(currentProjectId, async () => {
    if (currentProjectId.value) {
      files.value = await filesStore.getFilesList(currentProjectId.value)
    }
  }, { immediate: true})
</script>

<style scoped>
  .second-line-item {
    display: flex;
    align-items: center;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 60%;
  }

  .fix-card-width {
    width: var(--body-width) !important;
  }

  .active {
    opacity: 1
  }

  .inactive {
    opacity: 0.4
  }

  .fix-calendar :deep(.q-date__view) {
    min-height: auto;
  }

  .fix-calendar :deep(.q-date__calendar-days-container) {
    min-height: auto;
  }
</style>
