// require('es6-promise').polyfill();
// require('isomorphic-fetch');

import { getToken, setToken } from '@/webPublic/one_stop_public/utils/token';
import { controlNotification, isJSON } from '@/webPublic/zyd_public/utils/utils';
import { setFetchUrl, getFetchUrl } from './fetchData';

const codeMessage = {
	200: '服务器成功返回请求的数据。',
	201: '新建或修改数据成功。',
	202: '一个请求已经进入后台排队（异步任务）。',
	204: '删除数据成功。',
	400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
	401: '登录已过期,请重新登录',
	403: '用户得到授权，但是访问是被禁止的。',
	404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
	406: '请求的格式不可得。',
	410: '请求的资源被永久删除，且不会再得到的。',
	422: '当创建一个对象时，发生一个验证错误。',
	500: '服务器发生错误，请检查服务器。',
	502: '网关错误。',
	503: '服务不可用，服务器暂时过载或维护。',
	504: '网关超时。',
};

const checkStatus = (response) => {
	const status = Number(response.status);
	if (status === 200) {
		return response;
	}
	const errortext = codeMessage[status] || response.message;
	const token = getToken();
	if (token && token !== 'null') {
		controlNotification({
			message: `${status === 401 ? '登录过期' : '请求错误'}`,
			description: errortext,
		});
	}
	if (status === 401) {
		setToken('');
		return {
			status: 401,
			message: '登录过期', // token不对
		};
	}
	const error = new Error(errortext);
	error.name = status + '';
	console.error(response.message);
	throw error;
};

async function queryLocalStorage() {
	return false;
}

function setFetchInfo(url, options) {
	let session = getFetchUrl();
	if (isJSON(session)) {
		let newSession = JSON.parse(session);
		if (newSession.url === url && new Date().valueOf() - newSession.time < 500) {
			if (options.body && JSON.stringify(options.body) === newSession.body) {
				console.log('频繁调用接口: ', url, newSession.body);
				return '';
			}
		}
	}

	return JSON.stringify({
		url,
		time: new Date().valueOf(),
		body: options.body ? JSON.stringify(options.body) : '',
	});
}

export default function requestJson(url, options) {
	let sessionFetch = setFetchInfo(url, options);
	if (!sessionFetch) {
		return queryLocalStorage();
	} else {
		setFetchUrl(sessionFetch);
	}
	let defaultToken = getToken();
	const token = defaultToken !== null && defaultToken !== 'null' ? defaultToken : '';

	if (options.time) {
		const time = new Date().getTime();
		if (url.indexOf('?') === -1) {
			url = url + '?time=' + time;
		} else {
			url = url + '&time=' + time;
		}
	}
	const defaultOptions = {
		credentials: 'include',
		mode: 'cors',
	};
	let newOptions = { ...defaultOptions, ...options };
	if (token) {
		url = url.indexOf('?') > -1 ? `${url}&token=${token}` : `${url}?token=${token}`;
	}

	newOptions = {
		method: 'POST', // 暂时支持post 请求
		headers: {
			Accept: 'application/json;charset=UTF-8',
			'Content-Type': 'application/json',
			...newOptions.headers,
		},
		...newOptions,
		body: JSON.stringify(newOptions.body),
	};

	if (options.method && options.method.toUpperCase() === 'GET') {
		newOptions.body = undefined;
	}
	return fetch(url, newOptions)
		.then((res) => {
			return checkStatus(res);
		})
		.then((response) => {
			return response.json();
		})
		.then((response) => {
			if (response.state === 401) {
				return {
					status: 401,
					message: 'token无效,认证失败!', // 可能是跨域 可能是token过期
				};
			}

			if (response.status === 401) {
				return response;
			}

			if (typeof response.code === 'undefined' || response.code === 'invalid_token') {
				return response;
			}

			if (response.code === '0' && typeof response.data !== 'undefined') {
				return response.data; // 真正需要的数据
			} else {
				if (response.message) {
					controlNotification({
						message: response.message,
					});
					const error = new Error(response.message);
					error.name = response.code;
					console.error(response.message);
					throw error;
				} else {
					controlNotification({
						message: '数据错误',
					});
					const error = new Error(response.code);
					error.name = response.code;
					console.error(response.code);
					throw error;
				}
			}
		})
		.catch((e) => {
			const status = e.name;
			if (status === 401) {
				return false;
			}
			if (!window.navigator.onLine) {
				return controlNotification({
					message: '网络故障',
					description: `无法连接到网络,请稍后再试`,
				});
			}
			controlNotification({
				message: '网络故障',
				description: `无法连接到服务器,请稍后再试`,
			});
			return;
		});
}
