<template>
  <v-row no-gutters class="pa-0">
    <v-col cols="12" class="mb-2">
      <v-row no-gutters align="center">
        <v-col cols="12" md="6" class="d-flex align-center">
          <v-btn
            class="text-none me-2"
            rounded="pill"
            variant="tonal"
            size="large"
            @click="setDocument()"
            v-if="canCreate && canCreateDocument"
          >
            Add Document
          </v-btn>

          <v-btn
            class="text-none"
            rounded="pill"
            variant="tonal"
            size="large"
            @click="openCreateFolderDialog()"
            v-if="canCreate && canCreateFolder"
          >
            Create Folder
          </v-btn>
        </v-col>

        <v-col
          cols="12"
          md="6"
          class="d-flex justify-end align-center mt-4 mt-md-0"
        >
          <v-text-field
            v-model="search"
            placeholder="Search"
            density="comfortable"
            variant="outlined"
            hide-details
            rounded="lg"
            class="me-3"
            style="max-width: 220px"
          />

          <v-menu v-model="filterMenu" offset-y>
            <template #activator="{ props }">
              <v-btn
                v-bind="props"
                variant="outlined"
                rounded="lg"
                class="filtertype-btn text-none"
                style="max-width: 220px"
              >
                {{ selectedFileType || "Filter by File Type" }}
              </v-btn>
            </template>

            <v-card class="filtertype-card">
              <v-list class="pa-0">
                <v-list-item
                  v-for="(type, idx) in fileTypes"
                  :key="idx"
                  @click="selectFileType(type)"
                  class="filtertype-item"
                >
                  <v-list-item-title class="text-subtitle-2">
                    {{ type }}
                  </v-list-item-title>
                </v-list-item>
              </v-list>
            </v-card>
          </v-menu>
        </v-col>
      </v-row>
    </v-col>

    <v-col cols="12" class="mb-2" v-if="isInsideFolder">
      <div class="folder-path-bar d-flex align-center ga-2 px-3 py-2">
        <v-btn
          icon="mdi-arrow-left"
          size="small"
          variant="text"
          @click="goBackFolder"
        />
        <v-icon size="18" color="grey-darken-2">mdi-folder</v-icon>
        <span class="text-body-2 font-weight-medium">{{
          currentFolderPath
        }}</span>
      </div>
    </v-col>

    <v-col cols="12">
      <TableV3
        :headers="headers"
        :items="tableItems"
        :loading="loading"
        :page="page"
        :pages="pages"
        :page-range="pageRange"
        :items-per-page="10"
        @refresh="getDocuments"
        @update:page="page = $event"
        @row-click="tableRowClickHandler"
      >
        <template v-if="isInsideFolder" #breadcrumb>
          <div class="d-flex align-center flex-wrap ga-1">
            <v-btn
              icon="mdi-chevron-left"
              size="x-small"
              variant="text"
              density="comfortable"
              class="me-1"
              @click="goBackFolder"
            />

            <span
              class="breadcrumb-segment text-body-2 text-grey-darken-1 cursor-pointer"
              @click="navigateToRoot"
              >Home</span
            >
            <template v-for="(folder, idx) in folderStack" :key="folder.id">
              <v-icon size="14" color="grey-darken-1">mdi-chevron-right</v-icon>
              <span
                :class="[
                  'breadcrumb-segment text-body-2 font-weight-medium',
                  idx === folderStack.length - 1
                    ? 'text-black'
                    : 'text-grey-darken-1 cursor-pointer',
                ]"
                @click="
                  idx < folderStack.length - 1 && navigateToStackIndex(idx)
                "
                >{{ folder.name }}</span
              >
            </template>
          </div>
        </template>
        <template #item.name="{ item }">
          <div class="d-flex align-center ga-2">
            <v-icon
              size="18"
              :color="
                isFolderItem(item._raw) ? 'amber-darken-2' : 'grey-darken-2'
              "
            >
              {{
                isFolderItem(item._raw)
                  ? "mdi-folder"
                  : "mdi-file-document-outline"
              }}
            </v-icon>
            <span>{{ item.name }}</span>
          </div>
        </template>

        <template #item.date_modified="{ item }">
          <span>{{ item.date_modified || "N/A" }}</span>
        </template>

        <template #item.remarks="{ item }">
          <span>{{ item.remarks || "N/A" }}</span>
        </template>

        <template #item.action="{ item }">
          <v-btn
            variant="flat"
            class="table-download-btn text-none"
            @click.stop="downloadDocument(item._raw)"
            :disabled="isFolderItem(item._raw)"
          >
            Download
          </v-btn>
        </template>
      </TableV3>
    </v-col>

    <!-- Create Dialog -->
    <v-dialog v-model="createDialog" width="450" persistent>
      <DocumentForm
        :parent-id="activeParentId"
        @cancel="createDialog = false"
        @success="successCreate()"
      />
    </v-dialog>

    <!-- Create Folder Dialog -->
    <v-dialog v-model="createFolderDialog" width="450" persistent>
      <v-card width="100%">
        <v-toolbar class="pa-0" density="compact">
          <v-row no-gutters class="w-100">
            <v-col cols="12" class="pa-4">
              <span class="font-weight-medium text-h6">Create Folder</span>
            </v-col>
          </v-row>
        </v-toolbar>

        <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-0">
          <v-form v-model="validFolderForm">
            <v-col cols="12" class="px-6">
              <InputLabel title="Folder Title" />
              <v-text-field
                v-model.trim="folderTitle"
                density="comfortable"
                :rules="[(v) => !!v || 'Folder title is required']"
              />
            </v-col>

            <v-col cols="12" class="px-6">
              <InputLabel title="Remarks (Optional)" />
              <v-textarea
                v-model.trim="folderRemarks"
                density="comfortable"
                rows="3"
              />
            </v-col>
          </v-form>
        </v-card-text>

        <v-toolbar class="pa-0" density="compact">
          <v-row no-gutters class="w-100">
            <v-col cols="6" class="pa-0">
              <v-btn
                block
                variant="text"
                class="text-none"
                size="large"
                @click="createFolderDialog = false"
                :disabled="folderLoading"
                height="48"
              >
                Cancel
              </v-btn>
            </v-col>
            <v-col cols="6" class="pa-0">
              <v-btn
                block
                color="black"
                variant="flat"
                class="text-none"
                size="large"
                @click="handleCreateFolder"
                :loading="folderLoading"
                height="48"
              >
                Submit
              </v-btn>
            </v-col>
          </v-row>
        </v-toolbar>
      </v-card>
    </v-dialog>

    <!-- Edit Dialog -->
    <v-dialog v-model="editDialog" width="450" persistent>
      <DocumentForm
        mode="edit"
        @cancel="editDialog = false"
        @success="successUpdate()"
        :document="selectedDocument"
      />
    </v-dialog>

    <!-- Preview Dialog -->
    <v-dialog v-model="previewDialog" width="450" persistent>
      <v-card width="100%">
        <v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
          <v-row no-gutters class="mb-4">
            <v-col cols="12" class="mb-3">
              <div class="text-h6 font-weight-bold">
                {{ selectedDocument?.name || "N/A" }}
              </div>
            </v-col>

            <v-col cols="12" class="mb-2">
              <v-row no-gutters>
                <v-col cols="6" class="text-body-1">Document</v-col>
                <v-col cols="6" class="text-right text-body-1">
                  <NuxtLink
                    v-if="selectedDocument?.attachment && isViewable"
                    :to="getFileUrl(selectedDocument.attachment)"
                    external
                    target="_blank"
                  >
                    View Document
                  </NuxtLink>
                  <span v-else-if="selectedDocument?.attachment" class="text-grey" style="opacity: 0.6; cursor: not-allowed;">
                    View Document
                  </span>
                  <span v-else>N/A</span>
                </v-col>
              </v-row>
            </v-col>

            <v-col cols="12" class="mb-2">
              <v-row no-gutters>
                <v-col cols="6" class="text-body-1">File Type</v-col>
                <v-col cols="6" class="text-right text-body-1">{{
                  previewDetails.fileType
                }}</v-col>
              </v-row>
            </v-col>

            <v-col cols="12" class="mb-2">
              <v-row no-gutters>
                <v-col cols="6" class="text-body-1">File Size</v-col>
                <v-col cols="6" class="text-right text-body-1">{{
                  previewDetails.fileSize
                }}</v-col>
              </v-row>
            </v-col>

            <v-col cols="12" class="mb-2">
              <v-row no-gutters>
                <v-col cols="6" class="text-body-1">Date Created</v-col>
                <v-col cols="6" class="text-right text-body-1">{{
                  previewDetails.dateCreated
                }}</v-col>
              </v-row>
            </v-col>

            <v-col cols="12" class="mb-2">
              <v-row no-gutters>
                <v-col cols="6" class="text-body-1">Date Modified</v-col>
                <v-col cols="6" class="text-right text-body-1">{{
                  previewDetails.dateModified
                }}</v-col>
              </v-row>
            </v-col>

            <v-col cols="12">
              <v-row no-gutters>
                <v-col cols="6" class="text-body-1">Remarks</v-col>
                <v-col cols="6" class="text-right text-body-1">{{
                  previewDetails.remarks
                }}</v-col>
              </v-row>
            </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="previewDialog = false"
                height="48"
              >
                Close
              </v-btn>
            </v-col>
            <v-col cols="6" class="pa-0">
              <v-menu>
                <template #activator="{ props }">
                  <v-btn
                    block
                    variant="flat"
                    color="black"
                    class="text-none"
                    height="48"
                    v-bind="props"
                    tile
                  >
                    More actions
                  </v-btn>
                </template>
                <v-list class="pa-0">
                  <v-list-item
                    v-if="canUpdateDocument"
                    @click="openEditDialog()"
                  >
                    <v-list-item-title class="text-subtitle-2">
                      Edit Document
                    </v-list-item-title>
                  </v-list-item>

                  <v-list-item
                    v-if="canDeleteDocument"
                    @click="openDeleteDialog()"
                    class="text-red"
                  >
                    <v-list-item-title class="text-subtitle-2">
                      Delete Document
                    </v-list-item-title>
                  </v-list-item>
                </v-list>
              </v-menu>
            </v-col>
          </v-row>
        </v-toolbar>
      </v-card>
    </v-dialog>

    <!-- Delete Dialog -->
    <v-dialog
      v-model="confirmDialog"
      :loading="deleteLoading"
      width="450"
      persistent
    >
      <v-card width="100%">
        <v-toolbar density="compact" class="pl-4">
          <span class="font-weight-medium text-h5">Delete Document</span>
        </v-toolbar>
        <v-card-text>
          <p class="text-subtitle-2 text-center">
            Are you sure you want to delete this document? This action cannot be
            undone.
          </p>
        </v-card-text>

        <v-toolbar density="compact">
          <v-row no-gutters>
            <v-col cols="6">
              <v-btn
                tile
                block
                size="48"
                variant="text"
                class="text-none"
                @click="confirmDialog = false"
                :disabled="deleteLoading"
              >
                Close
              </v-btn>
            </v-col>
            <v-col cols="6">
              <v-btn
                tile
                block
                size="48"
                color="black"
                variant="flat"
                class="text-none"
                @click="handleDeleteDocument"
                :loading="deleteLoading"
              >
                Delete Document
              </v-btn>
            </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">
definePageMeta({
  middleware: ["01-auth", "02-org"],
  memberOnly: true,
});
const props = defineProps({
  headers: {
    type: Array as PropType<Array<Record<string, any>>>,
    default: () => [
      {
        title: "Name",
        value: "name",
      },
      {
        title: "File Type",
        value: "file_type",
      },
      {
        title: "File Size",
        value: "file_size",
      },
      {
        title: "Date Created",
        value: "date_created",
      },
      {
        title: "Date Modified",
        value: "date_modified",
      },
      {
        title: "Remarks",
        value: "remarks",
      },
      {
        title: "Action",
        value: "action",
        sortable: false,
      },
    ],
  },
  canCreate: {
    type: Boolean,
    default: true,
  },
  canUpdate: {
    type: Boolean,
    default: true,
  },
  canDelete: {
    type: Boolean,
    default: true,
  },
  canCreateDocument: {
    type: Boolean,
    default: true,
  },
  canCreateFolder: {
    type: Boolean,
    default: true,
  },
  canUpdateDocument: {
    type: Boolean,
    default: true,
  },
  canDeleteDocument: {
    type: Boolean,
    default: true,
  },
});

const { headerSearch } = useLocal();
const documentService = useDocument();
const {
  getAll: _getAllDocuments,
  deleteById,
  createFolder,
  create,
} = documentService;
const { getFileUrl } = useFile();

const router = useRouter();
const route = useRoute();

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

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

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

const siteId = route.params.site as string;
const orgId = route.params.org as string;
const routeParentId = computed(() =>
  typeof route.query.parentId === "string" ? route.query.parentId : ""
);
const activeParentId = ref(routeParentId.value);
const folderStack = ref<Array<{ id: string; name: string }>>([]);

const search = computed({
  get: () => headerSearch.value,
  set: (value: string) => {
    headerSearch.value = value;
  },
});

const isInsideFolder = computed(() => activeParentId.value !== "");
const currentFolderPath = computed(() => {
  if (folderStack.value.length === 0 && activeParentId.value) {
    return "Current Folder";
  }

  return folderStack.value.map((folder) => folder.name).join(" / ");
});

const fileTypes = ref(["all", "pdf", "csv", "doc"]);
const selectedFileType = ref("all");

const {
  data: getDocumentReq,
  refresh: getDocuments,
  status: getAllReqStatus,
} = useLazyAsyncData(
  "get-all-documents",
  () =>
    _getAllDocuments({
      page: page.value,
      search: headerSearch.value,
      site: siteId,
      parentId: activeParentId.value,
      type:
        selectedFileType.value === "all" ? undefined : selectedFileType.value,
    }),
  {
    watch: [page, headerSearch, activeParentId, selectedFileType],
  }
);

const loading = computed(() => getAllReqStatus.value === "pending");

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

function formatDate(value?: string | null) {
  if (!value) {
    return "N/A";
  }

  const dateValue = new Date(value);
  if (Number.isNaN(dateValue.getTime())) {
    return "N/A";
  }

  return dateValue.toLocaleString("en-SG", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  });
}

function formatBytes(bytes = 0) {
  const b = Number(bytes) || 0;
  if (b === 0) return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB", "GB", "TB"];
  const i = Math.floor(Math.log(b) / Math.log(k));
  return `${parseFloat((b / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
}

const tableItems = computed(() => {
  return items.value.map((doc: any) => ({
    ...doc,
    _raw: doc,
    file_type: doc.type === "folder" ? "Folder" : doc.type || "N/A",
    file_size:
      doc.type === "folder"
        ? "—"
        : formatBytes(Number(doc.file_size ?? doc.size ?? 0)),
    date_created: formatDate(doc.created_at || doc.createdAt),
    date_modified: formatDate(doc.updated_at || doc.updatedAt),
    remarks: doc.remarks || "N/A",
  }));
});

const createDialog = ref(false);
const editDialog = ref(false);
const previewDialog = ref(false);

// Create folder dialog state
const createFolderDialog = ref(false);
const folderTitle = ref("");
const folderRemarks = ref("");
const folderLoading = ref(false);
const validFolderForm = ref(false);

// fileTypes and selectedFileType are declared above to allow
// the fetch to include the selected filter.
const filterMenu = ref(false);
const selectedDocument = ref<TDocument>({
  _id: "",
  name: "",
  attachment: "",
  type: "",
});

const isViewable = computed(() => {
  const lowerType = String(selectedDocument.value?.type || "").trim().toLowerCase();
  return ["pdf", "doc", "csv"].includes(lowerType);
});

const previewDetails = computed(() => {
  const document = selectedDocument.value as Record<string, any>;
  const fileType =
    document?.type === "folder"
      ? "Folder"
      : document?.type || document?.file_type || "N/A";
  const fileSize =
    document?.type === "folder"
      ? "N/A"
      : formatBytes(Number(document?.file_size ?? document?.size ?? 0));

  return {
    fileType,
    fileSize,
    dateCreated: formatDate(document?.created_at || document?.createdAt),
    dateModified: formatDate(document?.updated_at || document?.updatedAt),
    remarks: document?.remarks || "N/A",
  };
});
const deleteLoading = ref(false);
const confirmDialog = ref(false);
const selectedDocumentId = ref<string | null>(null);

function tableRowClickHandler(data: any) {
  const rowData = (data?._raw || data) as TDocument;

  if (isFolderItem(rowData)) {
    openFolder(rowData);
    return;
  }

  openPreviewDialog(rowData);
}

async function openPreviewDialog(document: TDocument) {
  selectedDocument.value = document;
  previewDialog.value = true;

  const documentId = String(document?._id || "");
  if (!documentId) {
    return;
  }

  try {
    const response = await documentService.getById(documentId);
    const fetchedDocument =
      (response as any)?.item ||
      (response as any)?.data ||
      (response as any)?.document ||
      response;

    if (fetchedDocument && typeof fetchedDocument === "object") {
      selectedDocument.value = {
        ...document,
        ...(fetchedDocument as Record<string, any>),
      } as TDocument;
    }
  } catch (_error) {
    // Keep table data in modal if detail API request fails.
  }
}

function isFolderItem(document?: Partial<TDocument> & Record<string, any>) {
  if (!document) {
    return false;
  }

  const docType = String(
    document.type || document.file_type || ""
  ).toLowerCase();
  return docType === "folder";
}

function openFolder(document: Partial<TDocument> & Record<string, any>) {
  const folderId = String(document._id || "");
  const folderName = String(document.name || "Folder");

  if (!folderId) {
    return;
  }

  activeParentId.value = folderId;
  folderStack.value.push({ id: folderId, name: folderName });
  page.value = 1;
}

function goBackFolder() {
  if (folderStack.value.length === 0) {
    return;
  }

  folderStack.value.pop();
  activeParentId.value = folderStack.value.at(-1)?.id || "";
  page.value = 1;
}

function downloadDocument(document?: TDocument) {
  if (!document?.attachment || !process.client) {
    return;
  }

  const fileUrl = getFileUrl(document.attachment);
  if (fileUrl) {
    window.open(fileUrl, "_blank", "noopener,noreferrer");
  }
}

function setDocument({
  mode = "create",
  dialog = true,
  data = {} as TDocument,
} = {}) {
  if (mode === "create") {
    createDialog.value = dialog;
  } else if (mode === "edit") {
    editDialog.value = dialog;
    selectedDocument.value = data;
  } else if (mode === "preview") {
    if (!dialog) {
      previewDialog.value = false;
      return;
    }
    openPreviewDialog(data);
  }
}

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

function successCreate() {
  createDialog.value = false;
  getDocuments();
  showMessage("Document created successfully!", "success");
}

function openCreateFolderDialog() {
  folderTitle.value = "";
  folderRemarks.value = "";
  createFolderDialog.value = true;
}

async function handleCreateFolder() {
  if (!folderTitle.value) {
    showMessage("Folder title is required", "error");
    return;
  }

  folderLoading.value = true;
  try {
    const payload = {
      name: folderTitle.value,
      remarks: folderRemarks.value,
      org: orgId,
      site: siteId,
      parentId: activeParentId.value,
      type: "folder",
    };

    let resp: any = null;
    if ((documentService as any).createFolder) {
      resp = await (documentService as any).createFolder(payload);
    } else if ((documentService as any).create) {
      resp = await (documentService as any).create(payload);
    } else if ((documentService as any).add) {
      resp = await (documentService as any).add(payload);
    } else {
      showMessage("Unable to create folder. No API available.", "error");
    }

    if (resp) {
      showMessage(resp?.message || "Folder created successfully!", "success");
    }

    createFolderDialog.value = false;
    folderTitle.value = "";
    folderRemarks.value = "";
    await getDocuments();
  } catch (error: any) {
    showMessage(
      error?.response?._data?.message || "Failed to create folder",
      "error"
    );
  } finally {
    folderLoading.value = false;
  }
}

function openDeleteDialog() {
  confirmDialog.value = true;
  message.value = "";
}

function openEditDialog() {
  editDialog.value = true;
}

async function handleDeleteDocument() {
  deleteLoading.value = true;
  try {
    const response = await deleteById(selectedDocument.value._id ?? "");
    showMessage(response.message, "success");
    await getDocuments();
    selectedDocumentId.value = null;
    confirmDialog.value = false;
    previewDialog.value = false;
  } catch (error: any) {
    message.value =
      error?.response?._data?.message || "Failed to delete document";
  } finally {
    deleteLoading.value = false;
  }
}

function successUpdate() {
  editDialog.value = false;
  previewDialog.value = false;
  getDocuments();
  showMessage("Document updated successfully!", "success");
}

function selectFileType(type: string) {
  selectedFileType.value = type;
  filterMenu.value = false;
}
</script>

<style scoped>
.table-download-btn {
  min-width: 106px;
  height: 30px;
  border-radius: 4px;
  background-color: #e3e3e3;
  color: #38475a;
  font-size: 12px;
  font-weight: 500;
  box-shadow: none;
}

.table-download-btn:hover {
  background-color: #d8d8d8;
}

.filtertype-btn {
  justify-content: flex-start;
  width: 220px;
}

.filtertype-card {
  background: #fff;
  border-radius: 8px;
  min-width: 160px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
  overflow: hidden;
}

.filtertype-item {
  border-bottom: 1px solid #f0f0f0;
  padding: 10px 16px;
}

.filtertype-item:last-child {
  border-bottom: none;
}

.folder-path-bar {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background: #fafafa;
}
</style>
