<script setup lang="ts">
import { endOfDay, format } from 'date-fns'
import exportFromJSON from 'export-from-json'
import { VDataTable } from 'vuetify/labs/VDataTable'

const { t } = useI18n()

const headers = computed(() => [
  { title: '', key: 'data-table-expand' },
  { title: t('Store'), key: 'storeName' },
  { title: t('WSK'), key: 'wkstnId' },
  { title: t('Level'), key: 'logLevel' },
  { title: t('Category'), key: 'loggerCategory' },
  { title: t('Thread'), key: 'threadName' },
  { title: t('Date'), key: 'createDate' },
  { title: t('User'), key: 'createUserId' },
])

const selectedStore = ref(null)
const selectedWkStn = ref(null)
const selectedLogLevel = ref(null)
const selectedCategory = ref(null)
const selectedDateRange = ref(null)
const searchQuery = ref('')

const isSnackbarExport = ref(false)
const isSnackbarRange = ref(false)

// Data table options
const options = ref({ page: 1, itemsPerPage: 10, sortBy: ['createDate'], sortDesc: [true] })
const isLoading = ref(false)
interface dtListDataType {
  businessDate: string
  createDate: Date
  createUserId: string
  rtlLocId: number
  wkstnId: number
  logLevel: string
  threadName: string
  logMessage: string
  loggerCategory: string
  storeName: string
}
const dtListData = ref<dtListDataType[]>([])
const levelCounts = reactive({ INFO: 0, WARN: 0, ERROR: 0, FATAL: 0 })

const widgetData = computed(() => [
  { title: 'INFO', value: levelCounts.INFO, icon: 'tabler-info-circle' },
  { title: 'WARN', value: levelCounts.WARN, icon: 'tabler-alert-triangle' },
  { title: 'ERRROR', value: levelCounts.ERROR, icon: 'tabler-exclamation-circle' },
  { title: 'FATAL', value: levelCounts.FATAL, icon: 'tabler-bug' },
])

const fetchData = async () => {
  isLoading.value = true
  isSnackbarExport.value = false
  isSnackbarRange.value = false

  const rangeDate = selectedDateRange.value || ''
  let beginDate
  let endDate

  if (rangeDate.length === 8) {
    beginDate = rangeDate.substring(0, 8)
    endDate = beginDate
  }
  else if (rangeDate.length > 0) {
    beginDate = rangeDate.substring(0, 8)
    endDate = rangeDate.substring(rangeDate.length - 8)
  }
  else {
    beginDate = format(endOfDay(new Date()), 'yyyyMMdd')
    endDate = beginDate
  }

  let paramUrl = `?beginDate=${beginDate}&endDate=${endDate}`

  if (selectedStore && selectedStore.value) {
    const matchedStore: dtListDataType | undefined = dtListData.value.find((item: dtListDataType) => item.storeName === selectedStore.value)

    if (matchedStore && matchedStore.rtlLocId)
      paramUrl += `&storeId=${matchedStore.rtlLocId}`
  }

  if (selectedWkStn && selectedWkStn.value)
    paramUrl += `&wkstnId=${selectedWkStn.value}`

  if (searchQuery.value)
    paramUrl += `&searchText=${searchQuery.value}`

  levelCounts.INFO = 0
  levelCounts.WARN = 0
  levelCounts.ERROR = 0
  levelCounts.FATAL = 0

  if (beginDate !== endDate && (searchQuery.value.length < 5)) {
    isSnackbarRange.value = true
    dtListData.value = []
  }
  else {
    const response = await useApi<any>(createUrl(`/xadmin/log${paramUrl}`))

    if (response.data.value) {
      dtListData.value = response.data.value

      // Calculate the number of occurrences of each level
      dtListData.value.forEach((item: { logLevel: string }) => {
        const logLevel = item.logLevel as keyof typeof levelCounts

        if (logLevel in levelCounts)
          levelCounts[logLevel]++
      })
    }
    else { dtListData.value = [] }
  }

  isLoading.value = false
}

const store = computed(() => {
  const allItems = dtListData.value.map(({ storeName, rtlLocId }: { storeName: any; rtlLocId: any }) => ({ storeName, rtlLocId }))

  const uniqueItems = allItems.filter((item: any, index: any, self: any[]) =>
    // eslint-disable-next-line @typescript-eslint/no-shadow
    index === self.findIndex(t => (
      t.storeName === item.storeName && t.rtlLocId === item.rtlLocId
    )),
  )

  const sortedItems = uniqueItems.sort((a: { rtlLocId: number }, b: { rtlLocId: number }) => a.rtlLocId - b.rtlLocId)

  return sortedItems.map(({ storeName }: { storeName: any }) => ({ title: storeName, value: storeName }))
})

const wkstn = computed(() => {
  const allItems = dtListData.value.map((list: { wkstnId: any }) => list.wkstnId)
  // eslint-disable-next-line @typescript-eslint/no-shadow
  const uniqueItems = allItems.filter((wkstn: any, index: any, self: string | any[]) => self.indexOf(wkstn) === index)
  const sortedItems = uniqueItems.sort()

  return sortedItems.map((list: any) => ({ title: list, value: list }))
})

const level = computed(() => {
  const allItems = dtListData.value.map((list: { logLevel: any }) => list.logLevel)
  // eslint-disable-next-line @typescript-eslint/no-shadow
  const uniqueItems = allItems.filter((level: any, index: any, self: string | any[]) => self.indexOf(level) === index)
  const sortedItems = uniqueItems.sort()

  return sortedItems.map((list: any) => ({ title: list, value: list }))
})

const category = computed(() => {
  const allItems = dtListData.value.map((list: { loggerCategory: any }) => list.loggerCategory)
  // eslint-disable-next-line @typescript-eslint/no-shadow
  const uniqueItems = allItems.filter((category: any, index: any, self: string | any[]) => self.indexOf(category) === index)
  const sortedItems = uniqueItems.sort()

  return sortedItems.map((list: any) => ({ title: list, value: list }))
})

const filteredLogList = computed(() => {
  let filtered = dtListData.value

  // If a store is selected, filter the records for this store
  if (selectedStore.value !== undefined && selectedStore.value !== null)
    filtered = filtered.filter((list: { storeName: any }) => list.storeName === selectedStore.value)

  // If a workstation is selected, filter the records for this number
  if (selectedWkStn.value !== undefined && selectedWkStn.value !== null)
    filtered = filtered.filter((list: { wkstnId: any }) => list.wkstnId === selectedWkStn.value)

  // If a loglevel is selected, filter the records for this Loglevel
  if (selectedLogLevel.value !== undefined && selectedLogLevel.value !== null)
    filtered = filtered.filter((list: { logLevel: any }) => list.logLevel === selectedLogLevel.value)

  // If a loggerCategory is selected, filter the records for this loggerCategory
  if (selectedCategory.value !== undefined && selectedCategory.value !== null)
    filtered = filtered.filter((list: { loggerCategory: any }) => list.loggerCategory === selectedCategory.value)

  // If a search query is provided, filter the records for this query
  if (searchQuery.value) {
    filtered = filtered.filter((log: { [s: string]: unknown } | ArrayLike<unknown>) =>
      Object.values(log).some(value =>
        String(value).toLowerCase().includes(searchQuery.value.toLowerCase()),
      ),
    )
  }

  return filtered
})

const ExcelField = [
  'rtlLocId',
  'storeName',
  'wkstnId',
  'logLevel',
  'threadName',
  'logMessage',
  'loggerCategory',
  'createDate',
  'createUserId',
]

const ExcelData = computed(() => {
  return dtListData.value.map((item: dtListDataType) => {
    const orderedItem: { [key: string]: string } = {}

    ExcelField.forEach(field => {
      if (field === 'createDate') {
        const date = new Date(item[field as keyof dtListDataType])

        orderedItem[field] = format(date, 'dd/MM/yyyy HH:mm:ss')
      }
      else {
        orderedItem[field] = String(item[field as keyof dtListDataType])
      }
    })

    return orderedItem
  })
})

const exportEXCEL = () => {
  const fileName = `LOGS_XADMIN-${format(new Date(), 'yyyyMMdd')}`

  if (ExcelData.value.length > 0) {
    exportFromJSON({
      data: ExcelData.value,
      fileName,
      exportType: exportFromJSON.types.xls,
    })
  }
  else {
    isSnackbarExport.value = true
  }
}
</script>

<template>
  <VBreadcrumbs
    class="px-0 py-2"
    :items="[
      { title: t('Home'), to: { name: 'root' } },
      { title: t('Logs list') },
    ]"
  />
  <div>
    <!-- 👉 Statistics Widgets -->
    <VCard class="mb-6">
      <VCardText>
        <VRow>
          <template
            v-for="(data, id) in widgetData"
            :key="id"
          >
            <VCol
              cols="12"
              sm="6"
              md="3"
              class="px-6"
            >
              <div class="d-flex justify-space-between">
                <div class="d-flex flex-column gap-y-1">
                  <h4
                    class="text-h4 text-high-emphasis"
                    :class="{ 'text-error': id === 3 }"
                  >
                    {{ data.value }}
                  </h4>
                  <div class="text-body-1 text-capitalize">
                    {{ data.title }}
                  </div>
                </div>

                <VAvatar
                  color="rgba(var(--v-theme-on-background), var(--v-hover-opacity))"
                  rounded
                  class="text-high-emphasis"
                  size="38"
                >
                  <VIcon
                    :icon="data.icon"
                    size="26"
                  />
                </VAvatar>
              </div>
            </VCol>
            <VDivider
              v-if="$vuetify.display.mdAndUp ? id !== widgetData.length - 1
                : $vuetify.display.smAndUp ? id % 2 === 0
                  : false"
              vertical
              inset
            />
          </template>
        </VRow>
      </VCardText>
    </VCard>
    <!-- 👉 filters -->
    <VCard
      :title="$t('Filters')"
      class="mb-6"
    >
      <VCardText>
        <VRow>
          <!-- 👉 Select workstation -->
          <VCol
            cols="12"
            sm="4"
          >
            <AppSelect
              v-model="selectedStore"
              :placeholder="$t('Store')"
              :items="store"
              clearable
              clear-icon="tabler-x"
            />
          </VCol>

          <!-- 👉 Select workstation -->
          <VCol
            cols="12"
            sm="2"
          >
            <AppSelect
              v-model="selectedWkStn"
              :placeholder="$t('WorkStation')"
              :items="wkstn"
              clearable
              clear-icon="tabler-x"
            />
          </VCol>

          <!-- 👉 Select log level -->
          <VCol
            cols="12"
            sm="2"
          >
            <AppSelect
              v-model="selectedLogLevel"
              :placeholder="$t('Level')"
              :items="level"
              clearable
              clear-icon="tabler-x"
            />
          </VCol>

          <!-- 👉 Select logger category -->
          <VCol
            cols="12"
            sm="4"
          >
            <AppSelect
              v-model="selectedCategory"
              :placeholder="$t('loggerCategory')"
              :items="category"
              clearable
              clear-icon="tabler-x"
            />
          </VCol>
        </VRow>
        <VRow>
          <!-- 👉 Date log  -->
          <VCol sm="4">
            <AppDateTimePicker
              v-model="selectedDateRange"
              label=""
              :placeholder="$t('Select date')"
              :config="{ mode: 'range', altFormat: 'J M Y', altInput: true, dateFormat: 'Ymd' }"
            />
          </VCol>
        </VRow>
      </VCardText>
    </VCard>
    <!-- 👉 datatable, search & export & reload -->
    <VCard
      :title="$t('Logs list')"
      class="mb-6"
    >
      <div class="d-flex flex-wrap gap-4 mx-5">
        <div class="d-flex align-center">
          <!-- 👉 Search  -->
          <AppTextField
            v-model="searchQuery"
            :placeholder="$t('Search')"
            density="compact"
            style="inline-size: 200px;"
            class="me-3"
          />
        </div>
        <VSpacer />
        <div class="d-flex gap-1 flex-wrap aalign-center">
          <!-- 👉 Export button -->
          <VBtn
            variant="tonal"
            color="primary"
            prepend-icon="tabler-upload"
            @click="exportEXCEL"
          >
            Export
          </VBtn>
        </div>
        <div class="d-flex gap-4 flex-wrap align-center">
          <VBtn
            color="primary"
            prepend-icon="tabler-reload"
            @click="fetchData"
          >
            {{ t("Reload") }}
          </VBtn>
        </div>
      </div>

      <VDivider class="mt-4" />

      <VCol cols="12">
        <div v-if="isLoading">
          <VProgressCircular
            indeterminate
            color="primary"
          />
        </div>
        <!-- 👉 Datatable  -->
        <VDataTable
          v-else
          class="dt-row-striped"
          :headers="headers"
          :items="filteredLogList"
          :items-per-page="options.itemsPerPage"
          :page="options.page"
          :options="options"
          density="compact"
          expand-on-click
        >
          <!-- format date log -->
          <template #item.createDate="{ item }">
            {{ format(new Date(item.createDate), 'dd/MM/yyyy HH:mm:ss') }}
          </template>

          <!-- format business date -->
          <template #item.businessDate="{ item }">
            {{ format(new Date(item.businessDate), 'dd/MM/yyyy') }}
          </template>

          <!-- Expanded Row Data -->
          <template #expanded-row="slotProps">
            <tr class="v-data-table__tr">
              <td :colspan="headers.length">
                <p class="my-1">
                  {{ slotProps.item.logMessage }}
                </p>
              </td>
            </tr>
          </template>
        </VDataTable>
      </VCol>
    </VCard>
  </div>
  <!-- Snackbar Export -->
  <VSnackbar
    v-model="isSnackbarExport"
    location="center"
  >
    {{ $t('ExcelData is empty, cannot export') }}

    <template #actions>
      <VBtn
        color="error"
        @click="isSnackbarExport = false"
      >
        {{ $t("Close") }}
      </VBtn>
    </template>
  </VSnackbar>
  <!-- Snackbar Export -->
  <VSnackbar
    v-model="isSnackbarRange"
    location="center"
  >
    {{ $t('Dates range error') }}

    <template #actions>
      <VBtn
        color="error"
        @click="isSnackbarRange = false"
      >
        {{ $t("Close") }}
      </VBtn>
    </template>
  </VSnackbar>
</template>
