import getMD5 from '@/components/MD5';
import { useAjax } from '@/Hook/useAjax';
import {
  bdSysMediaList,
  bdSysMediaAdd,
  delMedia,
  bdSysMediaEdit,
  getFileUrl,
  getMedia,
  configSortApi,
  getFolderTree,
  editMediaFolder,
  bdSysMediaAddsApi,
} from '@/services/launchAdq/material';
import { blobToBase64, dataURLtoFile, videoMessage } from '@/utils/compress';
import { getImgSize } from '@/utils/utils';
import { message } from 'antd';
import { compressAccurately } from 'image-conversion';
import { Dispatch, useCallback, useReducer, useState } from 'react';
import { request } from 'umi';
/**新本地素材弹窗 */
type State = {
  fileVisible?: boolean; //文件夹弹窗
  imgVisrible?: boolean; //img,voice,video弹窗
  imgsVisrible?: boolean,//
  newsVisrible?: boolean; //news弹窗
  knewsVisrible?: boolean; //客服图文弹窗
  fileName?: string; //文件夹名称
  sort?: number; // 排序
  videoTitle?: string; //video文件名称
  videoDescription?: string; //视频描述
  belongUser?: any; //0公共本地|1个人本地
  mediaType?: 'VIDEO' | 'IMG' | 'PAGE'; // 类型
  parentId?: any; //上级目录ID，顶级使用null
  url?: string; //素材地址
  pathId?: string; //路径ID
  selectFile?: number[]; //选中的文件列表
  rightClickPup?: any; // /**右键菜单开关 all为全部 id 为目标文件 空为不显示*/
  xy?: { x: number; y: number }; // /**鼠标位置 菜单弹窗位置使用*/
  delPupId?: any; //按了单个删除存放的id为了让弹窗区分文件
  actionItem?: any; //当前选中的Itme
  path?: any[]; //个人路径
  publicPath?: any[]; //本地路径
  file?: File; //素材文件
  selectItem?: any[]; //单选素材时存放选中的素材
  knewsdefaultData?: any; //k图文编辑时的默认内容
  sortVisible?: boolean; //排序弹窗
  num?: number; //选择数量
  size?: number; // 需要上传素材的大小
  upLoadLoading?: boolean;
  cloudSize?: any[];
  maxSize?: number; //素材最大尺寸
  adcreativeTemplateId?: number; //创意模板 id
  promotedObjectType?: string; //推广目标类型
  promotedObjectId?: string; //推广目标 id
  pageType?: string; //落地页类型
  canvasType?: string; //原生页类型
  siteSet?: string[]; //版位
  sourceType?: string; //视频/图片/原生页等素材的创建来源类型
  marketingScene?: string; //营销场景
};
export type Action = {
  type: 'set' | 'init';
  params?: any;
};
const typeEnum = {
  IMG: '图片',
  VIDEO: '视频',
};
function reducer(state: State, action: Action) {
  let { type, params } = action;
  let newState = JSON.parse(JSON.stringify(state));
  newState.file = state.file;
  switch (type) {
    case 'set':
      Object.keys(params as State).forEach((key: string) => {
        newState[key] = (params as any)[key];
      });
      return newState;
    case 'init':
      return { ...initData, ...params };
    default:
      return state;
  }
}
const initData: State = {
  fileVisible: false,
  knewsVisrible: false,
  videoTitle: '',
  videoDescription: '',
  fileName: '',
  belongUser: '1',
  mediaType: 'IMG',
  parentId: null,
  selectFile: [],
  delPupId: '',
  rightClickPup: { id: '' },
  publicPath: [{ title: '公共本地', number: '0' }],
  path: [{ title: '个人本地', number: '0' }],
  imgVisrible: false,
  imgsVisrible: false,
  newsVisrible: false,
  sortVisible: false,
  sort: 0,
  num: 1,
};
/**本地素材管理器 */
function useBdMediaPup() {
  const [state, dispatch]: [State, Dispatch<Action>] = useReducer(reducer, initData);
  const {
    fileName,
    sort,
    belongUser,
    mediaType,
    parentId,
    selectFile,
    selectItem,
    delPupId,
    cloudSize,
    num,
    rightClickPup,
    actionItem,
    path,
    publicPath,
    videoTitle,
    videoDescription,
    size,
    maxSize,
    adcreativeTemplateId,
    promotedObjectType,
    promotedObjectId,
    pageType,
    canvasType,
    siteSet,
    sourceType,
    marketingScene,
  } = state;
  const list = useAjax((params) => bdSysMediaList(params));
  const add = useAjax((params) => bdSysMediaAdd(params), { msgNmae: '新增' });
  const del = useAjax((params) => delMedia(params), { msgNmae: '删除' });
  const edit = useAjax((params) => bdSysMediaEdit(params), { msgNmae: '编辑' });
  const configSort = useAjax((params) => configSortApi(params), { msgNmae: '排序' });
  const adds = useAjax((params) => bdSysMediaAddsApi(params), { msgNmae: '新增' })
  const get = useAjax((params) => getMedia(params)); //获取图文详情
  const get_folder_tree = useAjax((params: any) => getFolderTree(params));
  const edit_media_folder = useAjax((params: any) => editMediaFolder(params));
  const [isOk, setIsOk] = useState<boolean>(true);
  //请求上传地址
  const fileUrl = useAjax(
    (params: { type: string; fileType: 'video' | 'image' }) => getFileUrl(params),
    {
      manual: true,
    },
  );
  /**初始化数据 */
  const init = useCallback((params: State) => {
    console.log('params======>', params);
    dispatch({ type: 'init', params });
  }, []);
  /**设置state */
  const set = useCallback((params: State) => {
    if (params) {
      dispatch({ type: 'set', params });
    }
  }, []);
  /**新增文件夹 */
  const addFolder = () => {
    if (fileName) {
      let obj = {
        title: fileName,
        mediaType,
        folder: true,
        parentId,
        belongUser: belongUser === '0' ? false : true,
        sort,
      };
      add.run(obj).then((res) => {
        get_folder_tree.refresh();
        list.refresh();
        offEditFile(); //关闭弹窗并清空相关数据
      });
    }
  };
  /** 新增图片 视频 */
  const addFile = async (data: any) => {
    if (data) {
      //存在代表素材
      if (!data) {
        return;
      }
      if (data?.file) {
        let file = data.file;
        let fileSize = size || 0;
        if (!size) {
          if (mediaType === 'IMG') {
            fileSize = 409600
          } else {
            fileSize = 524288000
          }
        }

        if (mediaType === 'IMG') {
          if (file?.size > fileSize) {
            // 大于400kb进入压缩
            let bole = await compressAccurately(file, 250);
            if (bole?.size > 300000) {
              bole = await compressAccurately(file, 200);
            }
            if (bole?.size > 300000) {
              bole = await compressAccurately(file, 150);
            }
            if (bole?.size > 300000) {
              bole = await compressAccurately(file, 100);
            }
            let newFile = await blobToBase64(bole);
            message.warning({
              content: `选择的图片大于${fileSize / 1024}KB，图片已压缩`,
              duration: 3,
            });
            file = await dataURLtoFile(newFile, file?.name);
          }
        } else if (mediaType === 'VIDEO') {
          if (file?.size > fileSize) {
            // 大于100mb进入压缩
            message.error({
              content: `选择的视频大于${fileSize / 1024 / 1024}MB，请重新选择提交`,
              duration: 3,
            });
            return;
          }
        }
        set({ upLoadLoading: true });
        let width = 0;
        let height = 0;
        if (mediaType === 'IMG') {
          let imgData = await getImgSize(file);
          width = imgData.width;
          height = imgData.height;
        } else if (mediaType === 'VIDEO') {
          let videoInfo: any = await videoMessage([file]);
          width = videoInfo[0].width;
          height = videoInfo[0].height;
        }
        /**修改文件名以用户设置的文件title命名*/
        let newFile = new File(
          [file],
          data?.title ? data?.title + '.' + file?.name?.split('.')[1] : file?.name,
          { type: file?.type },
        );
        let formData = new FormData();

        /**向阿里云请求上传地址*/
        fileUrl
          .run({ type: newFile.type, fileType: mediaType === 'VIDEO' ? 'video' : 'image' })
          .then((res1) => {
            Object.keys(res1).forEach((key: string) => {
              if (key !== 'url') {
                formData.append(key, res1[key]);
              }
            });
            formData.append('file', newFile);
            /**向阿里云返回的上传地址上传文件*/
            request(res1?.ossUrl, { method: 'post', body: formData })
              .then(async (res2: { code: number; data: { url: string } }) => {
                if (res2.code === 200) {
                  message.success('上传成功');
                  if (data) {
                    /**取到返回的文件地址向后端发送具体数据*/
                    if (res2?.data?.url) {
                      let fileMd5 = await getMD5(newFile);
                      let obj: any = {
                        title: data.title,
                        mediaType,
                        folder: false,
                        parentId,
                        width,
                        height,
                        fileMd5,
                        belongUser: belongUser === '0' ? false : true,
                        url: res2?.data?.url,
                        sort: data?.sort,
                        fileSize: newFile?.size,
                        fileMime: newFile.type,
                      };
                      if (mediaType === 'VIDEO') {
                        obj['videoTitle'] = data?.videoTitle || data?.title;
                        obj['videoDescription'] = data?.videoDescription;
                      }
                      if (!obj?.title) {
                        obj.title = data.file.name
                      }
                      if (obj.title.match(RegExp(/[<>&\\'"/\x08\x09\x0A\x0D\x7F]/g))) {
                        obj.title = obj.title.replace(RegExp(/[<>&\\'"/\x08\x09\x0A\x0D\x7F]/g), '')
                      }
                      obj.title = obj.title.replace(/\.(jpg|jpeg|gif|png)$/i, '')
                      add.run(obj).then((res) => {
                        list.refresh();
                        offEditFile(); //关闭弹窗并清空相关数据
                        set({ upLoadLoading: false });
                      }).catch(() => set({ upLoadLoading: false }));
                    }
                  }
                } else {
                  message.error('上传失败！');
                }
              })
              .catch(() => set({ upLoadLoading: false }));
          })
          .catch(() => set({ upLoadLoading: false }));
      }
    }
  };

  /** 批量新增图片 视频 */
  const addFiles = async (data: any) => {
    if (data) {//存在代表素材
      if (!data) {
        return
      }
      let { files, ...value } = data
      let params = files?.map(async (item: any, index: number) => {
        let file = item
        let fileSize = size || 0
        if (mediaType === 'IMG') {
          fileSize = value?.fileSize ? value?.fileSize * 1024 : 307200
        } else {
          fileSize = 104857600
        }

        if (mediaType === 'IMG') {
          let bad = 50
          let size = fileSize / 1024
          if (size > 10 && size <= 50) {
            bad = 5
          } else if (size > 50 && size <= 100) {
            bad = 10
          } else if (size > 100 && size <= 300) {
            bad = 20
          } else {
            bad = 50
          }
          if (file?.size > fileSize) { // 大于300kb进入压缩
            let bole = await compressAccurately(file, fileSize / 1024 - bad)
            if (bole?.size > fileSize) {
              bole = await compressAccurately(file, fileSize / 1024 - bad * 2)
            }
            if (bole?.size > fileSize) {
              bole = await compressAccurately(file, fileSize / 1024 - bad * 3)
            }
            if (bole?.size > fileSize) {
              bole = await compressAccurately(file, fileSize / 1024 - bad * 4)
            }
            let newFile = await blobToBase64(bole)
            message.warning({
              content: `选择的图片大于${fileSize / 1024}KB，图片已压缩`,
              duration: 3
            })
            file = await dataURLtoFile(newFile, file?.name)
          }
        } else if (mediaType === 'VIDEO') {
          if (file?.size > fileSize) { // 大于100mb进入压缩
            message.error({
              content: `选择的视频大于${fileSize / 1024 / 1024}MB，请重新选择提交`,
              duration: 3
            })
            return
          }
        }
        let width = 0
        let height = 0
        if (mediaType === 'IMG') {
          let imgData = await getImgSize(file)
          width = imgData.width
          height = imgData.height
        } else if (mediaType === "VIDEO") {
          let videoInfo: any = await videoMessage([file])
          width = videoInfo[0].width
          height = videoInfo[0].height
        }
        /**修改文件名以用户设置的文件title命名*/
        let newFile = new File([file], data?.title ? data?.title + index + 1 + '.' + file?.name?.split('.')[1] : file?.name, { type: file?.type })
        let formData = new FormData();
        set({ upLoadLoading: true })
        let res = await getFileUrl({ type: newFile.type, fileType: mediaType === 'VIDEO' ? 'video' : 'image' }).catch(() => set({ upLoadLoading: false }))
        let res1 = res.data
        Object.keys(res1).forEach((key: string) => {
          if (key !== 'url') {
            formData.append(key, res1[key])
          }
        })
        formData.append('file', newFile)
        /**向阿里云返回的上传地址上传文件*/
        let data1: { code: number, data: { url: string } } = await request(res1?.ossUrl, { method: 'post', body: formData }).catch(() => set({ upLoadLoading: false }))
        message.success('上传成功')
        let fileMd5 = await getMD5(newFile)
        let obj: any = { title: data.title + (index + 1).toString(), folder: false, parentId, width, height, fileMd5, url: data1?.data?.url, sort: data?.sort, fileSize: newFile?.size, fileMime: newFile.type }
        if (mediaType === 'VIDEO') {
          obj['videoTitle'] = data?.videoTitle || data?.title
          obj['videoDescription'] = data?.videoDescription
        }
        return { ...obj }
      })

      Promise.all(params).then(res => {
        adds.run({ belongUser: belongUser === '0' ? false : true, data: res }).then(response => {
          list.refresh()
          offEditFile()//关闭弹窗并清空相关数据
          set({ upLoadLoading: false })
        }).catch(() => set({ upLoadLoading: false }))
      })
    }
  }

  /**编辑非图文素材名称*/
  const nameOk = useCallback((selectWx: any) => {
    if (fileName && actionItem) {
      let obj = {
        title: fileName,
        belongUser: belongUser === '0' ? false : true,
        sysMediaId: actionItem?.id,
        mediaType: actionItem?.mediaType,
        folder: actionItem?.folder,
        url: actionItem?.url,
        sort,
      };
      // if (mediaType === 'VIDEO') {
      //   obj['videoTitle'] = videoTitle;
      //   obj['videoDescription'] = videoDescription;
      // }
      edit.run(obj).then((res) => {
        list.refresh();
        get_folder_tree.refresh()
        offEditFile(); //关闭弹窗并清空相关数据
      });
    }
  },
    [fileName, actionItem, edit, belongUser, mediaType, videoTitle, videoDescription],
  );
  /**删除文件 */
  const dels = useCallback((id?: any) => {
    let arr = typeof id === 'number' ? [id] : selectFile;
    let len = arr?.length || 0;
    if (len) {
      arr?.map((id, index) => {
        del.run({ sysMediaId: id, mediaType }).then(() => {
          set({ selectFile: selectFile?.filter((i) => i !== id) }); //清理已删除文件
          if (index === len - 1) {
            list.refresh();
            get_folder_tree.refresh();
          }
        });
      });
    } else {
      message.error('请选择文件')
    }
  },
    [list, selectFile, mediaType],
  );
  /**获取本地素材数据列表 */
  const getList = useCallback(
    (props?: any) => {
      console.log('getList====>', props);
      let obj = {
        pageSize: 30,
        pageNum: 1,
        belongUser: belongUser === '0' ? false : true,
        mediaType,
        parentId,
        sizeQueries: cloudSize,
        maxSize,
        ...props,
      };
      if (mediaType === 'PAGE') {
        obj = {
          ...obj,
          adcreativeTemplateId,
          promotedObjectType,
          promotedObjectId,
          pageType,
          canvasType,
          siteSet,
          sourceType,
          marketingScene,
        };
      }
      list.run(obj).then((res) => {
        setIsOk(true);
      });
    },
    [list, mediaType, belongUser, parentId, cloudSize, maxSize, adcreativeTemplateId, promotedObjectType, promotedObjectId, pageType, canvasType, siteSet, sourceType, marketingScene],
  );
  /**选中文件 single 开启可单选为了在右键删除选择时只选一个*/
  const onFile = useCallback(
    (e: any, item: { id: any; folder?: boolean }, isAll?: boolean, single?: boolean) => {
      let { id } = item;
      e?.stopPropagation();
      if (isAll && !single) {
        set({ selectFile: [...new Set([...(selectFile as number[]), id])] });
      } else {
        if (item?.folder && !single) {
          //假如是文件不让选择
          message.error('不能选择文件夹');
          return;
        }
        set({ selectFile: [item.id], selectItem: [item] });
      }
    },
    [selectFile],
  );
  /**点击文件夹 */
  const fileClick = useCallback(
    (item: any) => {
      if (isOk) {
        setIsOk(false);
        if (belongUser == '1' && path) {
          set({ path: [...path, item] });
        }
        if (belongUser == '0' && publicPath) {
          set({ publicPath: [...publicPath, item] });
        }
        set({ parentId: item.id });
        getList({ parentId: item.id }); //请求对应文件夹列表
      }
    },
    [path, publicPath, mediaType, belongUser, isOk],
  );
  /**点击目录树*/
  const treeClick = useCallback(
    (item: any) => {
      if (isOk) {
        setIsOk(false);
        console.log(item, belongUser == '1');
        if (belongUser == '1' && path) {
          set({ path: [path[0], item] });
        }
        if (belongUser == '0' && publicPath) {
          set({ publicPath: [publicPath[0], item] });
        }
        set({ parentId: item.id });
        getList({ parentId: item.id }); //请求对应文件夹列表
      }
    },
    [path, publicPath, mediaType, belongUser, isOk],
  );
  /**点击路径 */
  const pathClick = useCallback(
    (item: any) => {
      let newPath: any[] = [];
      if (belongUser == '1') {
        path?.forEach((paths, index) => {
          //用传入的index和path循环的index对比小于等于index代表该保留的路径
          if (index <= item.index) {
            newPath.push(paths);
          }
        });
        set({ path: newPath });
      } else {
        publicPath?.forEach((paths, index) => {
          //用传入的index和path循环的index对比小于等于index代表该保留的路径
          if (index <= item.index) {
            newPath.push(paths);
          }
        });
        set({ publicPath: newPath });
      }
      set({ parentId: item.parentId });
      getList({
        pageSize: 30,
        pageNum: 1,
        mediaType,
        belongUser: belongUser === '0' ? false : true,
        parentId: item.id,
      });
    },
    [path, mediaType, belongUser, publicPath],
  );
  /**取消文件 */
  const offFile = useCallback(
    (e: any, item: { id: any }) => {
      let { id } = item;
      set({ selectFile: selectFile?.filter((i) => i !== id) });
    },
    [selectFile],
  );
  /**判断是取消还是选中文件的操作在点击打钩时使用 */
  const changeClickFile = useCallback((e: any, item: { id: any; folder?: boolean, url: string }, isAll?: boolean, noFile?: boolean) => {
    let { id, url } = item;
    e?.stopPropagation(); //阻止冒泡传递到文件夹被点击事件
    let state = selectItem?.some((i) => i.url === url);
    if (state) {
      //存在就是删除
      set({
        selectFile: selectFile?.filter((i) => i !== id),
        selectItem: selectItem?.filter((i: { url: string }) => i.url !== url),
      });
    } else {
      //否则新增
      if (num === 1) {
        if (state) {
          //存在就是删除
          set({ selectFile: selectFile?.filter((i) => i !== id), selectItem: [] });
        } else {
          //否则新增
          set({ selectFile: [id], selectItem: [item] });
        }
      } else {
        if (selectFile && num && selectFile?.length >= num) {
          message.error(`只能选择${num}张`);
          return;
        }
        let newSelectItem = selectItem || [];
        newSelectItem.push(item);
        set({ selectItem: newSelectItem, selectFile: [...(selectFile as number[]), id] });
      }
    }
    // }
  },
    [selectFile, mediaType, num],
  );
  /**开启删除弹窗 */
  const delPupOn = useCallback((delPupId: any) => {
    set({ delPupId });
  }, []);
  /**关闭删除弹窗并去除选中 */
  const delPupOff = useCallback(() => {
    set({ delPupId: '' });
    offFile(null, { id: delPupId });
  }, [delPupId]);
  /**编辑 */
  const editFile = useCallback((e?: any) => {
    e?.stopPropagation();
    onFile(null, rightClickPup, true, true);
    let obj = { fileVisible: true, actionItem: { ...rightClickPup, fileType: mediaType }, fileName: rightClickPup.title, sort: rightClickPup.sort };
    // if (rightClickPup?.mediaType === "video") {
    //   obj['videoTitle'] = rightClickPup?.videoTitle || rightClickPup?.title;
    //   obj['videoDescription'] = rightClickPup?.videoDescription;
    // }
    set(obj);
  },
    [rightClickPup],
  );
  /**取消编辑后清空选中存放的数据并关闭弹窗*/
  const offEditFile = useCallback(() => {
    set({
      fileVisible: false,
      imgVisrible: false,
      imgsVisrible: false,
      sortVisible: false,
      actionItem: '',
      fileName: '',
      selectFile: selectFile?.filter((id) => id !== actionItem?.id),
      sort: 0,
    });
  }, [selectFile, actionItem]);
  /**全选反选文件*/
  const allFile = useCallback((type: 'xz' | 'qx') => {
    let allArr: any[] = [], allFile: any[] = [];
    list?.data?.records?.forEach((item: { id: any }) => {
      allArr.push(item.id);
      allFile.push(item)
    });
    let newSelectFile = selectFile || []
    let newSelectItem = selectItem || []
    if (type === 'xz') {
      newSelectFile = newSelectFile.concat(allArr.filter((i) => selectFile?.every((id) => id !== i)))
      newSelectItem = newSelectItem.concat(allFile.filter((i) => selectItem?.every((item: any) => item.id !== i.id)))
    } else {
      newSelectFile = newSelectFile.filter(item => !allArr.includes(item))
      newSelectItem = newSelectItem.filter(item => !allArr.includes(item.id))
    }
    set({
      selectFile: newSelectFile,
      selectItem: newSelectItem
    });
  }, [selectFile, list, mediaType, selectItem]);
  return {
    state,
    init,
    set,
    addFile,
    addFolder,
    getList,
    dels,
    onFile,
    changeClickFile,
    allFile,
    delPupOn,
    delPupOff,
    editFile,
    offEditFile,
    nameOk,
    fileClick,
    treeClick,
    pathClick,
    addFiles,
    configSort,
    list,
    add,
    get,
    edit,
    typeEnum,
    get_folder_tree,
    edit_media_folder,
  };
}
export default useBdMediaPup;
