package main

import (
	"github.com/go-xweb/log"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"math"
	qu "qfw/util"
	"reflect"
	"sort"
	"strings"
)

func (p *ProjectTask) modifyUpdate(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) {
	backupPro(tmpPro)
	infoList := []interface{}(tmpPro["list"].(primitive.A))
	infoMap := infoList[index].(map[string]interface{})
	infoList[index] = updateValue(infoMap, modifyMap)
	infofiled := InfoField{
		Budget:       info.Budget,
		Bidamount:    info.Bidamount,
		ContractCode: info.ContractCode,
		ProjectName:  info.ProjectName,
		ProjectCode:  info.ProjectCode,
		Bidstatus:    info.SubType,
	}
	mapTmp, _ := tmpPro["infofiled"].(map[string]interface{})
	mapTmp[info.Id] = StructToMap(infofiled)
	set := map[string]interface{}{
		"$set": tmpPro,
	}
	_ = MongoTool.UpdateById(ProjectColl, pInfoId, set)
}

func (p *ProjectTask) mergeAndModify(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) {
	p.AllIdsMapLock.Lock()
	currentPro := p.AllIdsMap[pInfoId]
	p.AllIdsMapLock.Unlock()
	merge, pId, i, comStr, mergePro := p.updateMerge(index, info, pInfoId, tmp, tmpPro)
	//招标信息在list中第1个
	if index == 0 {
		log.Println("第1条合并", "------1------")
		//快照
		backupPro(tmpPro)
		p.AllIdsMapLock.Lock()
		delete(p.AllIdsMap, pInfoId)
		p.AllIdsMapLock.Unlock()
		count := MongoTool.Delete(ProjectColl, pInfoId)
		log.Println(count)
		for _, infoId := range currentPro.P.Ids{
			if infoId == info.Id {
				continue
			}
			tmp1 := MongoTool.FindById(ExtractColl, infoId)
			p.fillInPlace(tmp)
			info1 := ParseInfo(tmp1)
			p.CommonMerge(tmp1, info1)
		}
	}else {
		log.Println("第n条合并", "------n------")
		//快照    招标信息所在的项目
		backupPro(tmpPro)
		if merge {
			//跟原项目list第0条信息作对比，可以合并
			if pId == pInfoId {
				//合并到当前项目
				mergeProject(p, currentPro.P, info, tmpPro, tmp)
				p.AllIdsMapLock.Lock()
				p.AllIdsMap[currentPro.P.Id.Hex()].P = currentPro.P
				p.AllIdsMapLock.Unlock()
				infoList := []interface{}(tmpPro["list"].(primitive.A))
				infoMap := infoList[index].(map[string]interface{})
				infoList[index] = updateValue(infoMap, modifyMap)
				infofiled := InfoField{
					Budget:       info.Budget,
					Bidamount:    info.Bidamount,
					ContractCode: info.ContractCode,
					ProjectName:  info.ProjectName,
					ProjectCode:  info.ProjectCode,
					Bidstatus:    info.SubType,
				}
				mapTmp, _ := tmpPro["infofiled"].(map[string]interface{})
				mapTmp[info.Id] = StructToMap(infofiled)
				set := map[string]interface{}{
					"$set": tmpPro,
				}
				MongoTool.UpdateById(ProjectColl, pInfoId, set)
			}else {
				//合并到的其它项目里边
				//更新其它的项目
				pro := MongoTool.FindById(ProjectColl, mergePro.Id.Hex())
				backupPro(pro)
				choose, ex := p.CompareStatus(mergePro, info)
				if !choose {
					p.UpdateProject(tmp, info, mergePro, i, comStr, ex)
				}else {
					id, p1 := p.NewProject(tmp, info)
					p.AllIdsMapLock.Lock()
					p.AllIdsMap[id] = &ID{Id: id, P: p1}
					p.AllIdsMapLock.Unlock()
				}
				//内部合并
				p.innerMerge(currentPro.P, info, tmp, tmpPro)
			}
		}else {
			//合并到新建的项目里边，原有项目内部合并
			p.innerMerge(currentPro.P, info, tmp, tmpPro)
		}
	}
}

func (p *ProjectTask) updateMerge(index int, info *Info, pInfoId string, tmp map[string]interface{}, tmpPro map[string]interface{}) (bool, string, int, string, *ProjectInfo) {
	bpn, bpc, bptc, bpb, pids, _, IDArr := p.getCompareIds(info.ProjectName, info.ProjectCode, info.PTC, info.Buyer)
	defer p.wg.Done()

	for _, m := range pids {
		defer m.Lock.Unlock()
	}
	for _, id := range IDArr {
		defer id.Lock.Unlock()
	}

	bFindProject := false
	findPid := ""
	//获取完id，进行计算
	//定义两组
	comRes1 := []*ProjectInfo{} //优先级最高的对比结果数组
	comRes2 := []*ProjectInfo{} //优化级其次
	comRes3 := []*ProjectInfo{}
	for _, v := range IDArr {
		if index == 0 && pInfoId == v.P.Id.Hex() {
			//招标条目信息在原项目中是第0条时，忽略
			continue
		}
		comStr := ""
		compareProject := v.P
		compareProject.score = 0
		diffTime := int64(math.Abs(float64(info.Publishtime - compareProject.LastTime)))
		if diffTime <= p.validTime {

			//代理机构完全不相同，直接新建项目
			if CheckContain(compareProject.Agency, info.Agency) == 3 {
				continue
			}

			//地区(省、市、区)不同，直接新建项目
			if ComparePlace(compareProject, info) {
				continue
			}

			info.PNBH = 0
			info.PCBH = 0
			info.PTCBH = 0
			compareStr, score := comparePNC(info, compareProject)
			resVal, pjVal := Select(compareStr, info, compareProject)
			if resVal > 0 {
				compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount, score2 := p.compareBCTABB(info, compareProject, diffTime, score)

				//项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构
				comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount
				compareProject.comStr = comStr
				compareProject.pjVal = pjVal
				compareProject.resVal = resVal
				eqV := compareResult(resVal, pjVal, score2, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount)
				if eqV == 1 {
					comRes1 = append(comRes1, compareProject)
				} else if eqV == 2 {
					comRes2 = append(comRes2, compareProject)
				} else if eqV == 3 {
					comRes3 = append(comRes3, compareProject)
				}
			}
		}
	}
	//--------------------------------对比完成-----------------------
	k := -1
	comStr := ""
	mergePro := &ProjectInfo{}
	for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} {
		if len(resN) > 0 {
			if len(resN) > 1 {
				sort.Slice(resN, func(i, j int) bool {
					return resN[i].score > resN[j].score
				})
			}

			ex := 0
			resArr := []*ProjectInfo{}
			for _, res := range resN{
				choose, e := p.CompareStatus(resN[0], info)
				if !choose {
					ex = e
					resArr = append(resArr, res)
				}
			}
			if len(resArr) > 0 {
				bFindProject = true
				findPid = resArr[0].Id.Hex()
				for k2, bv := range []int{bpn, bpc, bptc, bpb} {
					if bv > -1 {
						pids[bv].Arr = append(pids[bv].Arr, findPid)
						if k2 == 0 {
							if resArr[0].ProjectName == "" {
								resArr[0].ProjectName = info.ProjectName
							} else {
								if resArr[0].MPN == nil {
									resArr[0].MPN = []string{info.ProjectName}
								} else {
									resArr[0].MPN = append(resArr[0].MPN, info.ProjectName)
								}
							}

						} else if k2 < 3 {
							if resArr[0].ProjectCode == "" {
								resArr[0].ProjectCode = qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)
							} else {
								if resArr[0].MPC == nil {
									resArr[0].MPC = []string{qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)}
								} else {
									resArr[0].MPC = append(resArr[0].MPC, qu.If(k2 == 1, info.ProjectCode, info.PTC).(string))
								}
							}

						} else {
							if resArr[0].Buyer == "" {
								resArr[0].Buyer = info.Buyer
							}
						}
					}
				}
				if index != 0 {
					//招标条目信息在原项目中是第非0条时，返回对比结果
					k = kv+1
					comStr = resArr[0].comStr
					mergePro = resArr[0]
					bFindProject = false
					findPid = ""
				}else {
					mergePro = resArr[0]
					//如果有合并，合并之前备份(快照)
					backupPro(tmpPro)
					p.UpdateProject(tmp, info, resArr[0], kv+1, resArr[0].comStr, ex)
				}
			}else {
				bFindProject = false
				findPid = ""
			}
			break
		}
	}

	if !bFindProject {
		id, p1 := p.NewProject(tmp, info)
		p.AllIdsMapLock.Lock()
		p.AllIdsMap[id] = &ID{Id: id, P: p1}
		p.AllIdsMapLock.Unlock()
		for _, m := range pids {
			m.Arr = append(m.Arr, id)
		}
	}
	return bFindProject, findPid, k, comStr, mergePro
}

//内部合并
func (p *ProjectTask) innerMerge(pInfo *ProjectInfo, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}) {
	infoList := []interface{}(tmpPro["list"].(primitive.A))
	for _, info1 := range infoList{
		info2 := info1.(map[string]interface{})
		if info2["infoid"] == info.Id {
			deleteSlice1(infoList, info1)
			continue
		}
		mergeProject(p, pInfo, info, tmpPro, tmp)
	}
	mapTmp, _ := tmpPro["infofiled"].(map[string]interface{})
	delete(mapTmp, info.Id)
	set := map[string]interface{}{
		"$set": tmpPro,
	}
	MongoTool.UpdateById(ProjectColl, pInfo.Id.Hex(), set)
}

//合并字段到project
func mergeProject(p *ProjectTask, pInfo *ProjectInfo, thisinfo *Info, set map[string]interface{}, tmp map[string]interface{}) map[string]interface{} {
	pInfo.LastTime = thisinfo.Publishtime
	set["lasttime"] = thisinfo.Publishtime
	if thisinfo.TopType == "招标" {
		if thisinfo.SubType != "变更" && thisinfo.SubType != "其它" {
			set["zbtime"] = thisinfo.Publishtime
		}
		if pInfo.Jgtime > 0 {
			pInfo.Jgtime = int64(0)
			set["jgtime"] = int64(0)
		}
	}else if thisinfo.TopType == "结果" {
		pInfo.Jgtime = thisinfo.Publishtime
		set["jgtime"] = thisinfo.Publishtime
	} else if thisinfo.SubType == "合同" {
		if pInfo.Jgtime <= 0 {
			set["jgtime"] = thisinfo.Publishtime
		}
	}

	if thisinfo.Bidopentime > pInfo.Bidopentime {
		pInfo.Bidopentime = thisinfo.Bidopentime
		set["bidopentime"] = pInfo.Bidopentime
	}


	bt := thisinfo.TopType
	bs := thisinfo.SubType
	p.mapBidLock.Lock()
	set["bidtype"] = bidtype[bs]
	if bt == "招标" {
		//招标状态，更新projectscope
		if thisinfo.ProjectScope != "" {
			set["projectscope"] = thisinfo.ProjectScope
		}
		set["bidstatus"] = bt
	}else {
		if bidstatus[bs] != "" {
			set["bidstatus"] = thisinfo.SubType
		} else if thisinfo.Infoformat == 2 {
			set["bidstatus"] = "拟建"
		} else {
			set["bidstatus"] = "其它"
		}
	}
	p.mapBidLock.Unlock()

	//3\4\5--省、市、县
	if thisinfo.Area != "全国" {
		//xt := true
		if pInfo.Area == "全国" {
			pInfo.Area = thisinfo.Area
			set["area"] = thisinfo.Area
		} else if pInfo.Area != thisinfo.Area {
			//xt = false
		}
		if pInfo.City == "" && thisinfo.City != "" {
			pInfo.City = thisinfo.City
			set["city"] = thisinfo.City
		} else if pInfo.City != thisinfo.City {
			//xt = false
		}
		if thisinfo.District != "" && pInfo.District == "" {
			pInfo.District = thisinfo.District
			set["district"] = thisinfo.District
		}
	}
	//6--项目名称
	if (thisinfo.ProjectName != "" && pInfo.ProjectName == "") || (len([]rune(pInfo.ProjectName)) < 6 && thisinfo.LenPN > 6) {
		pInfo.ProjectName = thisinfo.ProjectName
		set["projectname"] = thisinfo.ProjectName
	}
	//7--项目编号
	if (pInfo.ProjectCode == "" && thisinfo.ProjectCode != "") || (len([]rune(pInfo.ProjectCode)) < 6 && len([]rune(thisinfo.ProjectCode)) > 6) {
		pInfo.ProjectCode = thisinfo.ProjectCode
		set["projectcode"] = thisinfo.ProjectCode
	}
	//7--采购单位
	if (pInfo.Buyer == "" && thisinfo.Buyer != "") || (len([]rune(pInfo.Buyer)) < 5 && len([]rune(thisinfo.Buyer)) > 5) {
		pInfo.Buyer = thisinfo.Buyer
		set["buyer"] = thisinfo.Buyer

		pInfo.Buyerclass = thisinfo.Buyerclass
		set["buyerclass"] = thisinfo.Buyerclass
	}
	if pInfo.Buyer == "" {
		set["buyerclass"] = ""
	}

	if thisinfo.ContractCode != "" {
		set["contractcode"] = pInfo.ContractCode + ","+thisinfo.ContractCode
	}

	//8--代理机构
	if (pInfo.Agency == "" && thisinfo.Agency != "") || (len([]rune(pInfo.Agency)) < 5 && len([]rune(thisinfo.Agency)) > 5) {
		pInfo.Agency = thisinfo.Agency
		set["agency"] = thisinfo.Agency
	}
	//9--采购单位联系人
	if thisinfo.Buyerperson != "" && strings.Index(pInfo.Buyerperson, thisinfo.Buyerperson) < 0 {
		pInfo.Buyerperson = thisinfo.Buyerperson
		set["buyerperson"] = pInfo.Buyerperson
	}
	//10--采购单位電話
	if thisinfo.Buyertel != "" && strings.Index(pInfo.Buyertel, thisinfo.Buyertel) < 0 {
		pInfo.Buyertel = thisinfo.Buyertel
		set["buyertel"] = pInfo.Buyertel
	}

	if thisinfo.Bidopentime > pInfo.Bidopentime {
		pInfo.Bidopentime = thisinfo.Bidopentime
		set["bidopentime"] = pInfo.Bidopentime
	}

	//废标、流标   处理时间
	if thisinfo.SubType == "流标" || thisinfo.SubType == "废标" {
		pInfo.FirstTime = thisinfo.Publishtime
		pInfo.Bidopentime = int64(0)
		pInfo.LastTime = thisinfo.Publishtime

		set["firsttime"] = thisinfo.Publishtime
		set["zbtime"] = int64(0)
		set["publishtime"] = thisinfo.Publishtime
		set["bidopentime"] = int64(0)
	}

	if len(thisinfo.Topscopeclass) > 0 {
		sort.Strings(pInfo.Topscopeclass)
		for _, k := range thisinfo.Topscopeclass {
			if BinarySearch(pInfo.Topscopeclass, k) == -1 {
				pInfo.Topscopeclass = append(pInfo.Topscopeclass, k)
				sort.Strings(pInfo.Topscopeclass)
			}
		}
		set["topscopeclass"] = pInfo.Topscopeclass
	}

	if len(thisinfo.Subscopeclass) > 0 {
		sort.Strings(pInfo.Subscopeclass)
		for _, k := range thisinfo.Subscopeclass {
			if BinarySearch(pInfo.Subscopeclass, k) == -1 {
				pInfo.Subscopeclass = append(pInfo.Subscopeclass, k)
				sort.Strings(pInfo.Subscopeclass)
			}
		}
		set["subscopeclass"] = pInfo.Subscopeclass
		set["s_subscopeclass"] = strings.Join(pInfo.Subscopeclass, ",")
	}
	//winner
	if len(thisinfo.Winners) > 0 {
		sort.Strings(pInfo.Winners)
		for _, k := range thisinfo.Winners {
			if BinarySearch(pInfo.Winners, k) == -1 {
				pInfo.Winners = append(pInfo.Winners, k)
				sort.Strings(pInfo.Winners)
			}
		}
		set["s_winner"] = strings.Join(pInfo.Winners, ",")
	}

	if thisinfo.HasPackage {
		pkg := PackageFormat(thisinfo, pInfo)
		set["multipackage"] = 1
		pInfo.Package = pkg
	}else {
		set["multipackage"] = 0
	}
	//处理多包后，计算预算金额、中标金额
	CountAmount(pInfo, thisinfo, tmp)
	set["budget"] = pInfo.Budget
	set["bidamount"] = pInfo.Bidamount


	set["mpn"] = pInfo.MPN
	set["mpc"] = pInfo.MPC
	set["pici"] = p.pici

	return set
}

func deleteSlice1(arr []interface{}, v interface{}) []interface{} {
	for k, v1 := range arr {
		if reflect.DeepEqual(v1, v) {
			return append(arr[:k], arr[k+1:]...)
		}
	}
	return arr
}

func updateValue(info map[string]interface{}, tmp map[string]interface{}) map[string]interface{} {
	for k := range info{
		for k1 := range tmp {
			if k == k1 && info[k] != tmp[k1] {
				info[k] = tmp[k]
				break
			}
		}
	}
	return info
}

//备份(快照)
func backupPro(tmp map[string]interface{}) {
	tmp1 := make(map[string]interface{})
	for k, v := range tmp{
		tmp1[k] = v
	}
	if Sysconfig["backupFlag"].(bool) {
		tmp1["sourceprojectid"] = tmp1["_id"]
		delete(tmp1, "_id")
		MongoTool.Save(BackupColl, tmp1)
	}
}