<template>
  <v-row no-gutters align="center" justify="center">
    <v-col cols="12">
      <TableMain
        :title="tableTitle"
        :items="items"
        :headers="headers"
        :loading="loading"
        :show-header="true"
        v-model:page="page"
        :pages="pages"
        :pageRange="pageRange"
        :no-data-text="noDataText"
        @refresh="getTaskRefresh"
        :canCreate="canCreateArea"
        :createLabel="createLabel"
        @create="onCreateItem"
        @row-click="handleRowClick"
      >
        <template #extension>
          <v-row no-gutters class="w-100 d-flex flex-column">
            <v-card
              class="w-100 px-3 d-flex align-center ga-5 py-2"
              flat
              :height="60"
            >
              <v-select
                v-model="areaTypeFilter"
                :items="typeOptions"
                density="compact"
                hide-details
                class="mx-2"
                style="max-width: 160px"
                item-title="title"
                item-value="value"
                label="Type"
              />
            </v-card>
          </v-row>
        </template>

        <template #item.type="{ item }">
          <span class="text-capitalize">{{ item.type }}</span>
        </template>
        <template #actions>
          <v-row no-gutters align="center" class="w-100">
            <v-col cols="auto">
              <div class="d-flex align-center">
                <!-- Primary action -->
                <v-btn
                  v-if="canCreateArea"
                  class="text-none mr-3"
                  rounded="pill"
                  variant="tonal"
                  size="large"
                  @click="onCreateItem"
                >
                  {{ createLabel }}
                </v-btn>

                <!-- Secondary actions as icon buttons with tooltips -->
                <v-tooltip v-if="canCreateArea" location="top">
                  <template #activator="{ props: t }">
                    <v-btn
                      v-bind="t"
                      class="ma-1"
                      variant="tonal"
                      size="large"
                      rounded="pill"
                      href="/files/area-sample-data.xlsx"
                      target="_blank"
                      download
                    >
                      <v-icon>mdi-download</v-icon>
                    </v-btn>
                  </template>
                  <span>Download Template</span>
                </v-tooltip>

                <v-tooltip v-if="canImportArea" location="top">
                  <template #activator="{ props: t }">
                    <v-btn
                      v-bind="t"
                      class="ma-1"
                      variant="tonal"
                      size="large"
                      rounded="pill"
                      @click="onImportData"
                    >
                      <v-icon>mdi-upload</v-icon>
                    </v-btn>
                  </template>
                  <span>Import Data</span>
                </v-tooltip>

                <v-tooltip v-if="canViewAreas" location="top">
                  <template #activator="{ props: t }">
                    <v-btn
                      v-bind="t"
                      class="ma-1"
                      variant="tonal"
                      size="large"
                      rounded="pill"
                      @click="handleDownloadExcel"
                      :loading="isDownloading"
                    >
                      <v-icon>mdi-file-excel</v-icon>
                    </v-btn>
                  </template>
                  <span>Download Excel</span>
                </v-tooltip>
              </div>
            </v-col>

            <v-spacer />

            <v-col cols="auto">
              <v-text-field
                v-model="searchInput"
                density="compact"
                placeholder="Search"
                clearable
                width="300"
                append-inner-icon="mdi-magnify"
                hide-details
              />
            </v-col>
          </v-row>
        </template>

        <template #type="{ item }">
          <span class="text-capitalize">{{ item.type }}</span>
        </template>
      </TableMain>
    </v-col>
  </v-row>

  <AreaFormDialog
    v-model="dialogShowForm"
    v-model:name="itemName"
    v-model:type="itemType"
    v-model:set="itemSet"
    v-model:units="itemUnits"
    :mode="dialogMode"
    :areaData="editingItem"
    :label="formLabel"
    :entityType="entityTypeLabel"
    :showUnits="true"
    :site="props.site"
    :serviceType="props.serviceType"
    @saved="_createArea"
  />

  <v-dialog v-model="dialogShowMoreActions" width="400" persistent>
    <HygieneUpdateMoreAction
      :title="selectedItem?.name || `${entityTypeLabel} Actions`"
      :canUpdate="canUpdateArea"
      :canDelete="canDeleteArea"
      :showQrButton="isToiletLocation"
      @close="dialogShowMoreActions = false"
      @edit="onEditFromMoreAction"
      @delete="onDeleteFromMoreAction"
      @manage="onManageFromMoreAction"
      @showqr="onShowQRAction"
    >
      <template #content>
        <v-row no-gutters>
          <v-col v-if="selectedItem" cols="12" class="mb-2">
            <v-row no-gutters class="mb-2">
              <v-col cols="5" class="text-subtitle-2 font-weight-bold">
                Name:
              </v-col>
              <v-col cols="7" class="text-subtitle-2">
                {{ selectedItem.name || "N/A" }}
              </v-col>
            </v-row>

            <v-row no-gutters class="mb-2">
              <v-col cols="5" class="text-subtitle-2 font-weight-bold">
                Type:
              </v-col>
              <v-col cols="7" class="text-subtitle-2 text-capitalize">
                {{ selectedItem.type || "N/A" }}
              </v-col>
            </v-row>

            <v-row no-gutters class="mb-2">
              <v-col cols="5" class="text-subtitle-2 font-weight-bold">
                No. of Visits:
              </v-col>
              <v-col cols="7" class="text-subtitle-2">
                {{ selectedItem.set || "N/A" }}
              </v-col>
            </v-row>

            <v-row
              v-if="selectedItem.units && selectedItem.units.length > 0"
              no-gutters
              class="mb-2"
            >
              <v-col cols="5" class="text-subtitle-2 font-weight-bold">
                Units:
              </v-col>
              <v-col cols="7" class="text-subtitle-2">
                <div
                  v-for="(unit, idx) in selectedItem.units"
                  :key="idx"
                  class="mb-1"
                >
                  {{ unit.name || unit }}
                </div>
              </v-col>
            </v-row>
          </v-col>

          <v-col v-if="message" cols="12" class="my-2">
            <span class="text-subtitle-2 text-error">{{ message }}</span>
          </v-col>
        </v-row>
      </template>
    </HygieneUpdateMoreAction>
  </v-dialog>

  <v-dialog v-model="dialogDeleteItem" max-width="450">
    <v-card>
      <v-toolbar>
        <v-row no-gutters class="fill-height px-6" align="center">
          <span class="font-weight-bold text-h6 text-capitalize">
            Delete {{ selectedItem?.name || entityTypeLabel }}
          </span>
        </v-row>
      </v-toolbar>
      <v-card-text>
        <span class="text-subtitle-2"
          >Are you sure you want to delete this {{ entityTypeLabel }}?</span
        >
      </v-card-text>

      <v-toolbar class="pa-0" density="compact">
        <v-row no-gutters>
          <v-col cols="6" class="pa-0">
            <v-btn
              block
              variant="text"
              class="text-none"
              size="large"
              @click="dialogDeleteItem = false"
              height="48"
            >
              Cancel
            </v-btn>
          </v-col>

          <v-col cols="6" class="pa-0">
            <v-btn
              block
              variant="flat"
              color="black"
              class="text-none font-weight-bold rounded-0"
              height="48"
              :loading="submitting"
              @click="_deleteItem"
            >
              Delete
            </v-btn>
          </v-col>
        </v-row>
      </v-toolbar>
    </v-card>
  </v-dialog>

  <v-dialog v-if="isToiletLocation" v-model="dialogShowQR" max-width="500">
    <v-card>
      <v-toolbar>
        <v-row no-gutters class="fill-height px-6" align="center">
          <span class="font-weight-bold text-h6 text-capitalize">
            QR Code for {{ selectedItem?.name || "Toilet Location" }}
          </span>
        </v-row>
      </v-toolbar>
      <v-card-text class="d-flex justify-center pa-6">
        <v-row no-gutters class="d-flex justify-center">
          <v-col cols="12" class="text-center">
            <div v-if="qrLoading" class="d-flex flex-column align-center">
              <v-progress-circular indeterminate color="primary" size="64" />
              <p class="text-subtitle-2 mt-4">Generating QR Code...</p>
            </div>
            <div v-else-if="qrError" class="d-flex flex-column align-center">
              <v-icon size="80" color="error" class="mb-4">
                mdi-alert-circle
              </v-icon>
              <p class="text-subtitle-2 text-error">{{ qrError }}</p>
            </div>
            <div v-else-if="qrPath" class="d-flex flex-column align-center">
              <div>
                <QrcodeVue
                  :value="qrPath"
                  :level="'M'"
                  :render-as="'canvas'"
                  :size="300"
                  style="display: block"
                />
              </div>
              <p class="text-caption mt-3 text-grey">
                Scan this QR code to access the cleaning schedule
              </p>
            </div>
          </v-col>
        </v-row>
      </v-card-text>

      <v-toolbar class="pa-0" density="compact">
        <v-row no-gutters>
          <v-col cols="6" class="pa-0">
            <v-btn
              block
              variant="text"
              class="text-none"
              size="large"
              @click="dialogShowQR = false"
              height="48"
            >
              Cancel
            </v-btn>
          </v-col>

          <v-col cols="6" class="pa-0">
            <v-btn
              block
              variant="flat"
              color="black"
              class="text-none font-weight-bold rounded-0"
              height="48"
              :loading="qrLoading"
              @click="onDownloadQrCode"
            >
              Download
            </v-btn>
          </v-col>
        </v-row>
      </v-toolbar>
    </v-card>
  </v-dialog>

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

  <input
    ref="fileInput"
    type="file"
    accept=".csv,.xlsx,.xls"
    style="display: none"
    @change="onFileSelected"
  />
</template>

<script setup lang="ts">
import QrcodeVue from "qrcode.vue";
import useAreas from "../composables/useAreas";
import useUnits from "../composables/useUnits";
import useSiteSettings from "../composables/useSiteSettings";
import useUtils from "../composables/useUtils";

const props = defineProps({
  orgId: { type: String, default: "" },
  site: { type: String, default: "" },
  type: { type: String, default: "" },
  serviceType: { type: String, default: "" },
  scheduleRoute: { type: String, default: "cleaning-schedule" },
  canViewAreas: { type: Boolean, default: true },
  canCreateArea: { type: Boolean, default: false },
  canUpdateArea: { type: Boolean, default: false },
  canDeleteArea: { type: Boolean, default: false },
  canImportArea: { type: Boolean, default: false },
});

const isCleanerArea = computed(() => {
  return props.type === "cleaner";
});

const isToiletArea = computed(() => {
  return props.type === "toilet";
});

const isToiletLocation = computed(() => {
  return selectedItem.value?.type?.toLowerCase() === "toilet";
});

const isScheduledArea = computed(() => {
  return props.type === "schedule-task";
});

const areaTypeFilter = ref<TAreaType>("all");
const typeOptions = [
  { title: "All", value: "all" },
  { title: "Common", value: "common" },
  { title: "Toilet", value: "toilet" },
];

const entityTypeLabel = computed(() => {
  if (isToiletArea.value) return "toilet location";
  return "area";
});

const formLabel = computed(() => {
  if (isToiletArea.value) return "Toilet Location Name";
  return "Area Name";
});

const tableTitle = computed(() => {
  if (isToiletArea.value) return `${siteName.value} Toilet Location`;
  return `${siteName.value} Areas`;
});

const createLabel = computed(() => {
  if (isToiletArea.value) return "Add Toilet Location";
  return "Add Area";
});

const noDataText = computed(() => {
  if (isToiletArea.value)
    return `No toilet location found for ${siteName.value}.`;
  return `No areas found for ${siteName.value}.`;
});

const items = ref<Array<Record<string, any>>>([]);
const siteName = ref<string>("");
const submitting = ref(false);
const isDownloading = ref(false);

const headers = [
  { title: "AREA", value: "name" },
  { title: "TYPE", value: "type" },
  { title: "SETS", value: "set" },
];

const { debounce } = useUtils();

const {
  getAreas,
  createArea,
  updateArea,
  deleteArea,
  uploadAreas,
  getAreaById,
  exportAreas,
} = useAreas();

const { getSiteById } = useSiteSettings();

const { getUnits } = useUnits();

const searchInput = ref("");
const page = ref(1);
const pages = ref(0);
const pageRange = ref("-- - -- of --");

const {
  data: getTaskReq,
  refresh: getTaskRefresh,
  pending: loading,
} = await useLazyAsyncData(
  `get-all-task`,
  () =>
    getAreas({
      page: page.value,
      site: props.site,
      search: searchInput.value,
      type: areaTypeFilter.value === "all" ? undefined : areaTypeFilter.value,
      serviceType: props.serviceType,
    }),
  {
    watch: [page, () => props.site, () => props.type, areaTypeFilter],
  }
);

watchEffect(() => {
  if (getTaskReq.value) {
    items.value = getTaskReq.value.items;
    pages.value = getTaskReq.value.pages;
    pageRange.value = getTaskReq.value.pageRange;
  }
});

const debounceSearch = debounce(getTaskRefresh, 500);

watch(
  [searchInput],
  () => {
    debounceSearch();
  },
  { immediate: false, deep: true }
);

const selectedItem = ref<Record<string, any> | null>(null);
const message = ref("");
const messageSnackbar = ref(false);
const messageColor = ref("");
const fileInput = ref<HTMLInputElement | null>(null);

const dialogShowMoreActions = ref(false);
const dialogShowForm = ref(false);
const dialogDeleteItem = ref(false);
const dialogShowQR = ref(false);
const dialogMode = ref<"add" | "edit">("add");

const allUnits = ref<Array<Record<string, any>>>([]);

watch(
  [dialogShowForm, () => props.site],
  async ([isOpen, siteId]) => {
    if (isOpen && siteId) {
      try {
        const response = await getUnits({
          site: siteId,
          limit: 100,
          serviceType: props.serviceType,
        });
        allUnits.value = response?.items || [];
      } catch {
        allUnits.value = [];
      }
    }
  }
);

const editingItem = ref<Record<string, any>>({});
const itemName = ref("");
const itemType = ref("");
const itemSet = ref(1);
const itemUnits = ref<string[]>([]);

const qrPath = ref("");
const qrLoading = ref(false);
const qrError = ref("");

watch(
  () => props.site,
  async (val) => {
    if (!val) {
      siteName.value = "";
      return;
    }

    try {
      const siteResp = await getSiteById(val);
      siteName.value = (siteResp && (siteResp.name || siteResp.title)) || val;
    } catch (err) {
      siteName.value = val;
    }
  },
  { immediate: true }
);

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

const canCreateArea = computed(() => props.canCreateArea);
const canUpdateArea = computed(() => props.canUpdateArea);
const canDeleteArea = computed(() => props.canDeleteArea);
const canImportArea = computed(() => props.canImportArea);
const canViewAreas = computed(() => props.canViewAreas);

async function handleDownloadExcel() {
  try {
    isDownloading.value = true;

    if (!props.site || !/^[0-9a-fA-F]{24}$/.test(props.site)) {
      showMessage("Invalid site id for export.", "error");
      return;
    }

    const excelBuffer = await exportAreas(props.site, props.serviceType);

    if (!excelBuffer) {
      showMessage("Failed to download areas.", "error");
      return;
    }

    const blob = new Blob([excelBuffer], {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");

    const date = new Date();
    const formattedDate = `${String(date.getMonth() + 1).padStart(
      2,
      "0"
    )}-${String(date.getDate()).padStart(2, "0")}-${date.getFullYear()}`;

    a.href = url;
    a.download = `areas-${siteName.value || "export"}-${formattedDate}.xlsx`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);

    showMessage("Areas exported successfully.", "success");
  } catch (error: any) {
    showMessage(error?.message || "Failed to download areas.", "error");
  } finally {
    isDownloading.value = false;
  }
}

function onImportData() {
  fileInput.value?.click();
}

async function onFileSelected(event: Event) {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0];

  if (!file) return;

    try {
      submitting.value = true;
      const response = await uploadAreas(file, props.site, props.serviceType);
      showMessage(response?.message, "success");

      await getTaskRefresh();
    } catch (err: any) {
      showMessage(err?.data?.message, "error");
    } finally {
      submitting.value = false;
      if (target) target.value = "";
    }
}

function onCreateItem() {
  dialogMode.value = "add";
  editingItem.value = {};
  itemName.value = "";
  itemType.value = "";
  itemSet.value = 1;
  itemUnits.value = [];
  dialogShowForm.value = true;
}

const units = computed(() => {
  return itemUnits.value.map((unitId) => {
    const unit = allUnits.value.find((u: any) => (u._id || u.id) === unitId);

    return {
      unit: unit?._id || unit?.id || "",
      name: unit?.name || "",
    };
  });
});

async function _createArea() {
  submitting.value = true;
  try {
    const payload: TAreaCreate = {
      name: itemName.value,
      set: itemSet.value,
      type: (itemType.value || "common").toLowerCase(),
      units: units.value,
      serviceType: props.serviceType,
    };

    let response;

    if (dialogMode.value === "edit" && editingItem.value) {
      const id =
        (editingItem.value as any)._id || (editingItem.value as any).id;
      if (!id)
        throw new Error(`Invalid ${entityTypeLabel.value} id for update`);
      response = await updateArea(id, payload);
      showMessage(response?.message, "success");
    } else {
      response = await createArea(payload, props.site);
      showMessage(response?.message, "success");
      await getTaskRefresh();
    }

    showMessage(response?.message, "success");
    dialogShowForm.value = false;
    editingItem.value = {};
    itemType.value = "";
    itemUnits.value = [];

    await getTaskRefresh();
  } catch (error: any) {
    console.error(error);
    showMessage(error?.message, "error");
  } finally {
    submitting.value = false;
  }
}

function editItem(item: Record<string, any> | null) {
  if (!item) return;
  dialogMode.value = "edit";
  editingItem.value = item;
  itemName.value = item.name || "";
  itemType.value = item.type || "common";
  itemSet.value =
    typeof item.set === "string" ? parseInt(item.set, 10) : item.set || 1;

  if (item.units && Array.isArray(item.units)) {
    itemUnits.value = item.units.map((u: any) => {
      if (u.unit) return u.unit;

      return u._id || u.id;
    });
  } else {
    itemUnits.value = [];
  }
  dialogShowForm.value = true;
}

async function handleRowClick(data: any) {
  const item = data?.item;
  const areaId = item?._id || item?.id;

  if (!areaId) {
    selectedItem.value = item;
    dialogShowMoreActions.value = true;
    message.value = "";
    return;
  }

  try {
    submitting.value = true;
    const areaData = await getAreaById(areaId);
    selectedItem.value = areaData;
    dialogShowMoreActions.value = true;
    message.value = "";
  } catch (error: any) {
    selectedItem.value = item;
    dialogShowMoreActions.value = true;
    message.value = error?.message || "Failed to load area details";
  } finally {
    submitting.value = false;
  }
}

const onEditFromMoreAction = async () => {
  dialogShowMoreActions.value = false;

  const areaId =
    (selectedItem.value as any)?._id || (selectedItem.value as any)?.id;
  if (areaId) {
    try {
      loading.value = true;
      const areaData = await getAreaById(areaId);
      editItem(areaData);
    } catch (error: any) {
      showMessage(error?.message || "Failed to fetch area data", "error");
    } finally {
      loading.value = false;
    }
  } else {
    editItem(selectedItem.value);
  }
};

const onManageFromMoreAction = () => {
  dialogShowMoreActions.value = false;
  const id =
    (selectedItem.value as any)?._id || (selectedItem.value as any)?.id;
  if (id) {
    let path = "";
    if (isToiletArea.value) {
      path = `/${props.orgId}/${props.site}/toilet-checklist/toilet/${id}`;
    } else {
      path = `/${props.orgId}/${props.site}/${props.scheduleRoute}/area/${id}`;
    }
    navigateTo(path);
  } else {
    console.error(`No ${entityTypeLabel.value} ID found for navigation`);
  }
};

const onDeleteFromMoreAction = () => {
  dialogShowMoreActions.value = false;
  dialogDeleteItem.value = true;
};

const onShowQRAction = () => {
  dialogShowMoreActions.value = false;
  dialogShowQR.value = true;
  qrLoading.value = false;
  qrError.value = "";

  const id =
    (selectedItem.value as any)?._id || (selectedItem.value as any)?.id;
  const runtimeConfig = useRuntimeConfig ? useRuntimeConfig() : undefined;
  const origin =
    runtimeConfig?.public?.APP_HYGIENE ||
    (typeof window !== "undefined" && window.location?.origin
      ? window.location.origin
      : "https://hygiene.app.iservice365.org");
  qrPath.value = `${origin}/${props.orgId}/${
    props.site
  }/cleaning-schedule?qrcode=true&id=${encodeURIComponent(
    id
  )}&site=${encodeURIComponent(props.site)}`;
};

async function onDownloadQrCode() {
  if (!qrPath.value) {
    showMessage("QR code URL not available", "error");
    return;
  }

  const areaName = selectedItem.value?.name || "toilet-location";
  const filename = `qr-${areaName.toLowerCase().replace(/\s+/g, "-")}`;
  const siteDisplay = siteName.value || props.site || "";
  const title = siteDisplay;
  const subtitle = selectedItem.value?.name || "";

  try {
    qrLoading.value = true;
    const config = useRuntimeConfig();
    const apiBase = config.public.API_BASE_URL || "";

    // Fetch the PDF from the API
    const downloadUrl = `${apiBase}/api/hygiene-qr/generate?url=${encodeURIComponent(
      qrPath.value
    )}&filename=${encodeURIComponent(filename)}&title=${encodeURIComponent(
      title
    )}&subtitle=${encodeURIComponent(subtitle)}&download=true`;

    const response = await fetch(downloadUrl);

    if (!response.ok) {
      throw new Error(`Failed to generate QR code: ${response.statusText}`);
    }

    // Get the PDF blob
    const blob = await response.blob();

    // Create a download link and trigger it
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = `${filename}.pdf`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url);

    showMessage("QR code downloaded successfully", "success");
  } catch (error: any) {
    console.error("Failed to download QR code:", error);
    showMessage(error?.message || "Failed to download QR code", "error");
  } finally {
    qrLoading.value = false;
  }
}

async function _deleteItem() {
  if (!selectedItem.value) return;

  try {
    submitting.value = true;
    const id =
      (selectedItem.value as any)._id || (selectedItem.value as any).id;
    if (!id) throw new Error(`Invalid ${entityTypeLabel.value} id`);

    const response = await deleteArea(id);
    dialogDeleteItem.value = false;
    showMessage(response?.message, "success");

    await getTaskRefresh();
  } catch (err: any) {
    showMessage(err?.message, "error");
  } finally {
    submitting.value = false;
  }
}
</script>
