package front

import (
	"encoding/json"
	"fmt"
	"mongodb"
	qu "qfw/util"
	"strings"
	"time"
	"util"
)

// DataMark 数据标注
func (f *Front) DataMark() {
	qu.Debug("------------------")
	defer qu.Catch()
	success := false
	msg := ""
	user := f.GetSession("user").(map[string]interface{})
	username := qu.ObjToString(user["s_login"]) //当前登录用户
	userid := qu.ObjToString(user["id"])        //当前登录用户标识
	obj := []map[string]interface{}{}
	infoId := f.GetString("s_infoid")
	userTaskId := f.GetString("s_usertaskid")
	qu.Debug("Task ID：", userTaskId, "	Data ID：", infoId)
	data := f.GetString("data")
	err := json.Unmarshal([]byte(data), &obj)
	if err != nil {
		qu.Debug("Json Unmarshal Error")
		f.ServeJson(map[string]interface{}{"success": success, "msg": "解析数据失败"})
		return
	}
	tagSet := map[string]interface{}{}    //被标注字段状态
	baseSet := map[string]interface{}{}   //要修改的字段信息
	baseUnset := map[string]interface{}{} //要删除的字段信息
	//isSaveMarked := false
	if len(obj) == 1 { //单独保存某个一级
		content, ok := obj[0]["content"].([]interface{})
		if !ok || len(content) == 0 {
			f.ServeJson(map[string]interface{}{"success": success, "msg": "解析数据失败"})
			return
		}
		title := qu.ObjToString(obj[0]["title"])
		istag, _ := obj[0]["checkAllTag"].(bool)
		status := qu.IntAll(obj[0]["status"])
		switch title {
		case "基本字段":
			MarkBase(content, tagSet, baseSet, baseUnset)
		case "时间地点":
			MarkTimePlace(content, tagSet, baseSet, baseUnset)
		case "标的信息":
			MarkPurchasinglist(content, tagSet, baseSet, baseUnset, istag, status)
		case "多包信息":
			MarkPackage(content, tagSet, baseSet, baseUnset, status)
		case "中标候选人信息":
			MarkWonderorder(content, tagSet, baseSet, baseUnset, status)
		case "其余信息":
			MarkOther(content, tagSet, baseSet, baseUnset)
		}
	} else {
		for j, val := range obj {
			content, ok := val["content"].([]interface{})
			status := qu.IntAll(val["status"])
			if !ok {
				qu.Debug("Content Error")
				continue
			}
			istag, _ := val["checkAllTag"].(bool)
			qu.Debug(istag)
			if j == 0 { //基本信息
				MarkBase(content, tagSet, baseSet, baseUnset)
			} else if j == 1 { //时间地点
				MarkTimePlace(content, tagSet, baseSet, baseUnset)
			} else if j == 2 { //标的物
				MarkPurchasinglist(content, tagSet, baseSet, baseUnset, istag, status)
			} else if j == 3 { //多包
				MarkPackage(content, tagSet, baseSet, baseUnset, status)
			} else if j == 4 { //候选人
				MarkWonderorder(content, tagSet, baseSet, baseUnset, status)
			} else { //其余信息
				MarkOther(content, tagSet, baseSet, baseUnset)
			}
		}
	}
	//
	userTask, _ := util.Mgo.FindById(util.TASKCOLLNAME, userTaskId, map[string]interface{}{"s_personid": 1, "s_personname": 1, "s_projectname": 1, "s_sourceinfo": 1})
	if userTask == nil || len(*userTask) == 0 {
		f.ServeJson(map[string]interface{}{"success": success, "msg": "查询用户任务失败"})
		return
	}
	sourceInfo := qu.ObjToString((*userTask)["s_sourceinfo"])                                                     //数据源表
	dataInfo, _ := util.Mgo.FindById(sourceInfo, infoId, map[string]interface{}{"v_baseinfo": 1, "v_taginfo": 1}) //查询标注保存前的原始信息
	tagInfo, _ := (*dataInfo)["v_taginfo"].(map[string]interface{})
	baseInfo, _ := (*dataInfo)["v_baseinfo"].(map[string]interface{})
	if tagInfo != nil && len(tagInfo) > 0 {
		for field, tmpStatus := range tagSet { //比对本次标注信息和历史标注信息
			status := qu.IntAll(tmpStatus)            //此次被标注字段的状态
			markedStatus := qu.IntAll(tagInfo[field]) //历史标注状态
			if status == 1 && markedStatus != 0 {     //此次标注结果为正确，且有历史标注记录，不做修改
				qu.Debug("已标注字段field---", field)
				delete(tagSet, field)
				delete(baseSet, field)
				//continue
			}
			//else {
			//	qu.Debug("未标注字段field---", field, status)
			//}
		}
	}
	//
	allTagFields := map[string]interface{}{} //记录此此标注所有标注信息，用于日志记录
	for k, _ := range tagSet {
		allTagFields[k] = true
	}
	for k, v := range baseSet {
		allTagFields[k] = v
	}
	for k, _ := range baseUnset {
		allTagFields[k] = nil
	}
	qu.Debug("allTagFields===", allTagFields)
	qu.Debug("tagSet===", tagSet)
	if len(tagSet) > 0 || baseInfo["purchasinglist_alltag"] != nil { //purchasinglist_alltag特殊处理
		//1、更新数据源信息
		setResult := map[string]interface{}{ //更新字段集
			"i_updatetime": time.Now().Unix(),
			"i_ckdata":     2,
			"b_istag":      true,
		}
		for field, val := range tagSet { //更新标注字段
			setResult["v_taginfo."+field] = val
		}
		for field, val := range baseSet { //更新基本字段
			setResult["v_baseinfo."+field] = val
		}
		baseUnsetResult := map[string]interface{}{} //删除字段集
		for field, _ := range baseUnset {           //删除基本字段
			baseUnsetResult["v_baseinfo."+field] = ""
		}
		set := map[string]interface{}{
			"$set": setResult,
		}
		if len(baseUnsetResult) > 0 {
			set["$unset"] = baseUnsetResult
		}
		qu.Debug("set---", set)
		success = util.Mgo.UpdateById(sourceInfo, infoId, set)
		//2、更新marked表
		tmp, _ := util.Mgo.FindById(sourceInfo, infoId, map[string]interface{}{"v_baseinfo": 1, "v_taginfo": 1, "i_ckdata": 1})
		qu.Debug("infoId:", infoId)
		delete((*tmp), "_id")
		(*tmp)["updatetime"] = time.Now().Unix()
		b := util.Mgo.Update(util.AllToColl, map[string]interface{}{"_id": mongodb.StringTOBsonId(infoId)}, map[string]interface{}{"$set": tmp}, true, false)
		qu.Debug("Update Marked：", b)
	}
	/*
		} else {
			表示页面标注时未做修改标注
		}
	*/
	//3、修改任务状态
	b := util.Mgo.Update(util.TASKCOLLNAME, map[string]interface{}{"_id": (*userTask)["_id"], "s_status": "未开始"}, map[string]interface{}{
		"$set": map[string]interface{}{
			"i_starttime":    time.Now().Unix(),
			"i_updatetime":   time.Now().Unix(),
			"s_updateperson": username,
			"s_status":       "进行中",
		},
	}, false, false)
	qu.Debug("Update UserTask：", b)
	//4、保存标注日志
	b = SaveLog(infoId, userTaskId, username, userid, "标注", baseInfo, allTagFields, *userTask)
	qu.Debug("Save Log：", b)

	f.ServeJson(map[string]interface{}{"success": success, "msg": msg})
}

func MarkBase(content []interface{}, tagSet, baseSet, baseUnset map[string]interface{}) {
	defer qu.Catch()
	info, _ := content[0].(map[string]interface{})
	if uInputs, ok := info["uInput"].([]interface{}); ok {
		for _, tmp := range uInputs {
			if tmpMap, ok := tmp.(map[string]interface{}); ok {
				if status := qu.IntAll(tmpMap["status"]); status != -1 {
					key := qu.ObjToString(tmpMap["key"]) //字段
					if key == "" {
						continue
					}
					if status == 2 { //新增、修改、删除
						input := tmpMap["input"]                                                                                               //值
						if key == "bidamounttype" || key == "subtype" || key == "attach_discern" || key == "attach_ext" || key == "isrepeat" { //附件识别、抽取select
							input = tmpMap["select"]
						}
						if input == "" { //删除原字段
							baseUnset[key] = ""
						} else { //修改原字段
							if key == "budget" || key == "bidamount" || key == "biddiscount" {
								input = qu.Float64All(input)
								//input, _ = strconv.ParseFloat(qu.ObjToString(input), 32)
							}
							if key == "subtype" {
								if topsubtype := strings.Split(qu.ObjToString(input), "-"); len(topsubtype) == 2 {
									baseSet["toptype"] = topsubtype[0]
									baseSet[key] = topsubtype[1]
								}
							} else {
								baseSet[key] = input
							}
						}
					}
					tagSet[key] = status //记录被标注状态
				}
			}
		}
	}
	qu.Debug("tagSet===", tagSet)
	qu.Debug("baseSet===", baseSet)
	qu.Debug("baseUnset===", baseUnset)
}

func MarkTimePlace(content []interface{}, tagSet, baseSet, baseUnset map[string]interface{}) {
	info, _ := content[0].(map[string]interface{})
	if uInputs, ok := info["uInput"].([]interface{}); ok {
		for _, tmp := range uInputs {
			if tmpMap, ok := tmp.(map[string]interface{}); ok {
				if status := qu.IntAll(tmpMap["status"]); status != -1 {
					key := qu.ObjToString(tmpMap["key"]) //字段
					if key == "" {
						continue
					}
					if status == 2 { //新增、修改、删除
						input := tmpMap["input"] //值
						if input == "" {
							baseUnset[key] = ""
						} else {
							if key == "bidopentime" || key == "publishtime" || key == "bidendtime" || key == "project_startdate" || key == "project_completedate" {
								inputTmp, _ := time.ParseInLocation(qu.Date_Full_Layout, input.(string), time.Local)
								input = inputTmp.Unix()
							} else if key == "project_duration" {
								input = qu.IntAll(input)
							}
							baseSet[key] = input
						}
					}
					tagSet[key] = status
				}
			}
		}
	}
	qu.Debug("tagSet===", tagSet)
	qu.Debug("baseSet===", baseSet)
	qu.Debug("baseUnset===", baseUnset)
}

func MarkPurchasinglist(content []interface{}, tagSet, baseSet, baseUnset map[string]interface{}, istag bool, status int) {
	if status == -1 {
		return
	}
	baseSet["purchasinglist_alltag"] = istag //标的信息是否标注完全
	purchasinglist := []interface{}{}
	delpclson := 0
	for _, con := range content {
		info, _ := con.(map[string]interface{})
		isNew, _ := info["isnew"].(bool) //是否是新增子包
		pclSonStatus := qu.IntAll(info["status"])
		if pclSonStatus == 4 {
			delpclson++
		}
		if uInputs, ok := info["uInput"].([]interface{}); ok {
			result := map[string]interface{}{
				"isnew": isNew,
			}
			for _, tmp := range uInputs {
				if tmpMap, ok := tmp.(map[string]interface{}); ok {
					key := qu.ObjToString(tmpMap["key"]) //字段
					input := tmpMap["input"]             //值
					//status := qu.IntAll(tmpMap["status"])
					isNull := false
					if input == "" { //判断前台页面是否填值，无值不进行字段存储
						isNull = true
					} else if key == "number" || key == "unitprice" || key == "totalprice" {
						input = qu.Float64All(input)
					}
					if !isNull { //避免数字类型的字段在没有填写值的情况默认给0
						result[key] = input
					}
				}
			}
			if pclSonStatus != -1 { //没有标注的标的信息不打标记
				result["purchasinglist_son"] = pclSonStatus
			}
			if len(result) > 0 && pclSonStatus != 4 {
				purchasinglist = append(purchasinglist, result)
			}
		}
	}
	qu.Debug("purchasinglist", len(purchasinglist))
	if len(purchasinglist)+delpclson == len(content) {
		if len(purchasinglist) > 0 {
			baseSet["purchasinglist"] = purchasinglist
		} else if len(content) > 0 && delpclson == len(content) { //只有删除
			baseUnset["purchasinglist"] = ""
		}
		tagSet["purchasinglist"] = status
	} else {
		qu.Debug("Purchasinglist Tag Error")
	}
	qu.Debug("tagSet===", tagSet)
	qu.Debug("baseSet===", baseSet)
	qu.Debug("baseUnset===", baseUnset)
}

func MarkPackage(content []interface{}, tagSet, baseSet, baseUnset map[string]interface{}, status int) {
	if status == -1 {
		return
	}
	pkgs := map[string]interface{}{}
	newNum := 1
	delpkgson := 0 //记录子包删除个数
	for _, con := range content {
		info, _ := con.(map[string]interface{})
		pkgSonStatus := qu.IntAll(info["status"])
		if pkgSonStatus == 4 {
			delpkgson++
		}
		num := fmt.Sprint(info["num"])   //包号
		isNew, _ := info["isnew"].(bool) //是否是新增子包
		if isNew {                       //新增子包新建包名
			num = "new" + fmt.Sprint(newNum)
			newNum++
		}
		if uInputs, ok := info["uInput"].([]interface{}); ok {
			result := map[string]interface{}{
				"isnew": isNew,
			}
			winnerArr := []interface{}{}
			bidamountArr := []interface{}{}
			for _, tmp := range uInputs {
				if tmpMap, ok := tmp.(map[string]interface{}); ok {
					key := qu.ObjToString(tmpMap["key"]) //字段
					input := tmpMap["input"]             //值
					isNull := false                      //记录字段是否有值
					if key == "bidamounttype" {
						input = tmpMap["select"]
					} else {
						if input == "" { //判断前台页面是否填值，无值不进行字段存储
							isNull = true
						} else if key == "bidamount" || key == "budget" {
							input = qu.Float64All(input)
							//input, _ = strconv.ParseFloat(qu.ObjToString(input), 32)
						}
					}
					if key == "winner" {
						if isNull {
							winnerArr = append(winnerArr, nil)
						} else {
							winnerArr = append(winnerArr, input)
						}
						continue
					} else if key == "bidamount" {
						if isNull {
							bidamountArr = append(bidamountArr, nil)
						} else {
							bidamountArr = append(bidamountArr, input)
						}
						continue
					}

					if !isNull { //避免数字类型的字段在没有填写值的情况默认给0
						result[key] = input
					}
				}
			}
			winner_all := []interface{}{}
			if len(winnerArr) == len(bidamountArr) {
				for i, w := range winnerArr {
					b := bidamountArr[i]
					wbMap := map[string]interface{}{}
					if w != nil {
						wbMap["winner"] = w
					}
					if b != nil {
						wbMap["bidamount"] = b
					}
					if len(wbMap) > 0 {
						winner_all = append(winner_all, wbMap)
					}
				}
			}
			if len(winner_all) > 0 {
				result["winner_all"] = winner_all
			}
			result["package_son"] = pkgSonStatus

			if len(result) > 0 && pkgSonStatus != 4 { //要删除的子包不再保存
				pkgs[num] = result
			}
		}
	}
	qu.Debug("pkgs", len(pkgs))
	if len(pkgs)+delpkgson == len(content) {
		if len(pkgs) > 0 {
			baseSet["package"] = pkgs
		} else if len(content) > 0 && delpkgson == len(content) { //只有删除
			baseUnset["package"] = ""
		}
		tagSet["package"] = status
	} else {
		qu.Debug("Package Tag Error")
	}
	qu.Debug("tagSet===", tagSet)
	qu.Debug("baseSet===", baseSet)
	qu.Debug("baseUnset===", baseUnset)
}

func MarkWonderorder(content []interface{}, tagSet, baseSet, baseUnset map[string]interface{}, status int) {
	if status == -1 {
		return
	}
	winnerorder := []interface{}{}
	delwodrson := 0
	for _, con := range content {
		info, _ := con.(map[string]interface{})
		isNew, _ := info["isnew"].(bool) //是否是新增子包
		wodrSonStatus := qu.IntAll(info["status"])
		if wodrSonStatus == 4 {
			delwodrson++
		}
		if uInputs, ok := info["uInput"].([]interface{}); ok {
			result := map[string]interface{}{
				"isnew": isNew,
			}
			for _, tmp := range uInputs {
				if tmpMap, ok := tmp.(map[string]interface{}); ok {
					key := qu.ObjToString(tmpMap["key"]) //字段
					input := tmpMap["input"]             //值
					isNull := false
					if input == "" { //判断前台页面是否填值，无值不进行字段存储
						isNull = true
					} else if key == "price" {
						input = qu.Float64All(input)
						//input, _ = strconv.ParseFloat(qu.ObjToString(input), 32)
					}
					if !isNull { //避免数字类型的字段在没有填写值的情况默认给0
						result[key] = input
					}
					result["winnerorder_son"] = wodrSonStatus
				}
			}
			if len(result) > 0 && wodrSonStatus != 4 {
				winnerorder = append(winnerorder, result)
			}
		}
	}
	qu.Debug("winnerorder", len(winnerorder))
	if len(winnerorder)+delwodrson == len(content) {
		if len(winnerorder) > 0 {
			baseSet["winnerorder"] = winnerorder
		} else if len(content) > 0 && delwodrson == len(content) { //只有删除
			baseUnset["winnerorder"] = ""
		}
		tagSet["winnerorder"] = status
	} else {
		qu.Debug("Winnerorder Tag Error")
	}
	qu.Debug("tagSet===", tagSet)
	qu.Debug("baseSet===", baseSet)
	qu.Debug("baseUnset===", baseUnset)
}

func MarkOther(content []interface{}, tagSet, baseSet, baseUnset map[string]interface{}) {
	info, _ := content[0].(map[string]interface{})
	if uInputs, ok := info["uInput"].([]interface{}); ok {
		for _, tmp := range uInputs {
			if tmpMap, ok := tmp.(map[string]interface{}); ok {
				if status := qu.IntAll(tmpMap["status"]); status != -1 {
					key := qu.ObjToString(tmpMap["key"]) //字段
					if key == "" {
						continue
					}
					if status == 2 { //新增、修改、删除
						input := tmpMap["input"] //值
						if key == "isppp" || key == "contract_guarantee" || key == "bid_guarantee" {
							input = tmpMap["select"]
						}
						if input == "" {
							baseUnset[key] = ""
						} else {
							if key == "signaturedate" {
								inputTmp, _ := time.ParseInLocation(qu.Date_Full_Layout, input.(string), time.Local)
								input = inputTmp.Unix()
							} else if key == "bid_bond" || key == "contract_bond" || key == "supervisorrate" || key == "agencyrate" || key == "docamount" || key == "agencyfee" {
								input = qu.Float64All(input)
								//input, _ = strconv.ParseFloat(qu.ObjToString(input), 32)
							}
							baseSet[key] = input
						}
					}
					tagSet[key] = status
				}
			}
		}
	}
	qu.Debug("tagSet===", tagSet)
	qu.Debug("baseSet===", baseSet)
	qu.Debug("baseUnset===", baseUnset)
}

// SaveLog 标注日志保存
func SaveLog(s_infoid, s_usertaskid, username, userid, s_stype string, baseInfo, allTagFields, userTask map[string]interface{}) (success bool) {
	defer qu.Debug()
	v_before := map[string]interface{}{}
	for f, v := range allTagFields {
		if _, ok := v.(bool); ok && f != "purchasinglist_alltag" { //表示此次标注status=1的字段
			allTagFields[f] = baseInfo[f]
		}
		v_before[f] = baseInfo[f]
	}
	save := map[string]interface{}{
		"s_projectname": qu.ObjToString(userTask["s_projectname"]),
		"s_taskid":      s_usertaskid,
		"s_infoid":      s_infoid,
		"s_stype":       s_stype,
		"s_userid":      userid,
		"s_username":    username,
		"i_createtime":  time.Now().Unix(),
		"v_before":      v_before,
		"v_after":       allTagFields,
	}
	id := util.Mgo.Save(util.LOGCOLLNAME, save)
	if id != "" {
		success = true
	}
	return
}
