import request from "@/utils/request";
import { PageOption } from "@smallwei/avue";
import { ElMessageBox, ElMessage } from "element-plus";
import { useUserStoreHook } from "@/store/modules/user";
import { checkPerm } from "@/directive/permission";

interface UseCrudConfig {
  // 模块的url，用来进行增删改查
  src?: string;
  // 需要操作的数据
  row?: any;
  // done用于结束操作
  done?: () => void;
  // 具体操作的行
  index?: number;
  // 用于中断操作
  loading?: () => void;
  // 查询参数 一般用search的值就可以了
  params?: object;
  // 是否是编辑，如果是编辑调用更新，否则调用新增
  isEdit?: boolean;
}

export const useCrud = (config?: UseCrudConfig) => {
  const url = ref(config?.src);

  /** 表格配置属性 */
  const option = ref({
    searchIcon: true,
    searchIndex: 3, //searchIcon是否启用功能按钮, searchIndex配置收缩展示的个数,默认为2个
    index: true, //是否显示第几项
    refreshBtn: false,
    border: true,
    viewBtn: true,
  });
  const data = ref<any>([]); //表格数据
  const form = ref({}); //新增或者编辑弹出的表单绑定值
  /** 表格顶部搜索的表单的变量 v-model */
  const search = ref({});

  /** 表格的分页数据 v-model */
  const page = ref<PageOption>({
    total: 12220,
    currentPage: 1,
    pageSize: 10,
  });
  /** 配置项结构 v-model */
  // defaults ?: AvueCrudDefaults;

  const toDeleteIds = ref<Array<string>>([]);

  const save = async (config?: UseCrudConfig) => {
    const path = config?.isEdit ? "/update" : "/add";
    try {
      const res = await request({
        url: `${url.value}${path}`,
        method: "post",
        data: form.value,
      });
      if (res?.data?.code == 200) {
        Methords.dataList();
        config?.done && config?.done();
      } else {
        ElMessage.error(res?.data?.msg ?? "");
      }
    } catch (err) {
      ElMessage.error("Oops, this is a error message.");
      // config?.loading && config?.loading();
    } finally {
      ElMessage.error("Oops, this is a error message.");
      // config?.done && config?.done();
    }
  };

  const handleSearchData = () => {
    // const array = [null, undefined, ""];
    search.value = Object.fromEntries(
      Object.entries(search.value).filter(
        ([key, value]) =>
          value !== null &&
          value !== undefined &&
          Object.keys(value).length !== 0
      )
    );
  };

  /**
   * 表格增删改查等基本方法
   */
  const Methords = {
    /**
     * 查询方法
     */
    dataList: async (config?: UseCrudConfig) => {
      handleSearchData();
      try {
        const res = await request({
          url: `${url.value}/page`,
          method: "post",
          data: {
            pageNo: page.value.currentPage,
            pageSize: page.value.pageSize,
            ...search.value,
          },
        });
        if (res?.data) {
          data.value = res?.data?.records || [];
          page.value.total = res?.data?.totalCount || 0;
        }
        config?.done && config?.done();
      } catch (err) {
        config?.loading && config?.loading();
      } finally {
        config?.done && config?.done();
      }
    },

    createRow: (row: any, done: () => void, loading: () => void) => {
      save({ row: row, done: done, loading: loading });
    },

    updateRow: (
      row: any,
      index: number,
      done: () => void,
      loading: () => void
    ) => {
      save({
        row: row,
        done: done,
        loading: loading,
        index: index,
        isEdit: true,
      });
    },

    deleteRow: async (row: any, index: number, done: () => void) => {
      ElMessageBox.confirm("是否删除所选中数据？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(async () => {
        try {
          const res = await request({
            url: `${url.value}/del`,
            method: "post",
            data: { id: row.id ?? "" },
          });
          Methords.dataList();
          config?.done && config?.done();
        } catch (err) {
          config?.loading && config?.loading();
        } finally {
          config?.done && config?.done();
        }
      });
    },

    // 设置selection: true,后监听选中改变事件，将Id存入数组
    selectionChange: (rows?: any[]) => {
      toDeleteIds.value = [];
      rows?.forEach((element) => {
        toDeleteIds.value.push(element.id);
      });
    },

    /**
     * 表格上方的多选删除方法
     */
    multipleDelete: async () => {
      ElMessageBox.confirm("是否删除所选中数据？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(async () => {
        try {
          const res = await request({
            url: `${url.value}/batch-del`,
            method: "post",
            data: { ids: toDeleteIds.value },
          });
          Methords.dataList();
          config?.done && config?.done();
        } catch (err) {
          config?.loading && config?.loading();
        } finally {
          config?.done && config?.done();
        }
      });
    },

    /**
     * 点击搜索按钮触发
     */
    searchChange: async (params: any, done: () => void) => {
      // 点击搜索的时候重置search的值，要不然会传过去所有的值包括空字符串的值
      search.value = params;
      page.value.currentPage = 1;
      Methords.dataList({ done: done });
    },

    /**
     * 点击清空按钮触发
     */
    resetChange: async (item: any) => {
      page.value.currentPage = 1;
      Methords.dataList();
    },
  };

  /**
   * 表格辅助方法，按钮权限，导入导出
   */
  const Utils = {
    checkBtnPerm: (str: string) => {
      // 「超级管理员」拥有所有的按钮权限
      const { roles, perms } = useUserStoreHook().user;
      if (roles.includes("ROOT")) {
        return true;
      }
      const hasPerm = perms?.some((perm) => {
        return str.includes(perm);
      });
      return hasPerm;
    },

    /**
     * 根据返回的数据下载文件
     */
    downloadFile: (response: any) => {
      const fileData = response.data;
      const fileName = decodeURI(
        response.headers["content-disposition"].split(";")[1].split("=")[1]
      );
      const fileType =
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
      const blob = new Blob([fileData], { type: fileType });
      const downloadUrl = window.URL.createObjectURL(blob);
      const downloadLink = document.createElement("a");
      downloadLink.href = downloadUrl;
      downloadLink.download = fileName;
      document.body.appendChild(downloadLink);
      downloadLink.click();
      document.body.removeChild(downloadLink);
      window.URL.revokeObjectURL(downloadUrl);
    },

    /**
     * 下载模版 传入url
     */
    downloadTemplate: async (urlStr: string) => {
      const response = await request({
        url: urlStr,
        method: "get",
        responseType: "arraybuffer",
      });
      Utils.downloadFile(response);
    },

    /**
     * 根据搜索项导出数据
     */
    exportData: async (urlStr: string) => {
      const response = await request({
        url: urlStr,
        method: "post",
        data: search.value,
        responseType: "arraybuffer",
      });
      Utils.downloadFile(response);
    },
  };

  return {
    url,
    option,
    data,
    form,
    search,
    page,
    toDeleteIds,
    Methords,
    Utils,
  };
};
