<script setup lang="ts">
import { LazyLinkModal, LazyConfirmModal, LazyRenameFileModal } from "#components";

definePageMeta({ middleware: "auth" });

const toast = useToast();
const overlay = useOverlay();
const fileInput = ref<HTMLInputElement | null>(null);

const { fetch: fetchSession } = useUserSession();

const signOut = async () => {
  await $fetch("/api/auth/sign-out", { method: "POST" });
  await fetchSession();
  await navigateTo("/auth/sign-in");
};

const { data: links, status: linksStatus, refresh: refreshLinks } = useLazyFetch("/api/links", { key: "links", server: false });
const { data: files, status: filesStatus, refresh: refreshFiles } = useLazyFetch("/api/files", { key: "files", server: false });

const route = useRoute();
const section = computed(() => route.query.section === "files" ? "files" : "links");
const category = computed(() => {
  if (section.value !== "links") return "all";
  if (route.query.filter === "active") return "active";
  if (route.query.filter === "disabled") return "disabled";
  return "all";
});

const categoryTitle = computed(() => {
  if (category.value === "active") return "Active links";
  if (category.value === "disabled") return "Disabled links";
  return "All links";
});

const pageTitle = computed(() => section.value === "files" ? "Files" : categoryTitle.value);
useHead({ title: pageTitle });

const filteredLinks = computed(() => {
  if (!links.value) return [];
  if (category.value === "active") return links.value.filter((l) => !l.disabled);
  if (category.value === "disabled") return links.value.filter((l) => l.disabled);
  return links.value;
});

// Link actions
const openModal = async (link: Link | null) => {
  const modal = overlay.create(LazyLinkModal, { destroyOnClose: true });
  const instance = modal.open({ link });
  if (await instance.result) await refreshLinks();
};

const deleteLink = async (link: Link) => {
  const modal = overlay.create(LazyConfirmModal, { destroyOnClose: true });
  const instance = modal.open({ title: "Delete link", description: `Are you sure you want to delete "${link.name}"?` });
  if (!await instance.result) return;

  try {
    await $fetch(`/api/links/${link.id}`, { method: "DELETE" });
    toast.add({ title: "Link deleted", color: "success" });
    await refreshLinks();
  } catch (error) {
    toast.add({ title: getApiError(error), color: "error" });
  }
};

// File actions
const uploading = ref(false);

const handleUpload = async (event: Event) => {
  const input = event.target as HTMLInputElement;
  if (!input.files || input.files.length === 0) return;

  uploading.value = true;
  try {
    for (const file of Array.from(input.files)) {
      const form = new FormData();
      form.append("file", file);
      await $fetch("/api/files", { method: "POST", body: form });
    }
    toast.add({ title: `${input.files.length === 1 ? "File" : "Files"} uploaded`, color: "success" });
    await refreshFiles();
  } catch (error) {
    toast.add({ title: getApiError(error), color: "error" });
  } finally {
    uploading.value = false;
    input.value = "";
  }
};

const renameFile = async (file: FileEntry) => {
  const modal = overlay.create(LazyRenameFileModal, { destroyOnClose: true });
  const instance = modal.open({ filename: file.name });
  if (await instance.result) await refreshFiles();
};

const deleteFile = async (file: FileEntry) => {
  const modal = overlay.create(LazyConfirmModal, { destroyOnClose: true });
  const instance = modal.open({ title: "Delete file", description: `Are you sure you want to delete "${file.name}"?` });
  if (!await instance.result) return;

  try {
    await $fetch(`/api/files/${encodeURIComponent(file.name)}`, { method: "DELETE" });
    toast.add({ title: "File deleted", color: "success" });
    await refreshFiles();
  } catch (error) {
    toast.add({ title: getApiError(error), color: "error" });
  }
};
</script>

<template>
  <UDashboardGroup>
    <UDashboardSidebar :toggle="false" :ui="{ header: 'border-b border-default' }">
      <template #header>
        <span class="font-semibold text-highlighted text-lg">pihka.al</span>
      </template>

      <div class="px-2 space-y-2">
        <UNavigationMenu
          orientation="vertical"
          highlight
          :items="[
            {
              label: 'All',
              icon: 'i-lucide-link',
              badge: links?.length ?? 0,
              to: '/dashboard',
              active: section === 'links' && category === 'all',
            },
            {
              label: 'Active',
              icon: 'i-lucide-link-2',
              badge: links?.filter((l) => !l.disabled).length ?? 0,
              to: '/dashboard?filter=active',
              active: section === 'links' && category === 'active',
            },
            {
              label: 'Disabled',
              icon: 'i-lucide-link-2-off',
              badge: links?.filter((l) => l.disabled).length ?? 0,
              to: '/dashboard?filter=disabled',
              active: section === 'links' && category === 'disabled',
            },
          ]"
        />

        <USeparator />

        <UNavigationMenu
          orientation="vertical"
          highlight
          :items="[
            {
              label: 'Files',
              icon: 'i-lucide-folder',
              badge: files?.length ?? 0,
              to: '/dashboard?section=files',
              active: section === 'files',
            },
          ]"
        />
      </div>

      <template #footer>
        <UButton variant="link" icon="i-lucide-log-out" block @click="signOut">Sign out</UButton>
      </template>
    </UDashboardSidebar>

    <UDashboardPanel v-if="section === 'links'">
      <template #header>
        <UDashboardNavbar :title="categoryTitle">
          <template #right>
            <UButton icon="i-lucide-plus" variant="subtle" @click="openModal(null)">New link</UButton>
          </template>
        </UDashboardNavbar>
      </template>

      <template #body>
        <LinksTable
          :data="filteredLinks"
          :status="linksStatus"
          @edit="openModal"
          @delete="deleteLink"
        />
      </template>
    </UDashboardPanel>

    <UDashboardPanel v-else>
      <template #header>
        <UDashboardNavbar title="Files">
          <template #right>
            <input ref="fileInput" type="file" class="hidden" multiple @change="handleUpload" />
            <UButton icon="i-lucide-upload" variant="subtle" :loading="uploading" @click="(fileInput as HTMLInputElement)?.click()">Upload</UButton>
          </template>
        </UDashboardNavbar>
      </template>

      <template #body>
        <FilesTable
          :data="files ?? []"
          :status="filesStatus"
          @rename="renameFile"
          @delete="deleteFile"
        />
      </template>
    </UDashboardPanel>
  </UDashboardGroup>
</template>
