<template>
  <div class="q-pa-none flex column col-grow no-scroll">
    <pn-scroll-list>
      <template #card-body-header>
        <pn-action-bar
          v-model="search"
          placeholder="tasks__search"
          :calendar-active="showCalendar"
          :filter-active="showFiltersDialog"
          :calendar-badge="!!datesRange"
          :filter-badge="!checkFiltersSelect"
          @toggle-calendar="showCalendar = !showCalendar"
          @open-filters="showFiltersDialog = true"
        />
        <q-slide-transition>
          <div v-show="showCalendar">
            <q-date
              class="w100 fix-calendar q-mb-sm q-mt-xs"
              first-day-of-week="1"
              v-model="datesRange"
              range
              flat
              :events="tasksDates"
              event-color="brand"
              today-btn
              minimal
              dense
            />
          </div>
        </q-slide-transition>
      </template>
      <div class="w100 flex justify-end q-px-md">
        <q-btn flat dense no-caps @click="showArchiveTasks=!showArchiveTasks">
          <span class="text-caption text-grey">
            {{
              $t(!showArchiveTasks ? 'tasks__show_archive' : 'tasks__hide_archive') +
              (hiddenTask !== 0 ? ' (+' + hiddenTask +')' : '') 
            }}
          </span>
        </q-btn>
      </div>
      <q-list separator>
        <template v-for="item in displayTasks" :key="item.id">
          <q-slide-item
            @right="handleSlideRight($event, item.id)"
            @left="handleSlideLeft($event, item.id)"
            clickable
            v-ripple
            @click="goTask(item.id)"
            right-color="red"
            left-color="green"
            >
            <template #right v-if="item.status !== 6">
              <q-icon size="lg" name="mdi-clipboard-remove-outline"/>
            </template>
            <template #left v-if="item.status === 6">
              <q-icon size="lg" name="mdi-clipboard-play-outline"/>
            </template>
            <q-item
              :key="item.id"
              :style = "{
                backgroundColor: 
                  item.status === 6 
                  ? '#999'
                  : 'inherit',
                border: item.status === 6 ? 'solid 1px #999' : 'inherit'
              }"
              >
              <task-item :item/>
            </q-item>
          </q-slide-item>
        </template>
      </q-list>
    </pn-scroll-list>
    <q-page-sticky
      position="bottom-right"
      :offset="[0, 18]"
      class="fix-fab-offset"
      >
      <transition
        appear
        enter-active-class="animated zoomIn"
        >
        <q-btn
          v-if="showFab"
          fab 
          icon="add"
          color="brand"
          @click="createTask()"
        />
      </transition>
    </q-page-sticky>
  </div>

  <pn-small-dialog
    v-model="showDialogDeleteTask"
    icon="mdi-clipboard-remove-outline"
    color="negative"
    title="tasks__dialog_cancel_title"
    mainBtnLabel="tasks__dialog_cancel_ok"
    auxBtnLabel="tasks__dialog_cancel_delete"
    @clickMainBtn="onConfirmCancel()"
    @clickAuxBtn="onConfirmDelete()"
    @close="onCancel()"
    @before-hide="onDialogBeforeHide()"
  />

  <pn-small-dialog
    v-model="showDialogRestoreTask"
    icon="mdi-clipboard-play-outline"
    color="green"
    title="tasks__dialog_restore_title"
    mainBtnLabel="tasks__dialog_restore_ok"
    @clickMainBtn="onConfirmRestore()"
    @close="onCancel()"
    @before-hide="onDialogBeforeHide()"
  />

  <pn-bottom-sheet-dialog
    title="tasks__filters"
    v-model="showFiltersDialog"
    >
    <template #btnSlot>
      <div>
        <q-btn
          v-if="!checkFiltersSelect"
          @click="resetFilters"
          flat
          no-caps
          dense
          color="grey-6"
          >
          {{ $t('tasks__filters_reset')}}
        </q-btn>
      </div>
    </template>

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

    <div class="q-pl-sm text-bold text-caption">
      {{ $t('tasks__filters_by_participant') }}
    </div>

    <div class="flex column">
      <div
        v-for="(item,idx) in taskParticipantsOptions"
        :key="idx"
        >
        <q-checkbox
          v-model="filters.byParticipants"
          :val="item.value"
          >
          {{ $t(item.label) }}
        </q-checkbox>
      </div>
    </div>

    <div class="q-pl-sm q-mt-md text-bold text-caption">
      {{ $t('tasks__filters_by_priority') }}
    </div>

    <div class="flex column">
      <div
        v-for="(item,idx) in taskPriorityOptions"
        :key="idx"
        >
        <q-checkbox
          v-model="filters.byPriority"
          :val="item.value"
          >
          {{ $t(item.label) }}
        </q-checkbox>
      </div>
    </div>
  </pn-bottom-sheet-dialog>
</template>

<script setup lang="ts">
  import { ref, computed, onActivated, onDeactivated, onBeforeUnmount } from 'vue'
  import { useTasksStore } from 'stores/tasks'
  import { useUsersStore } from 'stores/users'
  import { useRouter } from 'vue-router'
  import taskItem from 'components/taskItem.vue'
  import type { Task } from 'types/Task'
  import { date } from 'quasar'
  import pnActionBar from 'components/pnActionBar.vue'

  const search = ref('')
  const showCalendar = ref<boolean>(false)
  const datesRange = ref<null | { from: string, to: string }>(null)
  const deleteTaskId = ref<number | undefined>(undefined)
  const restoreTaskId = ref<number | undefined>(undefined)
  const showDialogDeleteTask = ref<boolean>(false)
  const showDialogRestoreTask = ref<boolean>(false)
  const showFiltersDialog = ref(false)
  const showArchiveTasks = ref(false)
  const currentSlideEvent = ref<SlideEvent | null>(null)
  const closedByUserAction = ref(false)
  const tasksStore = useTasksStore()
  const usersStore = useUsersStore()
  const router = useRouter()

  interface SlideEvent {
    reset: () => void
  }

  const tasks = tasksStore.getTasks
  const tasksDates = computed(() => tasks.map(el => date.formatDate(el.plan_date * 1000, 'YYYY/MM/DD')))

  const displayTasks = computed(() => {
    return filteredTasks.value.filter(archiveTasks)

    function archiveTasks (el: Task) {
      if (showArchiveTasks.value) return true
      return (
        el.close_date < Date.now() - 7 * 24 * 60 * 60 * 1000 // показыать закрытые менее недели назад 
      )
    }
  })

  const hiddenTask = computed(() => filteredTasks.value.length - displayTasks.value.length)
  
  const filteredTasks = computed(() => {

    return tasks
      .filter(searchTasks)  
      .filter(checkDateInterval)
      .filter(byParticipants)
      .filter(byPriority)

    function searchTasks (el: Task) {
      if (!search.value || !(search.value && search.value.trim())) return true
      const searchValue = search.value.trim().toLowerCase()
      return (
        el.name.toLowerCase().includes(searchValue) ||
        el.description && el.description.toLowerCase().includes(searchValue)
      )
    }
  
    function checkDateInterval (el: Task) {
      if (!datesRange.value) return true
      const from = date.extractDate(datesRange.value.from, 'YYYY/MM/DD').getTime()
      const to = date.extractDate(datesRange.value.to, 'YYYY/MM/DD').getTime() + 86399999
      return  (from < el.plan_date * 1000) && ( to >= el.plan_date * 1000)
    }

    function byParticipants(task: Task): boolean {
      const selected = filters.value.byParticipants
      if (selected.length === 0) return true
      
      const userId = usersStore.myId.id
      return selected.some(opt => {
        switch (opt) {
          case 1: return task.assigned_to === userId
          case 2: return task.created_by === userId
          case 3: return task.observers.includes(userId)
          case 4: return task.assigned_to !== userId 
                      && task.created_by !== userId 
                      && !task.observers.includes(userId)
          default: return false
        }
      })
    }

    function byPriority (el: Task) {
      if (filters.value.byPriority.length === 0) return true
      return filters.value.byPriority.includes(el.priority)
    }
  })

  interface Filters {
    byParticipants: number[]
    byPriority: number[]
  } 
  
  const defaultFilters = {
    byParticipants: [],
    byPriority: []
  }
  
  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 taskParticipantsOptions = [
    { id: 1, value: 1, label: 'tasks__filters_to_me' },
    { id: 2, value: 2, label: 'tasks__filters_from_me' },
    { id: 3, value: 3, label: 'tasks__filters_observers' },
    { id: 4, value: 4, label: 'tasks__filters_not_involved' }
  ]

   const taskPriorityOptions = [
    { id: 0, value: 0, label: 'tasks__filters_priority_normal' },
    { id: 1, value: 1, label: 'tasks__filters_priority_important' },
    { id: 2, value: 2, label: 'tasks__filters_priority_critical' }
  ]

  async function goTask (taskId: number) {
    await new Promise(resolve => setTimeout(resolve, 300))
    await router.push({ name: 'task_info', params: { taskId }})
  }

  async function createTask () {
    await router.push({ name: 'task_add'})
  }

  function handleSlideRight (event: SlideEvent, id: number) {
    currentSlideEvent.value = event
    showDialogDeleteTask.value = true
    deleteTaskId.value = id
  }

  function handleSlideLeft (event: SlideEvent, id: number) {
    currentSlideEvent.value = event
    showDialogRestoreTask.value = true
    restoreTaskId.value = id
  }

  function onDialogBeforeHide () {
    if (!closedByUserAction.value) {
      onCancel()
    }
    closedByUserAction.value = false
  }

  function onCancel() {
    closedByUserAction.value = true
    if (currentSlideEvent.value) {
      currentSlideEvent.value.reset()
      currentSlideEvent.value = null
    }
  }

  async function onConfirmDelete() {
    closedByUserAction.value = true
    if (deleteTaskId.value) {
      await tasksStore.remove(deleteTaskId.value)
    }
    currentSlideEvent.value = null
  }

  async function onConfirmCancel() {
    closedByUserAction.value = true
    if (deleteTaskId.value) {
      await tasksStore.setCancelStatus(deleteTaskId.value)
    }
    currentSlideEvent.value = null
  }

  async function onConfirmRestore() {
    closedByUserAction.value = true
    if (restoreTaskId.value) {
      await tasksStore.setRestoreStatus(restoreTaskId.value)
    }
    currentSlideEvent.value = null
  }

  // fix fab jumping
  const showFab = ref(false)
  const timerId = ref<ReturnType<typeof setTimeout> | null>(null)

  onActivated(() => {
    timerId.value = setTimeout(() => {
      showFab.value = true
    }, 300)
  })


  onDeactivated(() => {
    showFab.value = false
    if (timerId.value) {
      clearTimeout(timerId.value)
      timerId.value = null
    }
  })

  onBeforeUnmount(() => {
    if (timerId.value) clearTimeout(timerId.value)
  })
 
</script>

<style scoped lang="scss">
   /* fix mini border after slide */
  :deep(.q-slide-item__right) {
    align-self: center;
    height: 98%;
  }

  :deep(.q-slide-item__left) {
    align-self: center;
    height: 98%;
  }

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

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