<template>
  <v-row no-gutters>
    <TableMain :headers="headers" :items="items" :loading="getVisitorPending" :page="page" :pages="pages"
      :extension-height="110" :offset="300" :pageRange="pageRange" @refresh="getVisitorRefresh"
      @update:page="handleUpdatePage" show-header @row-click="handleRowClick">
      <template #actions>
        <v-row no-gutters>
          <v-btn v-if="canAddVisitor" class="text-none" rounded="pill" variant="tonal" size="large"
            @click="handleAddNew" text="Add Visitor" />
          <v-btn v-if="canScanVisitorQRCode" text="Scan QR Code" class="text-none ml-2" rounded="pill" variant="tonal"
            size="large" @click="dialog.scanVisitorQRCode = true" />
          <v-menu>
            <template #activator="{ props }">
              <v-btn v-bind="props" text="Download Report" class="text-none ml-2" prepend-icon="mdi-download"
                rounded="pill" variant="tonal" size="large" />
            </template>
            <v-list>
              <v-list-item prepend-icon="mdi-file-pdf" title="Download PDF Report" @click="handleDownloadPDFReport" />
              <v-list-item prepend-icon="mdi-file-csv" title="Download CSV Report" @click="handleDownloadCSVReport" />
            </v-list>
          </v-menu>
        </v-row>
      </template>
      <template #extension>
        <v-row no-gutters class="w-100 d-flex flex-column">
          <v-tabs v-model="activeTab" color="primary" :height="40" @update:model-value="toRoute" class="w-100">
            <v-tab v-for="tab in tabOptions" :value="tab.value" :key="tab.value" class="text-capitalize">
              {{ tab.name }}
            </v-tab>
          </v-tabs>

          <v-card class="w-100 px-3 d-flex align-center ga-5 py-2" flat :height="60">
            <v-text-field v-model="searchInput" density="compact" placeholder="Search" clearable max-width="300"
              append-inner-icon="mdi-magnify" hide-details />
            <v-checkbox v-model="displayNotCheckedOut" class="text-subtitle-2" hide-details>
              <template #label>
                <span class="text-caption">Not Checked Out</span>
              </template>
            </v-checkbox>
            <InputDatePicker v-model="dateFrom" density="compact" hide-details />
            <InputDatePicker v-model="dateTo" density="compact" hide-details />
            <v-select v-if="activeTab == 'registered'" v-model="filterTypes" label="Filter by types" item-title="label"
              item-value="value" :items="visitorSelection" density="compact" clearable multiple max-width="200"
              hide-details>
              <template v-slot:selection="{ item, index }">
                <div class="d-flex align-center text-caption text-nowrap">
                  <v-chip v-if="index === 0" color="error" :text="filterTypeSelectionLabel()" size="x-small"
                    variant="tonal" class="ml-2" />
                </div>
              </template>
            </v-select>
          </v-card>
        </v-row>
      </template>

      <template v-slot:item.name="{ item }">
        <span class="d-flex align-center ga-2">
          <span>
            <AvatarMain :name="item?.name" :size="20" :id="item?._id" />
          </span>
          <span class="text-capitalize">{{ item?.name }}</span>
        </span>
        <span class="text-grey text-caption" v-if="item?.members?.length > 0">( +{{ item?.members?.length }}
          members)</span>
      </template>

      <template v-slot:item.email="{ value }">
        {{ value ?? "N/A" }}
      </template>

      <template v-slot:item.invited-by="{ item }">
        <span class="d-flex align-center ga-2">
          <AvatarMain v-if="item?.inviterName" :name="item?.inviterName" :size="20" :id="item?._id" />
          <span class="text-capitalize">{{ item?.inviterName ?? "N/A" }}</span>
        </span>
      </template>

      <template v-slot:item.type-company="{ item }">
        <span class="d-flex align-center ga-2">
          <v-icon icon="mdi-user" size="15" />
          <span v-if="item.type === 'contractor'" class="text-capitalize">{{
            formatCamelCaseToWords(item.contractorType)
            }}</span>
          <span v-else class="text-capitalize">{{ formatType(item) }}</span>
        </span>
        <span class="d-flex align-center ga-2">
          <v-icon icon="mdi-domain" size="15" />
          <span class="text-capitalize">{{ item?.company || "N/A" }}</span>
        </span>
      </template>

      <template v-slot:item.location="{ item }">
        <span class="d-flex align-center ga-2">
          <v-icon icon="mdi-storefront-outline" size="15" />
          <span class="text-capitalize">{{
            formatLocation({
              block: item.block,
              level: item.level,
              unit: item.unit,
            })
          }}</span>
        </span>
      </template>

      <template v-slot:item.contact-vehicleNumber="{ item }">
        <span class="d-flex align-center ga-2">
          <v-icon icon="mdi-phone" size="15" />
          <span class="text-capitalize">{{ item?.contact || "N/A" }}</span>
        </span>
        <span class="d-flex align-center ga-2">
          <v-icon icon="mdi-car-back" size="15" />
          <span class="text-capitalize">{{ item?.plateNumber || "N/A" }}</span>
        </span>
      </template>

      <template v-slot:item.checkin-out="{ item }">
        <v-row no-gutters class="d-flex flex-column py-2">
          <span class="d-flex align-center ga-2">
            <v-icon icon="mdi-clock-time-four-outline" color="green" size="20" />
            <span class="text-capitalize">{{
              UTCToLocalTIme(item.checkIn) || "-"
              }}</span>
            <span>
              <v-icon v-if="item?.snapshotEntryImage" size="17" icon="mdi-image"
                @click.stop="handleViewImage(item.snapshotEntryImage)" />
            </span>
          </span>

          <span v-if="
            !item.checkOut &&
            (item?.status === 'registered' ||
              item?.status === 'unregistered') &&
            canCheckoutVisitor
          ">
            <span class="d-flex align-center ga-2" v-bind="menuProps" style="cursor: pointer">
              <v-icon icon="mdi-clock-time-eight-outline" color="red" size="20" />
              <v-btn size="x-small" class="text-capitalize" color="red" text="Checkout" :loading="loading.checkingOut && item?._id === selectedVisitorId
                " @click.stop="handleCheckout(item._id)" />
            </span>
          </span>
          <span v-else class="d-flex align-center ga-2">
            <v-icon icon="mdi-clock-time-eight-outline" color="red" size="20" />
            <template v-if="item.checkOut">
              <span class="text-capitalize">{{
                UTCToLocalTIme(item.checkOut)
                }}</span>
              <span>
                <v-icon v-if="item?.snapshotExitImage" size="17" icon="mdi-image"
                  @click.stop="handleViewImage(item.snapshotExitImage)" />
              </span>
              <span v-if="item?.manualCheckout">
                <TooltipInfo text="Manual Checkout" density="compact" size="x-small" />
              </span>
            </template>
            <template v-else> <span class="mt-1"> N/A </span> </template>
          </span>

          <div v-if="showAddPassKeyButton(item)" class="d-flex flex-wrap ga-1 mt-1" v-bind="menuProps"
            style="cursor: pointer">
            <v-chip size="x-small" variant="tonal" prepend-icon="mdi-key" @click.stop="handleOpenAddPassKey(item)">Add
              Pass/Key</v-chip>
          </div>

          <v-menu :close-on-content-click="true">
            <template v-slot:activator="{ props: menuProps }">
              <div v-if="
                (item.visitorPass?.length ?? 0) > 0 ||
                (item.passKeys?.length ?? 0) > 0
              " class="d-flex flex-wrap ga-1 mt-1" v-bind="menuProps" style="cursor: pointer">
                <v-chip v-for="pass in item.visitorPass" :key="(pass as any)._id ?? (pass as any).keyId"
                  prepend-icon="mdi-card-bulleted-outline" size="x-small" variant="tonal" color="blue">
                  {{ (pass as any)?.prefixAndName }}
                </v-chip>
                <v-chip v-for="key in item.passKeys" :key="(key as any)._id ?? (key as any).keyId"
                  prepend-icon="mdi-key" size="x-small" variant="tonal" color="orange">
                  {{ (key as any)?.prefixAndName }}
                </v-chip>
              </div>
            </template>
            <v-list density="compact">
              <v-list-item v-if="!item?.checkOut" prepend-icon="mdi-logout" title="Checkout"
                @click.stop="handleCheckout(item._id)" />
              <v-list-item v-if="
                (item.visitorPass?.length ?? 0) > 0 ||
                (item.passKeys?.length ?? 0) > 0
              " prepend-icon="mdi-card-bulleted-outline" :title="item.checkOut ? 'View Pass/Key' : 'Edit Pass/Key'"
                @click.stop="handleOpenEditPassKey(item)" />
              <v-list-item v-if="showAddPassKeyButton(item)" prepend-icon="mdi-plus" title="Add Pass/Key"
                @click.stop="handleOpenAddPassKey(item)" />
            </v-list>
          </v-menu>
        </v-row>
      </template>

      <template v-slot:item.arrival-date-time="{ item }">
        <v-row no-gutters class="d-flex flex-column py-2">
          <span class="d-flex align-center ga-2">
            <v-icon icon="mdi-calendar" size="20" />
            {{ standardFormatDate(item.expectedCheckIn) }}
          </span>
          <span class="d-flex align-center ga-2">
            <v-icon icon="mdi-clock-time-four-outline" size="20" />
            {{ item.arrivalTime ?? "N/A" }}
          </span>

          <span v-if="!item.checkIn && canUpdateVisitor">
            <span class="d-flex align-center ga-2 cursor-pointer">
              <v-icon icon="mdi-clock-time-eight-outline" color="success" size="20" />
              <v-btn size="x-small" class="text-capitalize" color="success" text="Checkin"
                @click.stop="handleCheckin(item)" />
            </span>
          </span>
        </v-row>
      </template>

      <template v-slot:item.status="{ item }">
        <v-card v-if="item?.overnightParking?.status" size="small"
          class="rounded-xl text-capitalize text-center elevation-0 py-1 px-2"
          :color="getOvernightParkingRequestStatusColor(item?.overnightParking?.status as string)"
          style="max-width: 150px; margin: auto">
          {{ item?.overnightParking?.status }}
        </v-card>
        <span v-else> N/A </span>
      </template>

      <template v-slot:item.action="{ item }">
        <v-btn v-if="activeTab === 'unregistered' && canAddVisitor" size="small" color="primary" text="Register"
          @click.stop="handleRegistrationUnregisteredVisitor(item)" />
        <v-menu v-else-if="activeTab === 'overnight-parking'">
          <template #activator="{ props }">
            <v-avatar v-bind="props" class="rounded-xl border-md">
              <v-icon icon="mdi-dots-vertical" />
            </v-avatar>
          </template>

          <v-card>
            <v-list-item v-if="
              !overNightParkingListActions[0].disabled ||
              !['approved', 'rejected'].includes(
                item?.overnightParking?.status
              )
            " @click.stop="
                openApproveRejectOverNightParkingRequestDialog(
                  item,
                  overNightParkingListActions[0].status
                )
                ">
              <template #title>
                <span class="text-caption">
                  {{ overNightParkingListActions[0].text }}
                </span>
              </template>
            </v-list-item>
            <v-divider />
            <v-list-item v-if="
              !overNightParkingListActions[1].disabled ||
              !['approved', 'rejected'].includes(
                item?.overnightParking?.status
              )
            " @click="
                openApproveRejectOverNightParkingRequestDialog(
                  item,
                  overNightParkingListActions[1].status
                )
                ">
              <template #title>
                <span class="text-caption">
                  {{ overNightParkingListActions[1].text }}
                </span>
              </template>
            </v-list-item>
            <v-list-item v-if="item?.overnightParking?.remarks" @click="
              openApproveRejectOverNightParkingRequestDialog(
                item,
                overNightParkingListActions[2].status,
                item?.overnightParking?.remarks
              )
              ">
              <template #title>
                <span class="text-caption">
                  {{ overNightParkingListActions[2].text }}
                </span>
              </template>
            </v-list-item>
            <v-divider />
          </v-card>
        </v-menu>
      </template>

      <template v-slot:item.checkInRemarks="{ item }">
        <span>
          <v-btn variant="text" color="blue-darken-2" density="compact" size="small"
            @click.stop="handleOpenRemarks(item, 'checkIn')">{{ item.checkInRemarks ? "View Remarks" : "Add Remarks"
            }}</v-btn>
        </span>
      </template>
      <template v-slot:item.checkOutRemarks="{ item }">
        <span>
          <v-btn variant="text" color="blue-darken-2" density="compact" size="small"
            @click.stop="handleOpenRemarks(item, 'checkOut')">{{ item.checkOutRemarks ? "View Remarks" : "Add Remarks"
            }}</v-btn>
        </span>
      </template>
    </TableMain>

    <v-dialog v-model="dialog.showSelection" width="450" persistent>
      <VisitorFormSelection :mode="mode" @cancel="dialog.showSelection = false" @select="handleSelectVisitorType" />
    </v-dialog>

    <v-dialog v-model="dialog.showForm" v-if="activeVisitorFormType" width="450" persistent>
      <VisitorForm :mode="mode" :org="orgId" :site="siteId" :visitor-data="selectedVisitorDataObject"
        :type="activeVisitorFormType" @back="handleClickBack" @done="handleVisitorFormDone"
        @done:more="handleVisitorFormCreateMore" @close:all="handleCloseAll" />
    </v-dialog>

    <v-dialog v-model="dialog.viewVisitor" width="450" persistent>
      <VehicleUpdateMoreAction title="Preview" :can-update="false" :can-delete="false"
        @close="dialog.viewVisitor = false" edit-button-label="Edit Visitor">
        <template v-slot:content>
          <v-row no-gutters class="mb-4">
            <v-col v-for="(label, key) in formattedFields" :key="key" cols="12">
              <span v-if="
                key === 'checkIn' &&
                !selectedVisitorObject[key] &&
                canUpdateVisitor
              " class="d-flex align-center">
                <strong>{{ label }}:</strong>
                <v-btn size="x-small" class="ml-3 text-capitalize" color="success" text="Checkin"
                  :disabled="isVisitorDataFromScannedQRCodeCheckingInOut" @click="handleCheckin(selectedVisitorObject)"
                  :loading="isVisitorDataFromScannedQRCodeCheckingInOut" />
              </span>
              <span v-if="
                key === 'checkOut' &&
                selectedVisitorObject['checkIn'] &&
                !selectedVisitorObject[key] &&
                canCheckoutVisitor
              " class="d-flex align-center">
                <strong>{{ label }}:</strong>
                <v-btn size="x-small" class="ml-3 text-capitalize" color="red" text="Checkout"
                  :disabled="loading.checkingOut" @click="handleCheckout(selectedVisitorId as string)" />
              </span>

              <span v-else-if="
                key === 'nric' && selectedVisitorObject['nric']" class="d-flex align-center">
                <strong>{{ label }}:</strong>
                <span class="ml-2">{{ maskNRIC(selectedVisitorObject[key]) }}</span>
              </span>
              <span v-else-if="key === 'attachments' && selectedVisitorObject?.[key]?.length > 0"
                class="d-flex flex-column">
                <strong class="w-full">{{ label }}:</strong>
                <div class="d-flex flex-wrap ga-2">
                  <AttachmentsViewer :files="mappedAttachments(selectedVisitorObject.attachments)" title=""
                    show-file-type-title />
                </div>
              </span>

              <span v-else-if="selectedVisitorObject[key]" class="d-flex ga-3 align-start"><strong>{{ label
                  }}:</strong>
                {{ formatValues(key, selectedVisitorObject[key]) }}
                <TooltipInfo v-if="key === 'checkOut'" text="Manual Checkout" density="compact" size="x-small" />
              </span>
            </v-col>
          </v-row>
        </template>
      </VehicleUpdateMoreAction>
    </v-dialog>

    <v-dialog v-model="dialog.snapshotImage" max-width="700">
      <v-card>
        <v-card-title class="d-flex justify-space-between align-center">
          <span>Snapshot</span>
          <v-btn icon="mdi-close" variant="text" @click="dialog.snapshotImage = false" />
        </v-card-title>
        <v-card-text class="pa-2 d-flex justify-center">
          <v-img :src="snapshotImageUrl" max-height="600" contain />
        </v-card-text>
      </v-card>
    </v-dialog>

    <v-dialog v-model="dialog.remarks" max-width="450" persistent>
      <v-card>
        <v-card-title class="d-flex justify-space-between align-center pt-4 px-4">
          <span>{{
            remarksType === "checkIn" ? "Check-In Remarks" : "Check-Out Remarks"
            }}</span>
          <v-btn icon="mdi-close" variant="text" @click="dialog.remarks = false" />
        </v-card-title>
        <v-card-text class="px-4 pb-2">
          <v-textarea v-model="remarksInput" label="Remarks" rows="4" auto-grow variant="outlined"
            :readonly="remarksViewOnly" />
        </v-card-text>
        <v-toolbar class="pa-0" density="compact">
          <v-row no-gutters>
            <v-col cols="6">
              <v-btn variant="text" block :disabled="loading.savingRemarks"
                @click="dialog.remarks = false">Cancel</v-btn>
            </v-col>
            <v-col cols="6">
              <v-btn color="primary" variant="flat" height="48" rounded="0" block :loading="loading.savingRemarks"
                :disabled="!remarksInput.trim()" @click="handleSaveRemarks">Save</v-btn>
            </v-col>
          </v-row>
        </v-toolbar>
      </v-card>
    </v-dialog>

    <v-dialog v-model="dialog.returnPassesKeys" max-width="450" persistent>
      <v-card>
        <v-toolbar density="compact" color="">
          <v-row no-gutters class="d-flex fill-height justify-space-between align-center px-4">
            <span class="font-weight-bold">Return Passes &amp; Keys</span>
            <v-btn icon="mdi-close" variant="text" @click="dialog.returnPassesKeys = false" />
          </v-row>
        </v-toolbar>
        <v-card-text class="px-4 pb-2">
          <p class="text-body-2 mb-3">
            Please ensure all passes and keys are returned before checking out.
          </p>

          <div>
            <InputLabel class="text-capitalize" title="Full Name" />
            <v-text-field v-model="selectedVisitorObject.name" density="comfortable" readonly />
          </div>

          <div>
            <InputLabel class="text-capitalize" title="Location" />
            <v-text-field v-model="selectedVisitorObject.location" density="comfortable" readonly />
          </div>

          <div v-if="passReturnStatuses.length > 0" class="mb-2">
            <p class="text-caption text-medium-emphasis mb-1">Passes</p>
            <v-row no-gutters v-for="pass in passReturnStatuses" :key="(pass as any)._id ?? (pass as any).keyId"
              class="d-flex flex-wrap justify-space-between align-center ga-5 mb-2">
              <v-chip prepend-icon="mdi-card-bulleted-outline" size="small" variant="tonal" color="blue">
                {{ (pass as any)?.prefixAndName }}
              </v-chip>
              <v-select hide-details max-width="200px" density="compact" :items="passStatusOptions" item-title="label"
                item-value="value" v-model="pass.status" :disabled="selectedVisitorObject.checkOut"></v-select>
              <v-textarea v-if="pass.status === 'Lost' || pass.status === 'Damaged'" no-resize rows="3" class="w-100"
                density="compact" v-model="pass.remarks" :disabled="selectedVisitorObject.checkOut"></v-textarea>
            </v-row>
          </div>
          <div v-if="keyReturnStatuses.length > 0" class="mb-2">
            <p class="text-caption text-medium-emphasis mb-1">Keys</p>
            <v-row no-gutters v-for="key in keyReturnStatuses" :key="(key as any)._id ?? (key as any).keyId"
              class="d-flex flex-wrap justify-space-between align-center ga-5 mb-2">
              <v-chip prepend-icon="mdi-key" size="small" variant="tonal" color="orange">
                {{ (key as any)?.prefixAndName }}
              </v-chip>
              <v-select hide-details max-width="200px" density="compact" :items="passStatusOptions" item-title="label"
                item-value="value" v-model="key.status" :disabled="selectedVisitorObject.checkOut"></v-select>
              <v-textarea v-if="key.status === 'Lost' || key.status === 'Damaged'" no-resize rows="3" class="w-100"
                density="compact" v-model="key.remarks" :disabled="selectedVisitorObject.checkOut"></v-textarea>
            </v-row>
          </div>

          <v-row no-gutters class="my-5">
            <v-btn variant="flat" color="blue" density="comfortable" class="text-capitalize"
              :disabled="selectedVisitorObject.checkOut" :loading="loading.updatingPassKeys"
              @click.stop="handleUpdatePassKeys">Update Pass/Keys</v-btn>
          </v-row>
        </v-card-text>
        <v-toolbar class="pa-0" density="compact">
          <v-row no-gutters>
            <v-col cols="6">
              <v-btn variant="text" block @click="dialog.returnPassesKeys = false">Close</v-btn>
            </v-col>
            <v-col cols="6">
              <v-btn color="red" variant="flat" height="48" rounded="0" block :loading="loading.checkingOut" :disabled="!canConfirmCheckout || selectedVisitorObject.checkOut
                " @click="proceedCheckout">Confirm Checkout</v-btn>
            </v-col>
          </v-row>
        </v-toolbar>
      </v-card>
    </v-dialog>

    <v-dialog v-model="dialog.addPassKey" width="450" persistent>
      <AddPassKeyToVisitor mode="add" :visitor="selectedVisitorDataObject" :site="siteId"
        @close="dialog.addPassKey = false" @done="
          () => {
            dialog.addPassKey = false;
            getVisitorRefresh();
          }
        " />
    </v-dialog>

    <v-dialog v-model="dialog.editPassKey" width="450" persistent>
      <AddPassKeyToVisitor mode="edit" :visitor="selectedVisitorDataObject" :site="siteId"
        @close="dialog.editPassKey = false" @done="
          () => {
            dialog.editPassKey = false;
            getVisitorRefresh();
          }
        " />
    </v-dialog>

    <ScanVisitorQRCode :dialog="dialog.scanVisitorQRCode" :site="siteId" @open-visitor-data-from-scanned-qr-code-dialog="
      handleShowVisitorDataFromScannedQRCodeDialog
    " @close-dialog="dialog.scanVisitorQRCode = false" />

    <v-dialog v-model="dialog.showVisitorDataFromScannedQRCode" width="450" persistent>
      <VisitorDataFromScannedQRCodeForm :site="siteId" :visitor-data="visitorDataFromScannedQRCode"
        @check-in-out="handleVisitorDataFromScannedQRCodeCheckInOut"
        :processing="isVisitorDataFromScannedQRCodeCheckingInOut"
        @close="handleCloseVisitorDataFromScannedQRCodeDialog" />
    </v-dialog>

    <v-dialog v-model="dialog.approveRejectOvernightParkingRequestDialog" transition="dialog-bottom-transition"
      persistent width="60vh">
      <v-card>
        <v-toolbar density="compact">
          <v-row no-gutters class="d-flex fill-height justify-space-between align-center px-4">
            <span class="font-weight-bold"> Overnight Parking Request </span>
            <v-btn icon="mdi-close" variant="text" @click="dialog.approveRejectOvernightParkingRequestDialog = false" />
          </v-row>
        </v-toolbar>
        <v-card-text class="px-4 pb-6">
          <v-row no-gutters justify="center" align-content="center">
            <v-col v-if="
              approveRejectOvernightParkingRequestDialog.status !== 'remarks'
            " cols="12" class="text-h6 text-center">
              {{
                `Are you sure you want to ${approveRejectOvernightParkingRequestDialog.text} the visitor's overnight
              parking
              request?`
              }}
            </v-col>

            <v-col cols="12" md="8" class="mt-4">
              <v-textarea v-model="overNightParkingRequestApproveRejectRemarks" label="Remarks"
                placeholder="Enter remarks" outlined rows="3" clearable :hide-details="approveRejectOvernightParkingRequestDialog.status ===
                  'remarks'
                  " :readonly="approveRejectOvernightParkingRequestDialog.status ===
                  'remarks'
                  " />
            </v-col>
          </v-row>
        </v-card-text>
        <v-toolbar v-if="approveRejectOvernightParkingRequestDialog.status !== 'remarks'" class="pa-0"
          density="compact">
          <v-row no-gutters>
            <v-col cols="6">
              <v-btn text="No" color="grey-lighten-3" variant="flat" height="48" tile block
                :disabled="isApprovingRejectingOvernightParkingRequest"
                @click="closeApproveRejectOvernightParkingDialog" />
            </v-col>
            <v-col cols="6">
              <v-btn text="Yes" color="success" variant="flat" height="48" tile block :disabled="!overNightParkingRequestApproveRejectRemarks ||
                isApprovingRejectingOvernightParkingRequest
                " @click="updateOvernightParkingRequestStatus"
                :loading="isApprovingRejectingOvernightParkingRequest" />
            </v-col>
          </v-row>
        </v-toolbar>
      </v-card>
    </v-dialog>

    <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
  </v-row>
</template>

<script setup lang="ts">
import moment from "moment-timezone";

definePageMeta({
  middleware: ["01-auth", "02-org"],
});

const { downloadPDF } = usePDFDownload();

const props = defineProps({
  canAddVisitor: {
    type: Boolean,
    default: true,
  },
  canScanVisitorQRCode: {
    type: Boolean,
    default: true,
  },
  canViewVisitor: {
    type: Boolean,
    default: true,
  },
  canUpdateVisitor: {
    type: Boolean,
    default: true,
  },
  canCheckoutVisitor: {
    type: Boolean,
    default: true,
  },
});

const { authenticate, currentUser } = useLocalAuth();
authenticate();

const {
  getVisitors,
  visitorSelection,
  typeFieldMap,
  updateVisitor,
  visitorDataFromScannedQRCodeCheckIn,
} = useVisitor();
const {
  debounce,
  formatCamelCaseToWords,
  formatDate,
  UTCToLocalTIme,
  standardFormatDate,
  maskNRIC,
} = useUtils();
const { formatLocation } = useSecurityUtils();
const { getFileUrlAnpr } = useFile();
// const { status: visitorStatus, search } = useRoute().query as { status: string, search: string};

const route = useRoute();
const router = useRouter();
const { org: orgId, site: siteId } = route.params as {
  org: string;
  site: string;
};
const routeName = route.name;

const items = ref<Array<Record<string, any>>>([]);
const page = ref(1);
const pages = ref(0);
const pageRange = ref("-- - -- of --");
const activeTab = ref("registered");
const activeVisitorFormType = ref<TVisitorType | null>(null);
const selectedVisitorId = ref<string | null>(""); // selected visitor for viewing/actions

//filter states
const searchInput = ref("");

const today = new Date();
const oneMonthAgo = new Date();
oneMonthAgo.setMonth(today.getMonth() - 1);

const dateTo = ref(normalizeDateOnly(today.toISOString()));
const dateFrom = ref(normalizeDateOnly(oneMonthAgo.toISOString()));

const filterTypes = ref<TVisitorType[]>([]);
const displayNotCheckedOut = ref<boolean>(false);
const mode = ref<"add" | "edit" | "register">("add");

const message = ref("");
const messageColor = ref("");
const messageSnackbar = ref(false);

const loading = reactive({
  fetchingVisitors: false,
  checkingIn: false,
  checkingOut: false,
  savingRemarks: false,
  updatingPassKeys: false,
});

const dialog = reactive({
  showSelection: false,
  showForm: false,
  viewVisitor: false,
  snapshotImage: false,
  remarks: false,
  returnPassesKeys: false,
  addPassKey: false,
  editPassKey: false,
  scanVisitorQRCode: false,
  showVisitorDataFromScannedQRCode: false,
  approveRejectOvernightParkingRequestDialog: false,
});

const snapshotImageUrl = ref("");
const remarksType = ref<"checkIn" | "checkOut">("checkIn");
const remarksInput = ref("");
const remarksViewOnly = ref(false);

const headers = computed(() => {
  const tab = activeTab.value;

  // 1. Define the specific headers for Overnight Parking
  if (tab === "overnight-parking") {
    return [
      { title: "Name", value: "name" },
      { title: "Email", value: "email" },
      { title: "Invited By", value: "invited-by" },
      { title: "Arrival Date/Time", value: "arrival-date-time" },
      { title: "Check In/Out", value: "checkin-out" },
      { title: "Status", value: "status" },
      { title: "Action", value: "action" },
    ];
  }

  // 2. Define logic for all other tabs
  const list = [{ title: "Name", value: "name" }];

  // Standard info for non-parking tabs
  list.push(
    { title: "Type/Company", value: "type-company" },
    { title: "Location", value: "location" },
    { title: "Contact/Vehicle No.", value: "contact-vehicleNumber" }
  );

  // Conditional logic for Guests vs Others
  if (tab === "guests") {
    list.push({ title: "Arrival Date/Time", value: "arrival-date-time" });
  } else {
    list.push({ title: "Check In/Out", value: "checkin-out" });
  }

  // Specific additions
  if (tab === "resident-transactions") {
    list.push(
      { title: "Check-in Remarks", value: "checkInRemarks" },
      { title: "Check-out Remarks", value: "checkOutRemarks" }
    );
  }

  if (tab === "unregistered") {
    list.push({ title: "Action", value: "action" });
  }

  return list;
});

const tabOptions = [
  { name: "Registered", value: "registered" },
  { name: "Unregistered", value: "unregistered" },
  { name: "Guests", value: "guests" },
  { name: "Resident Transactions", value: "resident-transactions" },
  { name: "Overnight Parking", value: "overnight-parking" },
];

function getOvernightParkingRequestStatusColor(status: string) {
  switch (status) {
    case "approved":
      return "success";
    case "rejected":
      return "error";
    default:
      return "grey";
  }
}

const overNightParkingListActions = [
  {
    text: "Approve",
    status: "approved",
    disabled: props.canUpdateVisitor,
  },
  {
    text: "Reject",
    status: "rejected",
    disabled: props.canUpdateVisitor,
  },
  {
    text: "View Remarks",
    status: "remarks",
  },
];
const overNightParkingRequestApproveRejectRemarks = ref("");
const approveRejectOvernightParkingRequestDialog = ref({
  text: "",
  status: "",
});
const selectedOvernightParkingRequest = ref<Record<string, any>>({});

function openApproveRejectOverNightParkingRequestDialog(
  visitor: Record<string, any>,
  status: string,
  remarks?: string
) {
  selectedOvernightParkingRequest.value = visitor;
  approveRejectOvernightParkingRequestDialog.value = {
    text: status === "approved" ? "Approve" : "Reject",
    status,
  };
  dialog.approveRejectOvernightParkingRequestDialog = true;
  overNightParkingRequestApproveRejectRemarks.value = remarks ?? "";
}

const isApprovingRejectingOvernightParkingRequest = ref(false);

async function updateOvernightParkingRequestStatus() {
  isApprovingRejectingOvernightParkingRequest.value = true;
  try {
    await visitorDataFromScannedQRCodeCheckIn({
      type: "overnight-parking",
      filter: {
        _id: selectedOvernightParkingRequest.value._id,
      },
      update: {
        status: approveRejectOvernightParkingRequestDialog.value.status,
        remarks: overNightParkingRequestApproveRejectRemarks.value ?? "",
        updatedBy: currentUser.value?._id,
      },
      userType: "site",
    });
    showMessage(
      `Visitor's overnight parking request successfully ${approveRejectOvernightParkingRequestDialog.value.status}`,
      "success"
    );
    await getVisitorRefresh();
    closeApproveRejectOvernightParkingDialog();
  } catch (error) {
    showMessage(errorConverter(error), "error");
  } finally {
    isApprovingRejectingOvernightParkingRequest.value = false;
  }
}

function closeApproveRejectOvernightParkingDialog() {
  dialog.approveRejectOvernightParkingRequestDialog = false;
  selectedVisitorId.value = "";
  approveRejectOvernightParkingRequestDialog.value = { text: "", status: "" };
  overNightParkingRequestApproveRejectRemarks.value = "";
}

function mappedAttachments(attachments: string[]) {
  return attachments.map((x, index) => {
    return {
      id: x,
      name: `Attachment ${index + 1}`
    }
  });
}

function normalizeDateOnly(value: string) {
  if (!value) return "";
  if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return value;

  const parsedDate = new Date(value);
  if (Number.isNaN(parsedDate.getTime())) return "";

  const year = parsedDate.getFullYear();
  const month = String(parsedDate.getMonth() + 1).padStart(2, "0");
  const day = String(parsedDate.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}

const selectedVisitorDataObject = computed(() => {
  return items.value.find((x: any) => x?._id === selectedVisitorId.value) || {};
});

const formatType = (item: any) =>
  (item.deliveryType ? item.deliveryType + "-" : "") + item.type;

const formattedFields = {
  name: "Name",
  nric: "NRIC",
  contact: "Phone Number",
  plateNumber: "Vehicle Number",
  company: "Company",
  block: "Block",
  level: "Level",
  unit: "Unit",
  checkIn: "Check In",
  snapshotEntryImage: "Entry Image",
  checkOut: "Check Out",
  snapshotExitImage: "Exit Image",
  remarks: "Remarks",
  attachments: "Attachments",
} as const;

function filterTypeSelectionLabel() {
  const length = filterTypes.value.length;
  return `${length} selected ${length === 1 ? "type" : "types"}` as string;
}

const passStatusOptions = [
  { label: "Returned", value: "Returned" },
  { label: "Not Returned", value: "In Use" },
  { label: "Damaged", value: "Damaged" },
  { label: "Lost", value: "Lost" },
];

function toRoute(tab: any) {
  items.value = [];

  const obj = tabOptions.find((x) => x.value === tab);
  if (!obj) return;
  page.value = 1;
  getVisitorRefresh();
  // navigateTo({
  //   name: routeName,
  //   params: {
  //     org: orgId,
  //   },
  //   // query: {
  //   //   tab
  //   // },
  // });
}
const {
  data: getVisitorReq,
  refresh: getVisitorRefresh,
  pending: getVisitorPending,
} = await useLazyAsyncData(
  "get-all-visitors",
  async () => {
    const params: any = {
      page: page.value,
      site: siteId,
      search: searchInput.value,
      dateTo: dateTo.value
        ? moment(dateTo.value).endOf("day").toISOString()
        : undefined,
      dateFrom: dateFrom.value
        ? moment(dateFrom.value).startOf("day").toISOString()
        : undefined,
      type:
        filterTypes.value.length === 0 && activeTab.value === "registered"
          ? "contractor,delivery,walk-in,pick-up,drop-off,guest"
          : filterTypes.value.filter(Boolean).join(","),
      checkedOut: displayNotCheckedOut.value ? false : undefined,
    };

    if (activeTab.value === "guests") {
      params.type = "guest";
      params.status = "approved";
    } else if (activeTab.value === "resident-transactions") {
      params.status = "registered";
      params.type = "resident,tenant";
    } else if (activeTab.value === "overnight-parking") {
      params.tab = "Overnight Parking";
    } else {
      params.status = activeTab.value;
    }

    // if (activeTab.value !== "registered") {
    //   delete params.type;
    //   delete params.checkedOut;
    // }

    return await getVisitors(params);
  },
  {
    watch: [
      page,
      searchInput,
      dateFrom,
      dateTo,
      filterTypes,
      activeTab,
      displayNotCheckedOut,
    ],
    immediate: true,
  }
);

watch(getVisitorReq, (newData: any) => {
  if (newData) {
    items.value = newData.items ?? [];
    // items.value = [{ _id: "testid", name: "John Doe", type: "Contractor", company: "ABC Corp", location: "Block A, Level 1, Unit 101", contact: "12345678", plateNumber: "SGX1234A", checkIn: new Date().toISOString(), checkOut: null, status: "registered", visitorPass: [{ _id: "1", keyId: "pass1", prefixAndName: "VIP Pass" }, { _id: "2", keyId: "pass2", prefixAndName: "VIP Pass 2" }], passKeys: [{ _id: "1", keyId: "key2", prefixAndName: "Master Key" }] }];
    pages.value = newData.pages ?? 0;
    pageRange.value = newData?.pageRange ?? "-- - -- of --";
  }
});

const selectedVisitorObject = computed<Record<string, any>>(() => {
  const obj = items.value.find((x: any) => x?._id === selectedVisitorId.value);
  if (!obj) return {};

  const type = obj?.type as TVisitorType | undefined;

  let includedKeys: string[] = [
    "checkIn",
    "checkOut",
    "plateNumber",
    "snapshotEntryImage",
    "snapshotExitImage",
  ];
  includedKeys.unshift(...(typeFieldMap[type] ?? []));

  let locationString = "N/A";

  if (obj?.block?.name || obj?.level?.name || obj?.unitName) {
    locationString = `${obj.block?.name} / ${obj.level?.name} / ${obj.unitName}`;
  } else if (obj?.block?.name) {
    locationString = obj.block?.name;
  } else {
    locationString = "N/A";
  }

  return {
    ...Object.fromEntries(
      Object.entries(obj).filter(([key]) => includedKeys.includes(key))
    ),
    location: locationString,
  };
});

function formatValues(key: string, value: any) {
  if (!value) return "";
  switch (key) {
    case "unit":
      return value?.name;
    case "block":
      return value?.name;
    case "level":
      return value?.name;
    case "checkIn":
      return formatDate(value);
    case "checkOut":
      return formatDate(value);
  }

  return value;
}

const visitorDataFromScannedQRCode = ref<Record<string, any>>({});

function handleShowVisitorDataFromScannedQRCodeDialog(
  scannedData: Record<string, any>
) {
  visitorDataFromScannedQRCode.value = scannedData;

  const { checkIn, checkOut, _id, visitorPass } = scannedData;
  const hasPasses = (visitorPass?.length ?? 0) > 0;

  // 1. If they are checked in and HAVE passes/keys, go to the Return screen
  if (checkIn && !checkOut && hasPasses) {
    handleCheckout(_id);
    return;
  }

  // 2. Default Case: Show visitor data (Entry, already checked out, or checked in with no passes)
  dialog.showVisitorDataFromScannedQRCode = true;
}

const isVisitorDataFromScannedQRCodeCheckingInOut = ref(false);

async function handleVisitorDataFromScannedQRCodeCheckInOut(
  type: string,
  visitorData: Record<string, any>
) {
  try {
    isVisitorDataFromScannedQRCodeCheckingInOut.value = true;
    if (type != "checkOut") {
      await visitorDataFromScannedQRCodeCheckIn({
        type,
        filter: {
          _id: visitorData._id,
        },
        update: {
          updatedBy: currentUser.value._id,
          visitorPass: visitorData.visitorPass.find(
            (i: Record<string, any>) => i.keyId === null
          )
            ? undefined
            : visitorData.visitorPass,
          nric: visitorData.nric ?? "",
          plateNumber: visitorData.plateNumber ?? "",
        },
        userType: "site",
      });
      showMessage("Visitor successfully checked-in!", "info");
    } else {
      selectedVisitorId.value = visitorData._id;
      await proceedCheckout();
    }
    handleCloseVisitorDataFromScannedQRCodeDialog();
    getVisitorRefresh();
    dialog.viewVisitor = false;
  } catch (error) {
    showMessage(errorConverter(error), "error");
  } finally {
    isVisitorDataFromScannedQRCodeCheckingInOut.value = false;
  }
}

function handleCloseVisitorDataFromScannedQRCodeDialog() {
  dialog.showVisitorDataFromScannedQRCode = false;
  visitorDataFromScannedQRCode.value = {};
}

function handleAddNew() {
  dialog.showSelection = true;
  activeVisitorFormType.value = null;
  mode.value = "add";
}

function handleRowClick(data: any) {
  selectedVisitorId.value = data?.item?._id;
  dialog.viewVisitor = true;
}

function handleUpdatePage(newPageNum: number) {
  page.value = newPageNum;
}

function showAddPassKeyButton(item: any) {
  const hasPasses = (item?.visitorPass?.length ?? 0) > 0;
  const hasKeys = (item?.passKeys?.length ?? 0) > 0;

  const isTypeWithPassKey = ["contractor", "guest", "walk-in"].includes(
    item?.type
  );

  return (
    !hasPasses &&
    !hasKeys &&
    isTypeWithPassKey &&
    item?.status === "registered" &&
    !item?.checkOut
  );
}

function handleSelectVisitorType(type: TVisitorType) {
  dialog.showSelection = false;
  dialog.showForm = true;
  activeVisitorFormType.value = type;
}

function handleClickBack() {
  dialog.showSelection = true;
  dialog.showForm = false;
}

function handleVisitorFormDone() {
  getVisitorRefresh();
  dialog.showSelection = false;
  dialog.showForm = false;
}

function handleVisitorFormCreateMore() {
  getVisitorRefresh();
  dialog.showSelection = true;
  dialog.showForm = false;
}

function showMessage(msg: string, color: string) {
  message.value = msg;
  messageColor.value = color;
  messageSnackbar.value = true;
}

function handleCloseAll() {
  dialog.showSelection = false;
  dialog.showForm = false;
}

function handleRegistrationUnregisteredVisitor(item: Partial<TVisitor>) {
  const id = item?._id || null;
  selectedVisitorId.value = id;
  dialog.showSelection = true;
  mode.value = "register";
}

function handleViewImage(imageId: string) {
  const imageEndpoint = `${siteId}/${imageId}`;
  snapshotImageUrl.value = getFileUrlAnpr(imageEndpoint);
  dialog.snapshotImage = true;
}

function handleOpenAddPassKey(item: any) {
  selectedVisitorId.value = item?._id;
  dialog.addPassKey = true;
}

function handleOpenEditPassKey(item: any) {
  selectedVisitorId.value = item?._id;
  if (selectedVisitorDataObject.value.checkOut) {
    dialog.returnPassesKeys = true;
    handleCheckout(selectedVisitorId.value as string);
  } else dialog.editPassKey = true;
}

function handleOpenRemarks(item: any, type: "checkIn" | "checkOut") {
  selectedVisitorId.value = item?._id;
  remarksType.value = type;
  const existingRemarks =
    type === "checkIn" ? item?.checkInRemarks : item?.checkOutRemarks;
  remarksInput.value = existingRemarks || "";
  remarksViewOnly.value = !!existingRemarks;
  dialog.remarks = true;
}

async function handleSaveRemarks() {
  if (!remarksInput.value.trim() || !selectedVisitorId.value) return;
  try {
    loading.savingRemarks = true;
    const payload =
      remarksType.value === "checkIn"
        ? { checkInRemarks: remarksInput.value.trim() }
        : { checkOutRemarks: remarksInput.value.trim() };
    await updateVisitor(selectedVisitorId.value, payload);
    showMessage("Remarks saved successfully!", "info");
    await getVisitorRefresh();
    dialog.remarks = false;
  } catch (error: any) {
    const errorMessage = error?.response?._data?.message;
    showMessage(
      errorMessage || "Something went wrong. Please try again later.",
      "error"
    );
  } finally {
    loading.savingRemarks = false;
  }
}

async function handleUpdatePassKeys() {
  if (!selectedVisitorId.value) return;
  try {
    loading.updatingPassKeys = true;
    const payload: any = {};
    if (passReturnStatuses.value.length > 0) {
      const passReturnStatusesPayload = passReturnStatuses.value.map((p) => ({
        keyId: p.keyId,
        status: p.status,
        remarks: p.remarks,
      }));
      payload.visitorPass = passReturnStatusesPayload;
    }
    if (keyReturnStatuses.value.length > 0) {
      const keyReturnStatusesPayload = keyReturnStatuses.value.map((k) => ({
        keyId: k.keyId,
        status: k.status,
        remarks: k.remarks,
      }));
      payload.passKeys = keyReturnStatusesPayload;
    }
    await updateVisitor(selectedVisitorId.value, payload);
    showMessage("Pass/Key statuses updated successfully!", "info");
    await getVisitorRefresh();
  } catch (error: any) {
    const errorMessage = error?.response?._data?.message;
    showMessage(
      errorMessage || "Something went wrong. Please try again later.",
      "error"
    );
  } finally {
    loading.updatingPassKeys = false;
  }
}

const passReturnStatuses = ref<
  { keyId: string; status: string; prefixAndName: string; remarks: string }[]
>([]);
const keyReturnStatuses = ref<
  { keyId: string; status: string; prefixAndName: string; remarks: string }[]
>([]);

const canConfirmCheckout = computed(() => {
  const allEntries = [...passReturnStatuses.value, ...keyReturnStatuses.value];
  return allEntries.every((entry) => {
    if (!entry.status || entry.status === "In Use") return false;
    if (
      (entry.status === "Lost" || entry.status === "Damaged") &&
      !entry.remarks.trim()
    )
      return false;
    return true;
  });
});

function handleCheckin(user: Record<string, any>) {
  visitorDataFromScannedQRCode.value = user;
  dialog.showVisitorDataFromScannedQRCode = true;
}

function handleCheckout(userId: string) {
  if (!userId) {
    showMessage("Invalid userId", "error");
    return;
  }
  selectedVisitorId.value = userId;

  const visitor = items.value.find((x: any) => x?._id === userId);
  const hasPasses = (visitor?.visitorPass?.length ?? 0) > 0;
  const hasKeys = (visitor?.passKeys?.length ?? 0) > 0;

  if (hasPasses || hasKeys) {
    const visitor = items.value.find((x: any) => x?._id === userId);
    passReturnStatuses.value = ((visitor?.visitorPass as any[]) || []).map(
      (p: any) => ({
        keyId: p.keyId,
        status: p.status ?? "In Use",
        remarks: "",
        prefixAndName: p.prefixAndName,
      })
    );
    keyReturnStatuses.value = ((visitor?.passKeys as any[]) || []).map(
      (k: any) => ({
        keyId: k.keyId,
        status: k.status ?? "In Use",
        remarks: "",
        prefixAndName: k.prefixAndName,
      })
    );
    dialog.returnPassesKeys = true;
    return;
  }

  proceedCheckout();
}

async function proceedCheckout() {
  const userId = selectedVisitorId.value;
  if (!userId) return;

  try {
    loading.checkingOut = true;

    const passReturnStatusesPayload = passReturnStatuses.value.map((p) => ({
      keyId: p.keyId,
      status: p.status,
      remarks: p.remarks,
    }));
    const keyReturnStatusesPayload = keyReturnStatuses.value.map((k) => ({
      keyId: k.keyId,
      status: k.status,
      remarks: k.remarks,
    }));

    const res = await updateVisitor(userId as string, {
      checkOut: new Date().toISOString(),
      ...(passReturnStatuses.value.length > 0
        ? { visitorPass: passReturnStatusesPayload }
        : {}),
      ...(keyReturnStatuses.value.length > 0
        ? { passKeys: keyReturnStatusesPayload }
        : {}),
    });
    if (res) {
      showMessage("Visitor successfully checked-out!", "info");
      await getVisitorRefresh();
      dialog.viewVisitor = false;
      dialog.returnPassesKeys = false;
    }
  } catch (error: any) {
    const errorMessage = error?.response?._data?.message;
    console.log("[ERROR]", error);
    showMessage(
      errorMessage || "Something went wrong. Please try again later.",
      "error"
    );
  } finally {
    loading.checkingOut = false;
  }
}

function buildReportParams(): any {
  const params: any = {
    site: siteId,
    search: searchInput.value,
    dateTo: dateTo.value
      ? moment(dateTo.value).endOf("day").toISOString()
      : undefined,
    dateFrom: dateFrom.value
      ? moment(dateFrom.value).startOf("day").toISOString()
      : undefined,
    type:
      filterTypes.value.length === 0 && activeTab.value === "registered"
        ? "contractor,delivery,walk-in,pick-up,drop-off,guest"
        : filterTypes.value.filter(Boolean).join(","),
    checkedOut: displayNotCheckedOut.value ? false : undefined,
    limit: 100,
  };

  if (activeTab.value === "guests") {
    params.type = "guest";
    params.status = "approved";
  } else if (activeTab.value === "resident-transactions") {
    params.status = "registered";
    params.type = "resident,tenant";
  } else if (activeTab.value === "overnight-parking") {
    params.tab = "Overnight Parking";
  } else {
    params.status = activeTab.value;
  }

  if (activeTab.value !== "registered") {
    delete params.type;
    delete params.checkedOut;
  }

  return params;
}

async function handleDownloadPDFReport() {
  try {
    showMessage("Generating PDF report...", "info");

    // Build URL with query parameters
    const queryParams = new URLSearchParams();
    if (searchInput.value) queryParams.append("search", searchInput.value);
    if (dateFrom.value) queryParams.append("dateFrom", dateFrom.value);
    if (dateTo.value) queryParams.append("dateTo", dateTo.value);
    if (filterTypes.value.length > 0)
      queryParams.append("type", filterTypes.value.join(","));
    if (activeTab.value) queryParams.append("tab", activeTab.value);
    if (displayNotCheckedOut.value) queryParams.append("checkedOut", "true");

    const queryString = queryParams.toString();
    const url = `/${route.params.org}/${siteId}/visitor-management/preview${queryString ? "?" + queryString : ""
      }`;
    const title = `Visitor-Report-${siteId}-${new Date().toISOString().split("T")[0]
      }`;

    await downloadPDF({ url, title, orientation: "P", appKey: "SECURITY" });
    showMessage("PDF report downloaded successfully!", "success");
  } catch (error) {
    showMessage("Error downloading PDF report", "error");
  }
}

async function handleDownloadCSVReport() {
  try {
    showMessage("Generating CSV report...", "info");

    const params = buildReportParams();

    const reportData = await getVisitors(params);
    const csvData = generateCSVData(reportData.items ?? []);
    downloadCSVFile(csvData);
    showMessage("CSV report downloaded successfully!", "success");
  } catch (error) {
    showMessage("Error downloading CSV report", "error");
  }
}

function generateCSVData(visitors: any[]): string {
  const headers = [
    "NAME",
    "TYPE",
    "COMPANY",
    "BLOCK",
    "LEVEL",
    "UNIT",
    "CONTACT",
    "VEHICLE NO.",
    "CHECK-IN",
    "CHECK-OUT",
    "CHECK-IN IMAGE",
    "CHECK-OUT IMAGE",
  ];

  const formatExportTypes = (type: string) => {
    if (!type || type === "null") return "";
    if (type === "guest") return "Drive In";
    const typeParts = type.split("-");
    return typeParts.map((part) => formatCamelCaseToWords(part)).join("-");
  };

  const rows = visitors.map((visitor) => [
    visitor.name || "",
    formatExportTypes(formatType(visitor)) || "",
    visitor.company || "",
    visitor.block || "",
    visitor.level || "",
    visitor.unitName || "",
    visitor.contact || "",
    visitor.plateNumber || "",
    formatDate(visitor.checkIn) || "",
    formatDate(visitor.checkOut) || "",
    visitor.snapshotEntryImage
      ? getFileUrlAnpr(`${siteId}/${visitor.snapshotEntryImage}`)
      : "",
    visitor.snapshotExitImage
      ? getFileUrlAnpr(`${siteId}/${visitor.snapshotExitImage}`)
      : "",
  ]);

  const csvContent = [
    headers.map((h) => `"${h}"`).join(","),
    ...rows.map((row) =>
      row
        .map((cell) => {
          const cellStr = String(cell || "");
          return `"${cellStr.replace(/"/g, '""')}"`;
        })
        .join(",")
    ),
  ].join("\n");

  return csvContent;
}

function downloadCSVFile(csvContent: string) {
  const now = new Date();
  const dateStr = now.toISOString().split("T")[0];
  const timeStr = now.toTimeString().split(" ")[0].replace(/:/g, "_");
  const filename = `VISITOR_MANAGEMENT_CSV_REPORT_${activeTab.value}_${dateStr}_${timeStr}.csv`;

  const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
  const link = document.createElement("a");
  const url = URL.createObjectURL(blob);

  link.setAttribute("href", url);
  link.setAttribute("download", filename);
  link.style.visibility = "hidden";

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

const updateRouteQuery = debounce(
  // (search: string, from: string, to: string, types: string[], status, checkedOut) => {
  ({
    search,
    from,
    to,
    types,
    tab,
    checkedOut,
  }: {
    search: string;
    from: string;
    to: string;
    types: string[];
    tab: string;
    checkedOut: boolean;
  }) => {
    router.replace({
      query: {
        ...route.query,
        search: search || undefined,
        dateFrom: from || undefined,
        dateTo: to || undefined,
        type: types.filter(Boolean).join(",") || undefined,
        tab: tab || undefined,
        ...(checkedOut === true
          ? { checkedOut: "true" }
          : { checkedOut: undefined }),
      },
    });
  },
  500 // wait 500ms after last input
);

watch(
  [searchInput, dateFrom, dateTo, filterTypes, activeTab, displayNotCheckedOut],
  ([search, from, to, types, tab, checkedOut]) => {
    const normalizedFrom = normalizeDateOnly(from);
    const normalizedTo = normalizeDateOnly(to);
    dateFrom.value = normalizedFrom;
    dateTo.value = normalizedTo;

    // updateRouteQuery(search, from, to, types, status, checkedOut)
    updateRouteQuery({
      search,
      from: normalizedFrom,
      to: normalizedTo,
      types,
      tab,
      checkedOut,
    });
    // getVisitorRefresh();
  },
  { deep: true }
);
watch([searchInput, dateFrom, dateTo, filterTypes, activeTab], () => {
  page.value = 1;
});

onMounted(() => {
  activeTab.value = (route.query.tab as string) || "unregistered";
  searchInput.value = (route.query.search as string) || "";
  if (route.query.dateFrom) {
    dateFrom.value = normalizeDateOnly(route.query.dateFrom as string);
  }
  if (route.query.dateTo) {
    dateTo.value = normalizeDateOnly(route.query.dateTo as string);
  }
  if (activeTab.value === "registered") {
    filterTypes.value = ((route.query.type as string)?.split(",") || []).filter(
      Boolean
    ) as TVisitorType[];

    displayNotCheckedOut.value =
      (route.query.checkedOut as string) == "true" || false;
  }
});
</script>

<style scoped></style>
