const express = require('express');
const router = express.Router();
const request = require('request');

const config = require('doohanpub').config;

const tj1 = config.get('tj1');

const mongoUrl = config.get('mongoUrl');
const hexinUrl = config.get('hexinUrl');
const wlnUrl = config.get('wlnUrl');
const sbService=config.get('sbService');
//拉取数据接口
let javaSurl = sbService+'/shebao/getSbData';

const analyzeUrl=wlnUrl+':11002/si/analyzeSI';

let wsMap = new Map();
let noWsMap = new Map();
let orderIdMap = new Map();


const QueryStatus = require('./sbFuncLib').QueryStatus;
const UpdateStatus = require('./sbFuncLib').UpdateStatus;

router.ws('/', function (ws, req) {
	console.log('【Router ws】'+JSON.stringify(req.query));
	if (!(req.query.taskId && req.query.orderSn)) {
		return;
	}
	wsMap.set(String(req.query.taskId), ws);
	orderIdMap.set(String(req.query.taskId), {
		orderSn: req.query.orderSn,
		addTime: new Date().getTime(),
		cityName: req.query.cityName,
		type: 'ws'
	});
	try {
		ws.send('ok');
	} catch (err) {
		console.error(err);
	}
	let taskId = String(req.query.taskId);
	wsSendBack(taskId).then(msg => {
		if (msg.errcode !== 2017) {
			if (wsMap.has(taskId)) {
				try {
					wsMap.get(taskId).send(JSON.stringify(msg));
				} catch (err) {
					console.error(err);
				}
			} else {
				msg.addTime = new Date().getTime();
				noWsMap.set(taskId, msg);
			}
		}
	}).catch(err => {
		console.error(err);
		let msg = {errcode: -1, data: {code: 106, msg: '服务器出错啦'}};
		if (wsMap.has(taskId)) {
			try {
				wsMap.get(taskId).send(JSON.stringify(msg));
			} catch (error) {
				console.error(error);
			}
		} else {
			msg.addTime = new Date().getTime();
			noWsMap.set(taskId, msg);
		}
	});
	console.log('【Router ws】WSConnect');
	ws.on('message', function (msg) {
		console.log('【Router ws.onMessage】'+msg);
		if (msg.indexOf('name' > -1)) {
			msg = JSON.parse(msg);
			if (orderIdMap.has(String(req.query.taskId))) {
				orderIdMap.get(String(req.query.taskId)).needGeneral = 1;
				orderIdMap.get(String(req.query.taskId)).name = msg.name;
				orderIdMap.get(String(req.query.taskId)).ID = msg.ID;
				orderIdMap.get(String(req.query.taskId)).phone = msg.phone;
				console.log(orderIdMap.get(String(req.query.taskId)));
			}
		}
	});
	ws.on('close', function () {
		if (wsMap.has(String(req.query.taskId))) {
			wsMap.delete(String(req.query.taskId));
			console.log('【Router ws.onClose】 connectNum' + wsMap.size);
		}
	});
});

router.post('/result', function (req, res) {
	console.log('【Router result】' + JSON.stringify(req.body));
	let taskId = String(req.body.taskId);
	let appKey=req.query.appKey;
	wsSendBack(taskId,appKey).then(msg => {
		if (msg.errcode !== 2017) {
			if (wsMap.has(taskId)) {
				try {
					wsMap.get(taskId).send(JSON.stringify(msg));
				} catch (err) {
					console.error(err);
				}
			} else {
				msg.addTime = new Date().getTime();
				noWsMap.set(taskId, msg);
			}
		}
	}).catch(err => {
		let msg = {errcode: -1, data: {code: 106, msg: '服务器出错啦'}};
		console.error(err);
		if (wsMap.has(taskId)) {
			try {
				wsMap.get(taskId).send(JSON.stringify(msg));
			} catch (error) {
				console.error(error);
			}

		} else {
			msg.addTime = new Date().getTime();
			noWsMap.set(taskId, msg);
		}
	});
	res.send('OK');
});

router.post('/getJob', function (req, res) {
    console.log('【Router getJob】' + JSON.stringify(req.body));
	if (!(req.body.taskId && req.body.orderSn)) {
		console.log('[ /loop]参数错误');
		return res.send('err');
	}
	let msg = {errcode: 0, data: {code: 2, msg: '处理中'}, addTime: new Date().getTime()};
	if (noWsMap.has(String(req.body.taskId))) {
		if (noWsMap.get(String(req.body.taskId)).data.code == 0) {
			res.send(JSON.stringify(noWsMap.get(String(req.body.taskId))));
			noWsMap.delete(String(req.body.taskId));
			orderIdMap.delete(String(req.body.taskId));
		} else {
			res.send(JSON.stringify(noWsMap.get(String(req.body.taskId))));
			if (noWsMap.get(String(req.body.taskId)).data.code !== 2) {
				noWsMap.set(String(req.body.taskId), msg);
			}
		}
	} else {
		noWsMap.set(String(req.body.taskId), msg);
		let taskId = String(req.body.taskId);
		wsSendBack(taskId).then(msg => {
			if (msg.errcode !== 2017) {
				if (wsMap.has(taskId)) {
					try {
						wsMap.get(taskId).send(JSON.stringify(msg));
					} catch (err) {
						console.error(err);
					}

				} else {
					msg.addTime = new Date().getTime();
					noWsMap.set(taskId, msg);
				}
			}
		}).catch(err => {
			console.error(err);
			let msg = {errcode: -1, data: {code: 106, msg: '服务器出错啦'}};
			if (wsMap.has(taskId)) {
				try {
					wsMap.get(taskId).send(JSON.stringify(msg));
				} catch (error) {
					console.error(error);
				}

			} else {
				msg.addTime = new Date().getTime();
				noWsMap.set(taskId, msg);
			}
		});
		res.send(JSON.stringify(noWsMap.get(String(req.body.taskId))));
		orderIdMap.set(String(req.body.taskId), {
			orderSn: req.body.orderSn,
			addTime: new Date().getTime(),
			cityName: req.body.cityName,
			type: 'loop'
		});

	}

});

function wsSendBack(taskId,appKey) {
	return new Promise((resolve, reject) => {
		let msg = {};
		let options = {
			url: javaSurl,
			method: 'POST',
			json: true,
			body: {
				taskId: taskId
			},
			headers: {
				'content-type': 'application/json'
			}
		};
		request(options, (e, r, b) => {
			if (e) {
                console.error('【JAVA getData】获取数据服务出错Req：+' + JSON.stringify({taskId: taskId}) + ' Res: ' + JSON.stringify(e));
                msg = {errcode: 1, data: {code: -1, msg: '服务器出错啦 请稍后重试'}};
			} else {
                console.log('【JAVA getData】Req：' + JSON.stringify({taskId: taskId}) + ' ResCode: ' +b.code+ ' ResMsg: ' +b.msg );
                if (orderIdMap.has(taskId)) {
                    if(JSON.stringify(b).indexOf("违法")>-1||JSON.stringify(b).indexOf("盗取")>-1){
                        console.error("神经病啊"+JSON.stringify(b))
                        msg = {errcode: 1, data: {code: 106, msg: "任务爬取失败"}};
                        upDateGjjStatus({
                            orderSn: orderIdMap.get(taskId).orderSn,
                            taskId: taskId,
                            status: 'failed106',
                            type: 'sb',

                        }).then(result => {
                            console.log('change orderSn:' + orderIdMap.get(taskId).orderSn + ' taskId:' + taskId + 'to failed106');
                            return resolve(msg);
                        }).catch(err => {
                            return resolve(msg);
                        });
                    }
					switch (b.code) {
					case 1:
						msg = {errcode: 0, data: createNextHtml(b.data.loginParam)};
						resolve(msg);
						break;
					case 0:
                        deal0Data(b.data, taskId,appKey).then(upData=>{
                            uploadData(upData).then(upMsg => {
                                msg = {errcode: 0, data: {code: 0, msg: upMsg}};
                                let upParams = {
                                    orderSn: orderIdMap.get(taskId).orderSn,
                                    taskId: taskId,
                                    status: 'success',
                                    type: 'shebao'
                                };
                                upDateGjjStatus(upParams).then(result => {
                                    console.log(result);
                                    console.log('change orderSn:' + orderIdMap.get(taskId).orderSn + ' taskId:' + taskId + 'to SUCCESS');
                                    // callRedirectUrl(result,orderIdMap.get(taskId).orderSn,'success');
                                    serverSideCall(result.cbUrl,orderIdMap.get(taskId).orderSn,'success',result.userId)
                                    resolve(msg);
                                }).catch(err => {
                                    console.log(err);
                                    console.error('change orderSn:' + orderIdMap.get(taskId).orderSn + ' taskId:' + taskId + 'to SUCCESS failed');
                                    resolve(msg);
                                });

                            }).catch(upMsg => {
                                msg = {errcode: 1, data: {code: 0, msg: upMsg}};
                                let upParams = {
                                    orderSn: orderIdMap.get(taskId).orderSn,
                                    taskId: taskId,
                                    status: 'storageFailed',
                                    type: 'shebao'
                                };
                                upDateGjjStatus(upParams).then(result => {
                                    console.log(result);
                                    console.log('change orderSn:' + orderIdMap.get(taskId).orderSn + ' taskId:' + taskId + 'to storageFailed');
                                    resolve(msg);
                                }).catch(err => {
                                    console.error(err);
                                    console.error('change orderSn:' + orderIdMap.get(taskId).orderSn + ' taskId:' + taskId + 'to storageFailed failed');
                                    resolve(msg);
                                });

                            });
                        }).catch(err=>{
                            console.error(err)
                        })
						break;
					case -1:
					case 102:
					case 106:
					case 204:
						msg = {errcode: 1, data: {code: 106, msg: b.msg}};
						upDateGjjStatus({
							orderSn: orderIdMap.get(taskId).orderSn,
							taskId: taskId,
							status: 'failed106',
							type: 'sb',
                            text3:b.msg
						}).then(result => {
							console.log('change orderSn:' + orderIdMap.get(taskId).orderSn + ' taskId:' + taskId + 'to failed106');
							resolve(msg);
						}).catch(err => {
							resolve(msg);
						});

						break;
					case 110:
						msg = {errcode: 2017};
						upDateGjjStatus({
							orderSn: orderIdMap.get(taskId).orderSn,
							taskId: taskId,
							status: 'query',
							type: 'sb',
						}).then(result => {
							msg={errcode: 0, data: {type:'110',code:1}};
							resolve(msg);
						}).catch(err => {
							resolve(msg);
						});
						break;
					default:
						msg = {errcode: 2017};
						break;
					}
				}else{
					msg = {errcode: 2017};
					resolve(msg);
				}

			}
		});
	});

}
function deal0Data(bData, taskId,appKey) {
    return new Promise((resolve, reject) => {
        bData.data = JSON.parse(bData.data);
        bData.orderID = orderIdMap.get(taskId).orderSn;
        let options = {
            url: analyzeUrl,
            method: 'POST',
            json: true,
            body: bData,
            headers: {
                'content-type': 'application/json'
            }
        };
        request(options, (e, r, b) => {
            if (e) {
                console.error('[王鲁宁的处理程序出问题了]');
                console.error(e);
                bData.serviceType = 'shebao';
                bData.taskId = Number(taskId);
                bData.orderId = orderIdMap.get(taskId).orderSn;
                bData.appKey = appKey;
                let cityName = orderIdMap.get(taskId).cityName;
                if (cityName && cityName.length > 4) {
                    cityName = cityName.substr(0, cityName.length - 4);
                }
                if (bData.hasOwnProperty('code')) {
                    delete bData.code;
                }
                bData.cityName = cityName;
                resolve(bData);
            } else {
                if (b.code === 0) {
                    bData.data = b.data;
                    bData.serviceType = 'shebao';
                    bData.orderId = orderIdMap.get(taskId).orderSn;
                    let cityName = orderIdMap.get(taskId).cityName;
                    bData.appKey = appKey;
                    if (cityName && cityName.length > 4) {
                        cityName = cityName.substr(0, cityName.length - 4);
                    }
                    if (bData.hasOwnProperty('code')) {
                        delete bData.code;
                    }
                    if(bData.hasOwnProperty('orderID')){
                        delete bData.orderID;
                    }
                    bData.taskId = Number(taskId);
                    bData.cityName = cityName;
                    resolve(bData);
                } else {
                    console.error('wangluning sbDataerrr');
                    console.error(JSON.stringify(b))
                    bData.serviceType = 'shebao';
                    bData.orderId = orderIdMap.get(taskId).orderSn;
                    let cityName = orderIdMap.get(taskId).cityName;
                    bData.appKey = appKey;
                    if (cityName && cityName.length > 4) {
                        cityName = cityName.substr(0, cityName.length - 4);
                    }
                    if (bData.hasOwnProperty('code')) {
                        delete bData.code;
                    }
                    bData.taskId = Number(taskId);
                    bData.cityName = cityName;
                    resolve(bData);
                }

            }
        });
    })
}
function createNextHtml(loginParam) {
	let contentHtml = '<div id="tab-content"><ul style="display: block;" class="active">';

	var menuHtml = '';
	for (let j = 0; j < loginParam.length; j++) {
		let param = loginParam[j];
		if (param.type !== 'radio') {
			switch (param.name) {
			case 'code':
				contentHtml += `
                                  <div class="input-wrapper">
                                            <label>验证码</label>
                                            <div class="content">
                                                <div class="code">
                                                    <div class="captcha-wrapper failed"><img src=""></div>
                                                </div>
                                                <div class="input"><input name=${param.name} placeholder="${param.note}" class="input-option required" data-label="验证码"></div>
                                            </div>
                                        </div>`;
				break;
			case 'password':
				contentHtml += `
                                  <div class="input-wrapper">
                                        <label>${param.name}</label>
                                        <div class="content">
                                            <div class="input">
                                                <input name=${param.name} type="text" placeholder="${param.note}" class="" data-label="${param.name}">
                                            </div>
                                        </div>
                                    </div>`;
				break;
			case 'phoneCode':
				contentHtml += `
                                  <div class="input-wrapper">
                                        <label>手机验证码</label>
                                        <div class="content">
                                            <div class="input">
                                                <input name="phoneCode" type="text" placeholder="请填写手机验证码" class="input-option required" data-label="手机验证码" data-placeholder="请填写手机验证码" value="" data-value="">
                                            </div>
                                        </div>
                                        
                                        <button class="phoneCodeBtn action" data-api="getPhoneCode" data-req="ID" data-cd="60">免费获取</button>
                                        
                                    </div>`;
				break;
			default:
				contentHtml += `
                                  <div class="input-wrapper">
                                        <label>${param.name}</label>
                                        <div class="content">
                                            <div class="input">
                                                <input name=${param.name} type="text" placeholder="${param.note}" class="" data-label="${param.name}">
                                            </div>
                                        </div>
                                    </div>`;
			}
		} else {
			// console.log(JSON.parse(param.note));
			let note = JSON.parse(param.note);
			menuHtml = `<section class="dark-panel show note-field sel"></section><div class="selectMenu">
                                    <h1 class="title">需要您选择</h1>
                                    <ul class="sel-content">`;
			for (let menu in JSON.parse(param.note)) {
				menuHtml += `<li class="selItem" data-key="${menu}">
                                    <ul class="selItemCon">`;
				if (typeof (note[menu]) == 'string') {
					menuHtml += `<li><label class="itemKey">${(note[menu])}： </label> <label class="itemValue"></label></li>`;
				} else {
					for (let menuItem in note[menu]) {
						menuHtml += `<li><label class="itemKey">${menuItem}： </label> <label class="itemValue">${note[menu][menuItem]}</label></li>`;
					}
				}

				menuHtml += `</ul>
                                <div class="checkbox ${menu == 0 ? 'checked' : ''}" data-key="${menu}">
                                    <input type="checkbox" checked="checked">
                                </div>
                            </li>`;
			}
			menuHtml += `</ul><section class="btn-wrapper">
                                <button  id="submit" class="btn-default btn disabled" data-type="submit">
                                    <span>确&nbsp;&nbsp;&nbsp;&nbsp;定</span>
                                    <svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
                        <g fill="none" fill-rule="evenodd">
                            <g transform="translate(1 1)" stroke-width="3">
                                <circle stroke-opacity=".5" cx="18" cy="18" r="15"></circle>
                                <path d="M33 18c0-9.94-8.06-15-15-15" transform="rotate(156 18 18)">
                                    <animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="1s" repeatCount="indefinite"></animateTransform>
                                </path>
                            </g>
                        </g>
                    </svg>
                                </button>
                            </section>
                        </div>`;
			return {type: 'radio', html: menuHtml, code: 1};

		}


	}
	contentHtml += '</ul></div>';
	return {type: 'text', html: contentHtml, code: 1};

}
function uploadData(params) {
    return new Promise(function (resolve, reject) {
        let url = mongoUrl + ':11250/data';
        var options = {
            url: url,
            method: 'POST',
            json: true,
            body: params,
            headers: {
                'content-type': 'application/json'
            }
        };
        request(options, (e, r, b) => {
            if (e) {
                console.log(e);
                return reject('访问存储服务器出错');
            }
            if (b.msg == 'OK') {
                console.log()
                return resolve('查询成功');
            } else {
                console.log(b);
                return reject('存储数据失败');
            }
        });
    });

}


function upDateGjjStatus(params) {
	return new Promise((resolve,reject)=>{
		let sqlParams=[['status','taskId','callbackUrl','userId'],'taskId',params.taskId];
		QueryStatus(sqlParams).then(status=>{
			if(status.length===0||status.length===undefined){
				return reject(status);
			}
			if(status.length>0){
				let rawStatus=status[0].status;
				let rawTaskId=status[0].taskId;
				let rawCallbackUrl=status[0].callbackUrl;
                let rawUserId=status[0].userId;
				if (rawTaskId > params.taskId) {
                    console.warn("【DB upDateGjjStatus】更改状态失败 Req:"+JSON.stringify(params)+"Res:"+JSON.stringify(status[0]));
					return reject('try to mod taskId' + rawTaskId + 'status' + params.taskId);
				}
				if (rawStatus === params.status && rawTaskId === params.taskId) {
                    console.warn("【DB upDateGjjStatus】更改状态失败 Req:"+JSON.stringify(params)+"Res:"+JSON.stringify(status[0]));
					return reject('no change');
				}
				if (rawStatus === 'success') {
                    console.warn("【DB upDateGjjStatus】更改状态失败 Req:"+JSON.stringify(params)+"Res:"+JSON.stringify(status[0]));
					return reject('already Success');
				}
				let upObj={
					status:params.status,
					text2:params.taskId
				};
                if(params.hasOwnProperty('text3')){
                    upObj.text3=params.text3
                }
				let sqlParams=[upObj,'taskId',params.taskId];

				UpdateStatus(sqlParams).then(status=>{
                    console.log("【DB upDateGjjStatus】更改状态成功 Req:"+JSON.stringify(params)+"Res:"+JSON.stringify(status));
                    resolve({cbUrl:rawCallbackUrl,userId:rawUserId});
				}).catch(err=>{
                    console.error("【DB upDateGjjStatus】更改状态出错 Req:"+JSON.stringify(params)+"Res:"+JSON.stringify(err));
					reject(err);
				});
			}else{
                console.error("【DB upDateGjjStatus】status.length<0 Req:"+JSON.stringify(params)+"Res:"+JSON.stringify(status));
				reject(status);
			}

		}).catch(err=>{
            console.error("【DB upDateGjjStatus】QueryStatus Req:"+JSON.stringify(sqlParams)+"Res:"+JSON.stringify(err));
            reject(err);
		});
	});
}


function serverSideCall(callbackURL,orderSn,status,userId){
    let form = { order_id: orderSn, status: status,user_id:userId };
	if(callbackURL===''||callbackURL===undefined||callbackURL===null){
        console.log("【serverSideCall】无回调地址 Req:"+JSON.stringify(form));
		return;
	}
	let options = {
		url: callbackURL,
		method: 'POST',
		json: true,
		body: form,
		headers: {
			'content-type': 'application/json'
		}
	};
	request(options, function (e, r, b) {
		if (e) {
            console.error("【serverSideCall】通知失败 Req:"+JSON.stringify(options)+"Res:"+JSON.stringify(e));
		} else {
			console.log(b);
            console.log("【serverSideCall】通知成功 Req:"+JSON.stringify(options)+"Res:"+JSON.stringify(e));
		}
	});

}

setInterval(function () {
	let dateNow = new Date().getTime();
	console.log('[处理old 前 size： ]' + orderIdMap.size + ' loopMap:' + noWsMap.size);
	orderIdMap.forEach(function (value, key) {
		if (dateNow - value.addTime > 1000 * 60 * 30) {
			orderIdMap.delete(key);
		}
	});
	noWsMap.forEach(function (value, key) {
		if (dateNow - value.addTime > 1000 * 60 * 30) {
			noWsMap.delete(key);
		}
	});

	console.log('[处理old 后 size： ]' + orderIdMap.size + ' loopMap:' + noWsMap.size);
}, 1000 * 60 * 30);
module.exports = router;