// 运行时配置

// 全局初始化数据配置，用于 Layout 用户信息和权限初始化
// 更多信息见文档：https://umijs.org/docs/api/runtime-config#getinitialstate
import auth from '@/services/auth';
import { getRedirectUrl } from '@/utils/getRedirectUrl';
import { RunTimeLayoutConfig } from '@@/plugin-layout/types';
import { RequestConfig } from '@@/plugin-request/request';
import { history } from '@umijs/max';
import { message, notification } from 'antd';
import './global.less';

interface InitialState {
	channel?: AuthAPI.ChannelVO;
	homePagePath?: string;
	tip?: {
		show: boolean;
		message: string;
	};
}

export async function getInitialState(): Promise<InitialState> {
	await getRedirectUrl();

	const { data: channel } = await auth.channel.selectChannelByDomain({
		domain: window.location.host,
	});

	return {
		channel,
		tip: {
			show: false,
			message: '',
		},
	};
}

export const layout: RunTimeLayoutConfig = ({ initialState }) => {
	const link =
		document.querySelector("link[rel*='icon']") ||
		document.createElement('link');
	link.type = 'image/x-icon';
	link.rel = 'shortcut icon';
	link.href = initialState?.channel?.logo;
	document.getElementsByTagName('head')[0].appendChild(link);

	return {
		title: initialState?.channel?.title,
		subTitle: initialState?.channel?.subTitle,
		logo: initialState?.channel?.logo,
	};
};

// 错误处理方案： 错误类型
enum ErrorShowType {
	SILENT = 0,
	WARN_MESSAGE = 1,
	ERROR_MESSAGE = 2,
	NOTIFICATION = 3,
	REDIRECT = 9,
}

// 与后端约定的响应数据格式
interface ResponseStructure {
	success: boolean;
	data: any;
	errCode?: string;
	errMessage?: string;
	showType?: ErrorShowType;
}

// 运行时配置
export const request: RequestConfig = {
	// 统一的请求设定
	timeout: 60000,
	headers: {
		'X-Requested-With': 'XMLHttpRequest',
		'Xh-Platform-Id': '1769220738064285698',
	},

	// 错误处理： umi@3 的错误处理方案。
	errorConfig: {
		// 错误抛出
		errorThrower: (res: ResponseStructure) => {
			const { success, data, errCode, errMessage, showType } = res;
			if (!success) {
				if (errCode === '401' || errCode === '403') {
					// 未登录，跳转到登录页面
					history.push('/login');
					return;
				}

				if (errCode === '400') {
					message.error(errMessage);
					return;
				}

				if (errCode === 'UNKNOWN_ERROR') {
					message.error('未知的错误');
					return;
				}

				if (errCode === 'USER_AUTH_NOT_LOGIN') {
					return;
				}

				if (errCode === 'USER_AUTH_NO_APP_PERMISSION') {
					message.error(errMessage);
					return;
				}

				const error: any = new Error(errMessage || errCode);
				error.name = 'BizError';
				error.info = { errCode, errMessage, showType, data };
				throw error; // 抛出自制的错误
			}
		},
		// 错误接收及处理
		errorHandler: (error: any, opts: any) => {
			if (opts?.skipErrorHandler) throw error;
			// 我们的 errorThrower 抛出的错误。
			if (error.name === 'BizError') {
				const errorInfo: ResponseStructure | undefined = error.info;
				if (errorInfo) {
					const { errMessage, errCode } = errorInfo;
					switch (errorInfo.showType) {
						case ErrorShowType.SILENT:
							// do nothing
							break;
						case ErrorShowType.WARN_MESSAGE:
							message.warning(errMessage);
							break;
						case ErrorShowType.ERROR_MESSAGE:
							message.error(errMessage);
							break;
						case ErrorShowType.NOTIFICATION:
							notification.open({
								description: errMessage,
								message: errCode,
							});
							break;
						case ErrorShowType.REDIRECT:
							// TODO: redirect
							break;
						default:
							message.error(errMessage);
					}
				}
			} else if (error.response) {
				// Axios 的错误
				// 请求成功发出且服务器也响应了状态码，但状态代码超出了 2xx 的范围
				message.error(`Response status:${error.response.status}`);
			} else if (error.request) {
				// 请求已经成功发起，但没有收到响应
				// \`error.request\` 在浏览器中是 XMLHttpRequest 的实例，
				// 而在node.js中是 http.ClientRequest 的实例
				message.error('None response! Please retry.1');
			} else {
				// 发送请求时出了点问题
				message.error('Request error, please retry.2');
			}
		},
	},

	// 请求拦截器
	requestInterceptors: [
		(
			url: any,
			options: {
				headers: any;
			},
		) => {
			console.log('请求拦截器', url, options);
			const apiUrl = '/api' + url;
			return {
				url: apiUrl,
				options,
			};
		},
	],

	// 响应拦截器
	responseInterceptors: [
		(response: ResponseStructure) => {
			// 拦截响应数据，进行个性化处理
			return response;
		},
	],
} as any;
