<script setup lang="ts">
import { ArrowRight, HomeFilled } from "@element-plus/icons-vue";
import { useFileStore } from "@/pages/files/store.ts";
import { useRequest } from "vue-request";
import { myRequest } from "@/requests/request.ts";
import { userinfo } from "@/store/store.ts";
import { ref, watch } from "vue";
import { ElMessage, UploadFile, UploadUserFile } from "element-plus";
import { formatError } from "@/utils/utils.ts";
import router from "@/router/router.ts";

const fileIcon = [
  { type: "dir", icon: "bi-folder" },
  { type: "zip", icon: "bi-file-zip" },
  { type: "image", icon: "bi-image" },
  { type: "audio", icon: "bi-music-note-beamed" },
  { type: "video", icon: "bi-camera-video" },
  { type: "doc", icon: "bi-file-earmark" },
];
const newFolder = ref({ visible: false, name: "" });
const fileList = ref<UploadUserFile[]>([]);
const imgPreview = ref({ visible: false, src: "" });

const { data, loading, run } = useRequest<{
  data: { dirs: string[] | null; files: fileList[] | null };
}>(
  () =>
    myRequest(
      `/api_file/file/upload${useFileStore.path.length > 0 ? "/" + useFileStore.path.join("/") : ""}`,
      userinfo.token,
    ),
  { refreshDeps: [() => useFileStore.path] },
);
const { runAsync: addFolder } = useRequest(
  () =>
    myRequest(
      `/api_file/file/upload/${useFileStore.path
        .concat([newFolder.value.name])
        .join("/")}`,
      userinfo.token,
      {},
      "post",
    ),
  { manual: true },
);

const { runAsync: delFile } = useRequest(
  (name: string) =>
    myRequest(
      `/api_file/file/upload/${useFileStore.path.concat([name]).join("/")}`,
      userinfo.token,
      {},
      "delete",
    ),
  { manual: true },
);

const toPath = (index: number) => {
  useFileStore.path = useFileStore.path.filter((_, i) => i <= index);
};
const funcAddFolder = () => {
  addFolder()
    .then(() => {
      newFolder.value = { visible: false, name: "" };
      run();
    })
    .catch((res) => ElMessage.error(formatError(res)));
};
const funcDelFile = (file: string) => {
  delFile(file)
    .then(() => {
      run();
    })
    .catch((res) => ElMessage.error(formatError(res)));
};
const funcDownloadFile = (file: string) => {
  const win = window.open("_black");
  const url = `/api_file/file/download/${useFileStore.path.concat([file]).join("/")}`;
  if (win) {
    win.location.href = url;
  }
};
const handleFileUpload = (file: UploadFile) => {
  if (file.status === "success") {
    fileList.value = fileList.value.filter((e) => e.name !== file.name);
    run();
  } else if (file.status === "fail") {
    ElMessage.error(`${file.name}上传失败`);
  }
};
watch(fileList, () => console.log(fileList));
</script>

<template>
  <!--  面包屑路由-->
  <el-breadcrumb :separator-icon="ArrowRight" style="padding: 0.5rem">
    <el-breadcrumb-item @click="() => (useFileStore.path = [])"
      ><el-icon size="20"><home-filled /></el-icon
    ></el-breadcrumb-item>
    <el-breadcrumb-item v-for="(item, index) in useFileStore.path"
      ><el-tooltip :content="item" placement="top" effect="light"
        ><span class="path-item cursor-pointer" @click="() => toPath(index)">{{
          item
        }}</span></el-tooltip
      ></el-breadcrumb-item
    >
  </el-breadcrumb>
  <!--  分割线,新建文件夹,上传文件-->
  <div class="divider">
    <div style="background: #fff">
      <el-button link @click="newFolder = { visible: true, name: '' }"
        ><el-icon><i class="bi-folder-plus" /></el-icon
        ><span> 新建文件夹</span></el-button
      ><el-upload
        :action="`/api_file/file/upload-file/${useFileStore.path.length ? useFileStore.path.join('/') : 'root(根目录上传的文件)'}`"
        multiple
        :headers="{ Authorization: 'Bearer ' + userinfo.token }"
        name="file"
        :file-list="fileList"
        :on-change="handleFileUpload"
        ><el-button link
          ><el-icon><i class="bi-upload" /></el-icon
          ><span> 上传文件</span></el-button
        ></el-upload
      >
    </div>
  </div>
  <!--  文件列表-->
  <el-table
    v-loading="loading"
    size="small"
    v-if="data"
    :data="
      data?.data.dirs
        ? data.data.dirs
            .map((e) => ({ name: e, type: 'dir' }))
            .concat(data.data.files || [])
        : data.data.files
    "
    :row-class-name="(d: any) => (d.row.type === 'dir' ? 'cursor-pointer' : '')"
    @row-dblclick="
      (r: fileList) =>
        r.type === 'dir'
          ? (useFileStore.path = useFileStore.path.concat([r.name]))
          : 1
    "
  >
    <el-table-column label="名称" prop="name">
      <template #default="scope">
        <el-icon size="15"
          ><i
            :class="`${fileIcon.filter((e) => e.type === scope.row.type)[0].icon}`"
        /></el-icon>
        <span>{{ scope.row.name }}</span>
      </template>
    </el-table-column>
    <el-table-column label="大小" prop="size" align="center" />
    <el-table-column label="操作" align="center">
      <template #default="scope">
        <el-icon
          v-if="scope.row.type === 'image'"
          @click="
            () =>
              (imgPreview = {
                visible: true,
                src: `/api_file/file/download/${useFileStore.path
                  .concat([scope.row.name])
                  .join('/')}`,
              })
          "
          ><i class="bi-eye"
        /></el-icon>
        <el-icon
          v-if="scope.row.type === 'video'"
          @click="
            router.push(
              `/file/video?file=${useFileStore.path.concat([scope.row.name]).join('/')}`,
            )
          "
          ><i class="bi-play-btn"
        /></el-icon>
        <el-icon
          color="#108ee9"
          @click="() => funcDownloadFile(scope.row.name)"
          v-if="scope.row.type !== 'dir'"
          ><i class="bi-download"
        /></el-icon>
        <el-popconfirm
          :title="`确认删除 ${scope.row.name} ？`"
          confirm-button-text="确认"
          cancel-button-text="取消"
          @confirm="() => funcDelFile(scope.row.name)"
          ><template #reference
            ><el-icon color="red"><i class="bi-trash" /></el-icon></template
        ></el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <!--  新建文件夹弹窗-->
  <el-dialog title="新建文件夹" v-model="newFolder.visible">
    <el-input placeholder="输入文件夹名称" v-model="newFolder.name" clearable />
    <template #footer>
      <el-button type="primary" @click="funcAddFolder">确认</el-button>
    </template>
  </el-dialog>
  <el-image-viewer
    :url-list="[imgPreview.src]"
    v-if="imgPreview.visible"
    @close="imgPreview.visible = false"
  />
</template>

<style scoped>
.path-item {
  display: table-cell;
  max-width: 10rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 20px;
}
.divider {
  text-align: center;
  padding: 0 35%;
  background: linear-gradient(#fff calc(50% - 1px), #0003, #fff 50%);
}
i {
  padding: 0 0.2rem;
  font-size: 1rem;
}
</style>
