<template>
  <v-container class="text-center pt-6">
    <v-img
      src="/UNLOZE_logo_blue.png"
      max-width="200"
      alt="UNLOZE Logo"
      class="mx-auto"
      contain
    />
  </v-container>
  <v-container>
    <v-card>
      <v-breadcrumbs :items="breadcrumbItems" class="my-4">
        <template v-slot:item="{ item }">
          <span v-if="item.disabled" class="grey--text text--darken-2">
            {{ item.title }}
          </span>
          <span
            v-else
            class="blue--text text--darken-2"
            style="cursor: pointer"
            @click="goToBreadcrumb((item as any).value)"
          >
            {{ item.title }}
          </span>
        </template>
      </v-breadcrumbs>
      <v-text-field
        v-model="search"
        label="Search files..."
        prepend-inner-icon="mdi-magnify"
        hide-details
        density="compact"
        class="ma-4"
        @keyup.enter="onSearch"
      />
      <v-progress-linear v-if="loading" indeterminate color="blue" />
      <v-data-table
        :headers="headers"
        :items="combinedItems"
        :items-per-page="-1"
        class="elevation-1"
        disable-pagination
        hide-default-footer
      >
        <template #item.name="{ item }">
          <span
            v-if="item.isDir"
            class="blue--text text--darken-2"
            @click="enterFolder(item.path)"
            style="cursor: pointer"
          >
            <v-icon small class="me-2">mdi-folder-outline</v-icon>

            {{ item.name }}
          </span>
          <span v-else>
            <v-icon small class="me-2">mdi-file-outline</v-icon>
            <a
              :href="`${DOWNLOAD_BASE_URL}${currentPath}${item.name}`"
              target="_blank"
              class="blue--text text--darken-2"
              style="text-decoration: none"
            >
              {{ item.name }}
            </a>
          </span>
        </template>

        <template #item.size="{ item }">
          {{ item.isDir ? "-" : formatSize(item.size) }}
        </template>

        <template #item.lastModified="{ item }">
          {{
            item.lastModified
              ? new Date(item.lastModified).toLocaleString()
              : "-"
          }}
        </template>
      </v-data-table>
    </v-card>
  </v-container>
</template>

<script lang="ts">
import { defineComponent, ref, nextTick } from "vue";

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;

interface FolderItem {
  name: string;
  path: string;
  isDir: true;
  size: null;
  lastModified: null;
}

interface FileItem {
  name: string;
  path: string;
  isDir: false;
  size: number;
  lastModified: string;
}

interface BreadcrumbItem {
  title: string;
  value: string;
  disabled: boolean;
}

export default defineComponent({
  data() {
    return {
      currentPath: "",
      folders: [] as string[],
      files: [] as {
        key: string;
        size: number;
        lastModified: string;
      }[],
      nextToken: null as string | null,
      loading: false,
      search: "",
      headers: [
        { title: "Name", key: "name" },
        { title: "Size", key: "size", width: "120px" },
        { title: "Last Modified", key: "lastModified", width: "200px" },
      ],
      DOWNLOAD_BASE_URL: import.meta.env.VITE_DOWNLOAD_BASE_URL
    };
  },
  computed: {
    combinedItems(): (FolderItem | FileItem)[] {
      const folderItems: FolderItem[] = this.folders.map((p) => ({
        name: this.extractFolderName(p),
        path: p,
        isDir: true,
        size: null,
        lastModified: null,
      }));
      const fileItems: FileItem[] = this.files.map((f) => ({
        name: f.key.split("/").pop() || f.key,
        path: f.key,
        isDir: false,
        size: f.size,
        lastModified: f.lastModified,
      }));
      return [...folderItems, ...fileItems];
    },
    breadcrumbItems(): BreadcrumbItem[] {
      const parts = this.currentPath.split("/").filter((p) => p !== "");
      const items: BreadcrumbItem[] = [
        { title: "Home", value: "", disabled: parts.length === 0 },
      ];
      let cumulativePath = "";
      parts.forEach((part, index) => {
        cumulativePath += part + "/";
        items.push({
          title: part,
          value: cumulativePath,
          disabled: index === parts.length - 1,
        });
      });
      return items;
    },
  },
  methods: {
    async fetchList(reset = false) {
      if (this.loading) return;
      this.loading = true;

      const url = new URL(`${API_BASE_URL}/api/list`);
      url.searchParams.set("prefix", this.currentPath);
      url.searchParams.set("limit", "50");
      if (this.search) url.searchParams.set("search", this.search);
      if (this.nextToken && !reset) {
        url.searchParams.set("token", this.nextToken);
      }

      const res = await fetch(url.toString());
      const data = await res.json();

      if (reset) {
        this.folders = [];
        this.files = [];
        nextTick(() => {
          const container = this.$refs.scrollContainer as HTMLElement;
          if (container) container.scrollTop = 0;
        });
      }

      this.folders.push(...(data.folders || []));
      this.files.push(...(data.files || []));
      this.nextToken = data.nextToken;
      this.loading = false;
    },
    onSearch() {
      this.nextToken = null;
      this.fetchList(true);
    },
    enterFolder(path: string) {
      this.currentPath = path;
      this.nextToken = null;
      this.fetchList(true);
    },
    goToBreadcrumb(path: string) {
      this.currentPath = path;
      this.nextToken = null;
      this.fetchList(true);
    },
    extractFolderName(path: string): string {
      const parts = path.split("/");
      return parts[parts.length - 2] || path;
    },
    formatSize(size: number): string {
      if (size > 1e6) return (size / 1e6).toFixed(1) + " MB";
      if (size > 1e3) return (size / 1e3).toFixed(1) + " KB";
      return size + " B";
    },
  },
  mounted() {
    this.fetchList(true);
  },
});
</script>
