import message from 'components/message';
import http, { request } from 'utils/fetch';
import { api } from 'constants/config';
import { actionTypes } from 'constants/action-types';
import { getScreenId } from 'utils/screen';
import { deepUpdate } from 'utils/data-helper';
import { omitUndefined ,getAssetsUrl} from 'utils/utils';
import { ScreenItem } from './screen.types';

const THUMB_OSS_SUFFIX = '?x-oss-process=image/resize,m_pad,w_310,h_180,color_181b24';

export function getScreens() {
  return async (dispatch) => {
    dispatch({
      type: actionTypes.SCREEN_GET_LIST_START
    });

    const result: _resulf | null = await http.get(api.screenList);
    interface _screens {
      id: number;
      groupId: null | number;
      name: string;
      thumb: null | string | number;
      sharePassword: string;
      apps: Array<any>;
      share: any;
      shareToken?: string;
      shareInfo?: {
        description: string;
        thumb: string;
        title: string;
      };
      deletedAt?: Date;
      expiredAt?: Date;
      updatedAt: Date;
      createdAt: Date;
    }
    interface _resulf {
      screens: _screens[];
    }
    if (result) {
      const mappedList = result.screens.map((d) => ({
        screenId: d.id,
        groupId: d.groupId,
        screenName: d.name,
        thumb: d.thumb ? getAssetsUrl(`${d.thumb}${THUMB_OSS_SUFFIX}`) : null,
        share: d.share,
        password: d.sharePassword,
        shareToken: d.shareToken,
        shareInfo: d.shareInfo,
        apps: d.apps || [],
        deletedAt: d.deletedAt,
        expiredAt: d.expiredAt,
        updatedAt: d.updatedAt,
        createdAt: d.createdAt
      }));

      dispatch({
        type: actionTypes.SCREEN_GET_LIST_SUCCESS,
        payload: {
          list: mappedList
        }
      });
      return result;
    } else {
      dispatch({
        type: actionTypes.SCREEN_GET_LIST_FAILURE
      });
    }
  };
}

export function addScreen(id, courseId) {
  return async (_dispatch, getState) => {
    const { groups } = getState();
    const { current } = groups;

    const body: {
      templateId?: number;
      courseId?: number;
      groupId?: number;
    } = {};

    if (id) {
      body.templateId = id;
    }

    if (courseId) {
      body.courseId = courseId;
    }

    if (typeof current === 'number' && current > 0) {
      body.groupId = current;
    }

    const result = await request(api.screenAdd, undefined, undefined, JSON.stringify(body));

    return result;
  };
}

export function copyScreen(screenId) {
  return async (dispatch, getState) => {
    const { screens, space } = getState();
    let { list } = screens;
    list = list.filter((d) => !d.deletedAt);
    const screenCount = space?.active?.size || 0;
    if (list.length >= screenCount) {
      message.error('您的应用数已超出上限，请删除部分应用后再试');
      return;
    }
    const hide = message.loading('正在复制可视化应用...', 0);

    const result = await request(api.screenCopy, undefined, undefined, JSON.stringify({ screenId }));

    hide();
    if (result) {
      message.success('复制成功');
      const originScreen = list.find((d) => d.screenId === screenId);
      const screen = {
        screenId: result.id,
        screenName: result.name,
        groupId: originScreen.groupId,
        thumb: originScreen.thumb,
        share: false,
        apps: []
      };

      dispatch({
        type: actionTypes.SCREEN_COPY_SUCCESS,
        payload: screen
      });
    }
  };
}

export function updateScreen(updateData) {
  return async (dispatch, getState) => {
    const screenId = getScreenId();
    const { screensById } = getState();

    const newState: any = deepUpdate(updateData, screensById[screenId]);

    dispatch({
      type: actionTypes.SCREEN_UPDATE_SUCCESS,
      payload: {
        id: newState.id,
        name: newState.name,
        leftBarWidth: newState.leftBarWidth,
        groupId: newState.groupId,
        thumb: newState.thumb,
        config: newState.config,
        lines: newState.lines
      }
    });

    const result = await http.post(api.screenUpdate, updateData);

    return result;
  };
}

export function updateScreenShare({
  id,
  share,
  needPassword,
  sharePassword,
  needToken,
  shareInfo
}: {
  id: number;
  share: boolean;
  needPassword: boolean;
  sharePassword?: string | null;
  needToken?: boolean;
  shareInfo?: {
    title: string;
    description: string;
    thumb: string;
  };
}) {
  return async (dispatch) => {
    const result: any = await http.post(
      api.screenShareUpdate,
      {
        id,
        share,
        needPassword,
        sharePassword,
        needToken,
        shareInfo
      },
      {
        error: () => {
          message.error('操作失败');
        }
      }
    );

    if (result) {
      if (result.share) {
        message.success('发布成功');
      }

      dispatch({
        type: actionTypes.SCREEN_SHARE_UPDATE,
        payload: {
          id,
          share: result.share,
          sharePassword: result.sharePassword,
          shareToken: result.shareToken,
          shareInfo: result.shareInfo
        }
      });
    }
  };
}

export function deleteScreen(id: number | number[]) {
  return async (dispatch) => {
    const hide = message.loading('删除中...', 0);
    const result = await http.post(
      api.screenDelete,
      { id },
      {
        error: () => {
          message.error('删除失败');
        }
      }
    );
    hide();
    if (result) {
      message.success('删除成功');

      dispatch(getScreens());
      return result;
    }
  };
}

export function toNextPage() {
  return (dispatch) => {
    dispatch({
      type: actionTypes.SCREEN_NEXT_PAGE
    });
  };
}

export function searchScreen(search) {
  return {
    type: actionTypes.SCREEN_SEARCH,
    payload: search
  };
}

export function dragScreenStart(screenId) {
  return {
    type: actionTypes.SCREEN_DRAG_START,
    payload: {
      isDragging: true,
      dragScreenId: screenId
    }
  };
}

export function dragScreenEnd() {
  return {
    type: actionTypes.SCREEN_DRAG_END,
    payload: {
      isDragging: false,
      dragScreenId: null
    }
  };
}

export function selectScreen(screenId) {
  return {
    type: actionTypes.SCREEN_SELECT,
    payload: screenId
  };
}

export function unselectScreen(screenId) {
  return {
    type: actionTypes.SCREEN_UNSELECT,
    payload: screenId
  };
}

export function selectAllScreen(screens) {
  return {
    type: actionTypes.SCREEN_ALL_SELECT,
    payload: screens
  };
}

export function cancelSelectedCurrentGroupScreen(screens) {
  return {
    type: actionTypes.SCREEN_ALL_SELECT,
    payload: screens
  };
}
/**
 *
 * @param sortType
 * @returns 更新大屏筛选方式
 */
export function updateScreensSortType(sortType: ScreensState['sortType']) {
  return {
    type: actionTypes.UPDAE_SCREEN_SORT_TYPE,
    payload: sortType
  };
}

export function openMultiExport() {
  return {
    type: actionTypes.SCREEN_EXPORT_OPEN
  };
}

export function closeMultiExport() {
  return {
    type: actionTypes.SCREEN_EXPORT_CLOSE
  };
}

export function clearScreenList() {
  return {
    type: actionTypes.SCREEN_LIST_CLEAR
  };
}

export function importScreen(data, signal) {
  return async () => {
    let errMsg;
    const result = await request(api.screenImport, undefined, undefined, JSON.stringify(data), {
      signal,
      error: (err) => {
        errMsg = { message: err.message, code: -1 };
      }
    });
    return errMsg ? errMsg : result;
  };
}

// 修改列表页屏幕的信息
export function changeInfo({ id, name, groupId }: { id: number; name?: string; groupId?: number }) {
  return async (dispatch, getState) => {
    const { screens } = getState();
    const list = screens.list;
    const screen = list.find((item) => item.screenId === id);
    if (!screen) return;

    dispatch({
      type: actionTypes.SCREEN_LIST_UPDATE_SUCCESS,
      payload: {
        id,
        screenName: name,
        groupId: groupId
      }
    });

    await http.post(api.screenUpdate, {
      id,
      name,
      groupId: groupId === null ? -1 : groupId
    });
  };
}

// 从回收站恢复大屏
export function restoreScreen(id) {
  return async (dispatch, getState) => {
    const { screens, space } = getState();
    const screenCount = space.active?.size || 0;
    const currentCount = screens.list.filter((d) => !d.deletedAt).length;
    if (currentCount >= screenCount) {
      message.error('项目数量已达上限，若对项目空间有更高的要求，可联系我们');
      return;
    }

    const result = await http.post(api.screenRestore, { id });

    if (result) {
      dispatch(getScreens());
    }

    return result;
  };
}

export type Screens = ScreenItem[];

export interface ScreensState {
  loading: boolean;
  list: Screens;
  page: number;
  pageSize: number;
  search: string;
  isDragging: boolean;
  dragScreenId: null | number;
  isMultiExport: boolean;
  selectedScreens: number[];
  sortType: 'byCreatedAt' | 'byUpdatedAt';
}

const initialState: ScreensState = {
  loading: false,
  list: [],
  page: 0,
  pageSize: 20,
  search: '',
  isDragging: false,
  dragScreenId: null,
  isMultiExport: false,
  selectedScreens: [],
  sortType: 'byUpdatedAt' // 大屏排序方式
};

export default function screensReducer(state = initialState, { type, payload }) {
  switch (type) {
    case actionTypes.SCREEN_GET_LIST_START: {
      return { ...state, loading: true };
    }
    case actionTypes.SCREEN_GET_LIST_SUCCESS: {
      return { ...state, loading: false, list: payload.list };
    }
    case actionTypes.SCREEN_GET_LIST_FAILURE: {
      return { ...state, loading: false };
    }
    case actionTypes.SCREEN_LIST_UPDATE_SUCCESS: {
      const newList = state.list.map((d) => {
        if (d.screenId === payload.id) {
          return {
            ...d,
            ...omitUndefined(payload)
          };
        } else {
          return d;
        }
      });
      return { ...state, list: newList };
    }
    case actionTypes.SCREEN_SHARE_UPDATE: {
      const newList = state.list.map((d) => {
        if (d.screenId === payload.id) {
          return {
            ...d,
            share: payload.share,
            password: payload.sharePassword,
            shareToken: payload.shareToken,
            shareInfo: payload.shareInfo
          };
        } else {
          return d;
        }
      });
      return { ...state, list: newList };
    }
    case actionTypes.SCREEN_COPY_SUCCESS: {
      return { ...state, list: [payload].concat(state.list) };
    }
    case actionTypes.SCREEN_DELETE_SUCCESS: {
      const newList = state.list.filter((d) => payload !== d.screenId);
      return { ...state, list: newList };
    }
    case actionTypes.SCREEN_NEXT_PAGE: {
      return { ...state, page: state.page + 1 };
    }
    case actionTypes.SCREEN_TOP_PAGE: {
      return { ...state, page: 1 };
    }
    case actionTypes.SCREEN_SEARCH: {
      return { ...state, search: payload, page: 1 };
    }
    case actionTypes.SCREEN_DRAG_START: {
      return { ...state, ...payload };
    }
    case actionTypes.SCREEN_DRAG_END: {
      return { ...state, ...payload };
    }
    case actionTypes.SCREEN_EXPORT_OPEN: {
      return { ...state, isMultiExport: true };
    }
    case actionTypes.SCREEN_EXPORT_CLOSE: {
      return { ...state, isMultiExport: false, selectedScreens: [] };
    }
    case actionTypes.SCREEN_SELECT: {
      const newSelectedScreens = state.selectedScreens.concat(payload);
      return { ...state, selectedScreens: newSelectedScreens };
    }
    case actionTypes.SCREEN_UNSELECT: {
      const newSelectedScreens = state.selectedScreens.filter((d) => d !== payload);
      return { ...state, selectedScreens: newSelectedScreens };
    }
    case actionTypes.SCREEN_ALL_SELECT: {
      return { ...state, selectedScreens: payload };
    }
    case actionTypes.SCREEN_LIST_CLEAR: {
      return { ...state, list: [] };
    }
    case actionTypes.UPDAE_SCREEN_SORT_TYPE: {
      return { ...state, sortType: payload };
    }
    default:
      return state;
  }
}
