package mysql

import (
	MC "app.yhyue.com/moapp/jybase/common"
	"app.yhyue.com/moapp/jybase/date"
	"app.yhyue.com/moapp/jybase/encrypt"
	"database/sql"
	"encoding/json"
	"fmt"
	IC "jyBXCore/rpc/init"
	"jyBXCore/rpc/model/es"
	"jyBXCore/rpc/type/bxcore"
	"log"
	"strconv"
	"strings"
	"time"
)

// 投标状态更新内容
type PartStatusContent struct {
	BidStage      []string `json:"bidStage"`      //投标项目阶段
	BidType       int64    `json:"bidType"`       //投标类型1:直接投标；2：渠道投标
	ChannelName   string   `json:"channelName"`   //渠道名称
	ChannelPerson string   `json:"channelPerson"` //联系人
	ChannelPhone  string   `json:"channelPhone"`  //联系电话
	IsWin         int64    `json:"isWin"`         //渠道是否中标
	Winner        string   `json:"winner"`        //中标单位
}

// 参标
type RecordsContent struct {
	After       PartStatusContent `json:"after"`       //更新前
	Before      PartStatusContent `json:"before"`      //更新后
	ChangeField []string          `json:"changeField"` //更新字段
	Content     string            `json:"content"`     //更新内容
}

var (
	PartTable                  = "participate"
	ParticipateBidRecordsTable = "participate_bid_records"
	ParticipateUserTable       = "participate_user" // 参标用户表
	EntnicheUserTable          = "entniche_user"    // 企业用户表
)

// 划转参标信息
func TransferParticipateInfo(projectId string, in *bxcore.ParticipateActionReq) error {
	defer MC.Catch()
	//保存或更新新跟踪人
	if !IC.BaseMysql.ExecTx("划转参标信息", func(tx *sql.Tx) bool {
		var (
			b1                                             = true
			b2, b3                                         bool
			now                                            = time.Now()
			content                                        = "从%s名下划转给%s%s"
			lastNotes                                      = ",保留原参标人"
			fromEntUserNames, toEntUserNames, toEntUserIds []string
			ids                                            []int
		)
		partInfo := IC.BaseMysql.SelectBySqlByTx(tx, "SELECT id,position_id FROM "+ParticipateUserTable+" WHERE  project_id = ?  AND ent_id = ? AND state > -1", projectId, in.EntId)
		if partInfo == nil || len(*partInfo) == 0 {
			log.Println("当前项目不满足划转条件")
			return false
		} else {
			for _, v := range *partInfo {
				ids = append(ids, MC.IntAll(v["id"]))
				positionId := MC.Int64All(v["position_id"])
				userInfo := IC.Middleground.UserCenter.IdentityByPositionId(positionId)
				if userInfo.EntUserName != "" {
					fromEntUserNames = append(fromEntUserNames, userInfo.EntUserName)
				}
			}
		}
		if len(fromEntUserNames) == 0 {
			log.Println("原参标人信息查询有误")
			return false
		}
		//是否保留原参标人
		if !in.IsRetain {
			lastNotes = ""
			//不保留 原参标人，获取把原参标人信息
			//当前项目有参标人 更新参标人状态
			b1 = IC.BaseMysql.UpdateByTx(tx, ParticipateUserTable, map[string]interface{}{
				"ent_id":     in.EntId,
				"project_id": projectId,
			}, map[string]interface{}{
				"state":       -1,
				"mark":        -2, //0：参标；1：被划入；-1：终止参标；-2：被划走
				"update_date": date.FormatDate(&now, date.Date_Full_Layout),
			})
		}
		//移动端 划转对象是多选
		//划转对象entuserid 解密
		for _, toEntUserId := range strings.Split(in.ToEntUserId, ",") {
			toEntUserId = encrypt.SE.Decode4HexByCheck(toEntUserId)
			if toEntUserId == "" {
				log.Println("划转对象不能为空", in.ProjectIds, in.EntId)
				continue
			}
			//查询划转人信息
			entUserId, _ := strconv.ParseInt(toEntUserId, 10, 64)
			userInfo := IC.Middleground.UserCenter.IdentityByEntUserId(entUserId)
			positionId := userInfo.PositionId
			//保存参标--participate_user
			//查看是否参标过当前项目
			if c := IC.BaseMysql.CountBySql("SELECT count(id) FROM "+ParticipateUserTable+" WHERE position_id = ? AND project_id = ?  AND ent_id = ?", positionId, projectId, in.EntId); c > 0 {
				//更新
				b3 = IC.BaseMysql.UpdateByTx(tx, ParticipateUserTable, map[string]interface{}{
					"position_id": positionId,
					"project_id":  projectId,
					"ent_id":      in.EntId,
				}, map[string]interface{}{
					"state":       0,
					"mark":        1, //0：参标；1：被划入；-1：终止参标；-2：被划走
					"update_date": date.FormatDate(&now, date.Date_Full_Layout),
				})
			} else {
				//保存
				b3 = IC.BaseMysql.InsertByTx(tx, ParticipateUserTable, map[string]interface{}{
					"ent_id":      in.EntId,
					"ent_user_id": entUserId,
					"position_id": positionId,
					"project_id":  projectId,
					"user_id":     in.MgoUserId,
					"state":       0,
					"mark":        1, //0：参标；1：被划入；-1：终止参标；-2：被划走
					"create_date": date.FormatDate(&now, date.Date_Full_Layout),
					"update_date": date.FormatDate(&now, date.Date_Full_Layout),
				}) > 0
			}
			if b3 {
				toEntUserIds = append(toEntUserIds, toEntUserId)
				toEntUserNames = append(toEntUserNames, userInfo.EntUserName)
			}
		}
		//保存多个用户时  如果个别用户划转参标项目异常，直接跳过此用户，保存其他用户信息
		//防止最后一个用户保存异常
		if len(toEntUserIds) > 0 {
			b3 = true
		}
		//移动端单个项目划转给多个用户，划转记录保存一份，当前企业下参过标的或当前正在参标的人都能看到次记录
		//企业下 根据企业id 和项目id查询划转记录
		//个人版 根据职位id 和项目id查询划转记录
		//划转记录
		b2 = IC.BaseMysql.InsertByTx(tx, ParticipateBidRecordsTable, map[string]interface{}{
			"ent_id":               in.EntId,
			"ent_user_id":          in.EntUserId,
			"position_id":          in.PositionId,
			"project_id":           projectId,
			"record_type":          0,
			"transfer_ent_user_id": strings.Join(toEntUserIds, ","),
			"record_content":       fmt.Sprintf(content, strings.Join(fromEntUserNames, "、"), strings.Join(toEntUserNames, "、"), lastNotes),
			"create_date":          date.FormatDate(&now, date.Date_Full_Layout),
		}) > 0
		log.Println(b1, "--", b2, "--", b3)
		return b1 && b2 && b3
	}) {
		log.Println(in.PositionId, "---终止---", projectId)
		return fmt.Errorf("终止参标更新信息出错")
	}
	return nil
}

// 终止参标
func CancelParticipateInfo(in *bxcore.ParticipateActionReq, roleId int64) error {
	defer MC.Catch()
	if !IC.BaseMysql.ExecTx("终止参标", func(tx *sql.Tx) bool {
		var (
			b1, b2 bool
			now    = time.Now()
			tip    = "终止参标"
		)
		//管理员终止：当前项目 其他参标人也被终止
		query := map[string]interface{}{
			"project_id": in.ProjectIds,
			"ent_id":     in.EntId,
		}
		//个人终止：仅仅终止本人参标项目
		if roleId == 0 {
			query["position_id"] = in.PositionId
			tip = "终止参标"
		}
		insert := map[string]interface{}{
			"state":       -1,
			"mark":        -1, //0：参标；1：被划入；-1：终止参标；-2：被划走
			"update_date": date.FormatDate(&now, date.Date_Full_Layout),
		}
		//更新参标participate_user
		b1 = IC.BaseMysql.UpdateByTx(tx, ParticipateUserTable, query, insert)
		//保存参标记录--participate_bid_records
		b2 = IC.BaseMysql.InsertByTx(tx, ParticipateBidRecordsTable, map[string]interface{}{
			"ent_id":         in.EntId,
			"ent_user_id":    in.EntUserId,
			"position_id":    in.PositionId,
			"project_id":     in.ProjectIds,
			"record_type":    0,
			"record_content": tip,
			"create_date":    date.FormatDate(&now, date.Date_Full_Layout),
		}) > 0
		return b1 && b2
	}) {
		log.Println(in.PositionId, "---终止---", in.ProjectIds)
		return fmt.Errorf("终止参标更新信息出错")
	}
	return nil
}

// 保存参标信息
func SaveParticipateInfo(in *bxcore.ParticipateActionReq) error {
	defer MC.Catch()
	if !IC.BaseMysql.ExecTx("保存|更新参标信息及保存参标记录", func(tx *sql.Tx) bool {
		var (
			b1, b2, b3 bool
			now        = time.Now()
		)
		//保存参标--participate_user
		//查看是否参标过当前项目
		if c := IC.BaseMysql.CountBySql("SELECT count(id) FROM "+ParticipateUserTable+" WHERE position_id = ? AND project_id = ?  AND ent_id = ?", in.PositionId, in.ProjectIds, in.EntId); c > 0 {
			//更新
			b1 = IC.BaseMysql.UpdateByTx(tx, ParticipateUserTable, map[string]interface{}{
				"position_id": in.PositionId,
				"ent_id":      in.EntId,
				"project_id":  in.ProjectIds,
			}, map[string]interface{}{
				"state":       0,
				"mark":        0,
				"update_date": date.FormatDate(&now, date.Date_Full_Layout),
			})
		} else {
			//保存
			b1 = IC.BaseMysql.InsertByTx(tx, ParticipateUserTable, map[string]interface{}{
				"ent_id":      in.EntId,
				"ent_user_id": in.EntUserId,
				"position_id": in.PositionId,
				"project_id":  in.ProjectIds,
				"user_id":     in.MgoUserId,
				"state":       0,
				"mark":        0,
				"create_date": date.FormatDate(&now, date.Date_Full_Layout),
				"update_date": date.FormatDate(&now, date.Date_Full_Layout),
			}) > 0
		}
		if !b1 {
			return false
		}
		//保存参标记录participate_bid_records
		b2 = IC.BaseMysql.InsertByTx(tx, ParticipateBidRecordsTable, map[string]interface{}{
			"ent_id":         in.EntId,
			"ent_user_id":    in.EntUserId,
			"position_id":    in.PositionId,
			"project_id":     in.ProjectIds,
			"record_type":    0,
			"record_content": "参标",
			"create_date":    date.FormatDate(&now, date.Date_Full_Layout),
		}) > 0
		if !b2 {
			return false
		}
		//保存或更新项目信息
		//有问题 其他回滚，项目信息不用回滚
		b3 = UpdateProjectInfo(in.ProjectIds, es.GetProjectInfo(in.ProjectIds)) == nil
		return b1 && b2 && b3
	}) {
		log.Println(in.PositionId, "---保存---", in.ProjectIds)
		return fmt.Errorf("保存参标信息出错")
	}
	return nil
}

// 查询当前招标信息是否已被参标
func IsParticipatedByBidId(in *bxcore.ParticipateActionReq) (entUserName string) {
	defer MC.Catch()
	//如果不允许多人参标 当前项目是否已经有企业其他人员参标
	query := fmt.Sprintf(`SELECT ent_id,ent_user_id FROM `+ParticipateUserTable+` WHERE %s AND project_id = '%s' AND state >-1`, "%s", in.ProjectIds)
	if in.PositionType > 0 { //企业版
		query = fmt.Sprintf(query, fmt.Sprintf("ent_id = %d", in.EntId))
	} else { //个人版
		query = fmt.Sprintf(query, fmt.Sprintf("position_id = %d", in.PositionId))
	}
	data := IC.BaseMysql.SelectBySql(query)
	if data != nil && len(*data) > 0 {
		partInfo := (*data)[0]
		if entUserId := MC.Int64All(partInfo["ent_user_id"]); entUserId > 0 {
			userInfo := IC.Middleground.UserCenter.IdentityByEntUserId(entUserId)
			entUserName = userInfo.EntUserName
		}
	}
	return
}

// 获取参标权限
func GetParticipateIsAllow(query map[string]interface{}) (b bool) {
	defer MC.Catch()
	if info, ok := IC.Mgo.FindOne(PartTable, query); ok {
		if info != nil {
			if (*info)["i_isallow"] != nil {
				b = MC.IntAll((*info)["i_isallow"]) > 0
			}
		}
	}
	return
}

// 更新设置信息
func UpdateParticipateSetInfo(in *bxcore.ParticipateSetUpInfoReq) error {
	defer MC.Catch()
	query := map[string]interface{}{
		"i_positionid": in.PositionId,
	}
	if in.PositionType > 0 {
		query = map[string]interface{}{
			"i_entid": in.EntId,
		}
	}
	upsert := map[string]interface{}{
		"i_entid":      in.EntId,
		"i_entuserid":  in.EntUserId,
		"i_positionid": in.PositionId,
		"l_createtime": time.Now().Unix(),
	}
	if in.IsAllow != "" {
		if in.IsAllow == "0" { //修改为允许单人参标
			//判断是否有多人参标的项目
			//pSql := `SELECT project_id,COUNT(id) AS c FROM ` + ParticipateUserTable + ` WHERE ent_id = ?  AND state =0 GROUP BY project_id ORDER BY c DESC;`
			pSql := `SELECT pu.project_id,COUNT(pu.id) AS c,p.bid_end_time,p.bid_open_time FROM ` + ParticipateUserTable + ` pu LEFT JOIN project p ON pu.project_id = p.id WHERE pu.ent_id = ?  AND pu.state =0 AND ((p.bid_open_time  > ?  or p.bid_open_time is null) and (p.bid_end_time IS NULL  or p.bid_end_time > ?)) GROUP BY pu.project_id ORDER BY c DESC`
			data := IC.BaseMysql.SelectBySql(pSql, in.EntId, time.Now().Format(date.Date_Full_Layout), time.Now().Format(date.Date_Full_Layout))
			if data != nil && len(*data) > 0 {
				if max := MC.IntAll((*data)[0]["c"]); max > 1 {
					return fmt.Errorf("公司当前有项目多人参标的情况，请先确保项目都是单人参标的前提下再调整配置。\n前往”企业参标项目列表“查看具体情况。")
				}
			}
		}
		isAllow, _ := strconv.Atoi(in.IsAllow)
		upsert["i_isallow"] = isAllow
	}
	if len(in.BidType) > 0 {
		upsert["o_bidtype"] = in.BidType
	}
	if len(in.RemindRule) > 0 {
		upsert["o_remindrule"] = in.RemindRule
	}
	if in.NecessaryField != "" {
		upsert["s_requiredField"] = in.NecessaryField
	}
	if ok := IC.Mgo.Update(PartTable, query, map[string]interface{}{
		"$set": upsert,
	}, true, false); ok {
		return nil
	}
	return fmt.Errorf("更新失败")
}

// 查询企业|个人参标设置信息
func GetParticipateSetInfo(in *bxcore.ParticipateSetUpInfoReq) (*bxcore.ParticipateSetUpInfo, error) {
	defer MC.Catch()
	query := map[string]interface{}{
		"i_positionid": in.PositionId,
	}
	if in.PositionType > 0 {
		query = map[string]interface{}{
			"i_entid": in.EntId,
		}
	}
	if setInfo, ok := IC.Mgo.FindOne(PartTable, query); ok {
		var (
			isAllow    int64
			isRequired string
			bidType    []*bxcore.BidTypeReq
			remindRule []*bxcore.RemindRuleReq
		)
		bidType = append(bidType, &bxcore.BidTypeReq{
			Name:    "直接投标",
			Content: []string{"未报名", "已报名", "投标决策", "编制投标文件", "递交投标文件", "中标公示", "签合同", "已结束"},
		}, &bxcore.BidTypeReq{
			Name:    "渠道投标",
			Content: []string{"已报名", "签合同", "已结束"},
		})
		remindRule = append(remindRule, &bxcore.RemindRuleReq{
			BidState:  "直接投标",
			Remainder: 72,
			Node:      "编制投标文件",
		})
		if setInfo != nil {
			//必填字段
			if (*setInfo)["s_requiredField"] != nil {
				isRequired = MC.ObjToString((*setInfo)["s_requiredField"])
			} else {
				isRequired = "bidType"
			}
			isAllow = MC.Int64All((*setInfo)["i_isallow"])
			if (*setInfo)["o_bidtype"] != nil {
				if sbb, err := json.Marshal((*setInfo)["o_bidtype"]); err == nil {
					if err := json.Unmarshal(sbb, &bidType); err != nil {
						log.Println("bidType json un err:", err.Error())
						return nil, err
					}
				} else {
					log.Println("bidType json err:", err.Error())
					return nil, err
				}
			}
			if (*setInfo)["o_remindrule"] != nil {
				if sbr, err := json.Marshal((*setInfo)["o_remindrule"]); err == nil {
					if err := json.Unmarshal(sbr, &remindRule); err != nil {
						log.Println("remindRule json un err:", err.Error())
						return nil, err
					}
				} else {
					log.Println("remindRule json err:", err.Error())
					return nil, err
				}
			}
		}
		return &bxcore.ParticipateSetUpInfo{
			NecessaryField: isRequired,
			IsAllow:        isAllow,
			BidType:        bidType,
			RemindRule:     remindRule,
		}, nil
	}
	return nil, nil
}

// 保存或更新tidb 项目信息
func UpdateProjectInfo(id string, pInfo map[string]interface{}) error {
	//id 项目id
	//name 项目名称
	//area  省份
	//city 城市
	//buyer 采购单位
	//budget 预算
	//bid_open_time  开标时间
	//zbtime 招标时间
	//bid_end_time 开标结束时间  bidding表 由 数据组 重新生索引到project表
	//pici 批次 轮询更新数据
	//
	projectInfo := map[string]interface{}{
		"id":     id,
		"name":   MC.ObjToString(pInfo["projectname"]),
		"area":   MC.ObjToString(pInfo["area"]),
		"city":   MC.ObjToString(pInfo["city"]),
		"buyer":  MC.ObjToString(pInfo["buyer"]),
		"budget": MC.Int64All(pInfo["budget"]),
	}
	if pInfo["bidopentime"] != nil {
		openTime := pInfo["bidopentime"]
		projectInfo["bid_open_time"] = date.FormatDateWithObj(&openTime, date.Date_Full_Layout)
	}
	if pInfo["pici"] != nil {
		pici := pInfo["pici"]
		projectInfo["pici"] = date.FormatDateWithObj(&pici, date.Date_Full_Layout)
	}
	// 项目表：zbtime 招标时间是 biding表：publishtime发布时间
	if pInfo["zbtime"] != nil {
		bidTime := pInfo["zbtime"]
		projectInfo["bid_time"] = date.FormatDateWithObj(&bidTime, date.Date_Full_Layout)
	}
	if pInfo["bidendtime"] != nil {
		bidEndTime := pInfo["bidendtime"]
		projectInfo["bid_end_time"] = date.FormatDateWithObj(&bidEndTime, date.Date_Full_Layout)
	}
	if c := IC.BaseMysql.CountBySql(`SELECT COUNT(id) FROM project WHERE id = ?`, id); c > 0 {
		if ok := IC.BaseMysql.Update("project", map[string]interface{}{
			"id": id,
		}, projectInfo); !ok {
			return fmt.Errorf("项目信息更新异常", id)
		}
	} else {
		if i := IC.BaseMysql.Insert("project", projectInfo); i < 0 {
			return fmt.Errorf("项目信息插入异常", id)
		}
	}
	return nil
}

// 参标列表其他条件
func ParticipateListSql(in *bxcore.ParticipateListReq) string {
	//b  project表
	//a  participate_user表
	now := time.Now()
	nowDate := date.FormatDate(&now, date.Date_Full_Layout)
	//查询tidb  base_service.project
	conditionSql := ` `
	//地区
	if in.Area != "" {
		conditionSql += fmt.Sprintf(" AND pt.area IN ('%s') ", strings.ReplaceAll(in.Area, ",", "','"))
	}
	//城市
	if in.City != "" {
		conditionSql += fmt.Sprintf(" AND pt.city IN ('%s') ", strings.ReplaceAll(in.City, ",", "','"))
	}
	//关键词
	if in.Keywords != "" {
		kSql := ` AND (`
		for kk, kv := range strings.Split(in.Keywords, " ") {
			log.Println(kk, "----", kv)
			if kk > 0 {
				kSql += " OR "
			}
			kSql += " pt.name like '%" + kv + "%'"
		}
		kSql += `)`
		conditionSql += kSql
	}
	//招标日期
	if in.BidTime != "" && strings.Contains(in.BidTime, "-") {
		startTime := strings.Split(in.BidTime, "-")[0]
		entTime := strings.Split(in.BidTime, "-")[1]
		if startTime != "" {
			startTimeInt, _ := strconv.ParseInt(startTime, 10, 64)
			conditionSql += ` AND pt.bid_time > '` + date.FormatDateByInt64(&startTimeInt, date.Date_Full_Layout) + `'`
		}
		if entTime != "" {
			entTimeInt, _ := strconv.ParseInt(entTime, 10, 64)
			conditionSql += ` AND pt.bid_time < '` + date.FormatDateByInt64(&entTimeInt, date.Date_Full_Layout) + `'`
		}
	}
	//招标截止日期
	if in.BidEndTime != "" {
		//投标截止日期规则：
		//1、开始时间小于当前时间 ，结束时间大于当前时间，投标截止状态按钮未截止和已截止可用；
		//2、结束时间小于当前时间|开始时间大于当前时间，投标截止状态按钮未截止和已截止不可用；
		//3、需要前端做成连动
		startTime := strings.Split(in.BidEndTime, "-")[0]
		endTime := strings.Split(in.BidEndTime, "-")[1]
		startTimeInt, _ := strconv.ParseInt(startTime, 10, 64)
		endTimeInt, _ := strconv.ParseInt(endTime, 10, 64)
		bidEndTimeSql := ``
		if startTimeInt > 0 && endTimeInt > 0 && startTimeInt > endTimeInt {
			log.Println(fmt.Sprintf("投标截止日期 %d 开始时间 大于 结束时间%d！！！", startTimeInt, endTimeInt))
		} else {
			if startTimeInt > 0 {
				bidEndTimeSql += ` AND pt.bid_end_time > '` + date.FormatDateByInt64(&startTimeInt, date.Date_Full_Layout) + `'`
			}
			if endTimeInt > 0 {
				bidEndTimeSql += ` AND pt.bid_end_time < '` + date.FormatDateByInt64(&endTimeInt, date.Date_Full_Layout) + `'`
			}
			switch in.BidEndStatus {
			case 1: //投标截止状态：1：未截止；2：已截止；3：终止参标
				bidEndTimeSql = ``
				//未截止：
				var (
					endBool = true
				)
				//如果结束时间存在且小于当前时间，投标截止日期 范围都是已截止 不会存在未截止的数据
				if endTimeInt > 0 {
					bidEndTimeSql += ` AND pt.bid_end_time < '` + date.FormatDateByInt64(&endTimeInt, date.Date_Full_Layout) + `'`
					endBool = endTimeInt > now.Unix()
				}
				//开始时间小于 当前时间
				if endBool && now.Unix() > startTimeInt {
					startTimeInt = now.Unix()
				}
				//存在开始时间为0的情况
				if startTimeInt > 0 {
					bidEndTimeSql += ` AND pt.bid_end_time > '` + date.FormatDateByInt64(&startTimeInt, date.Date_Full_Layout) + `'`
				}
			case 2: //投标截止状态：1：未截止；2：已截止；3：终止参标
				//如果开始时间存在且大于当前时间，投标截止日期 范围都是未截止 不会存在已截止的数据
				var (
					startBool = true
				)
				bidEndTimeSql = ``
				if startTimeInt > 0 {
					bidEndTimeSql += ` AND pt.bid_end_time > '` + date.FormatDateByInt64(&startTimeInt, date.Date_Full_Layout) + `'`
					startBool = startTimeInt < now.Unix()
				}
				if startBool && (endTimeInt == 0 || now.Unix() < endTimeInt) {
					endTimeInt = now.Unix()
				}
				//存在结束时间为0的情况
				if endTimeInt > 0 {
					bidEndTimeSql += ` AND pt.bid_end_time < '` + date.FormatDateByInt64(&endTimeInt, date.Date_Full_Layout) + `'`
				}
			case 3:
				bidEndTimeSql += ` AND pug.state < 0 `
			}
		}
		if bidEndTimeSql != "" {
			conditionSql += bidEndTimeSql
		}
	} else if in.BidEndStatus > 0 { //投标截止状态1:未截止；2:已截止；3:终止参标
		switch in.BidEndStatus {
		case 1:
			conditionSql += ` AND pt.bid_end_time > '` + nowDate + `'`
		case 2:
			conditionSql += ` AND pt.bid_end_time < '` + nowDate + `'`
		case 3:
			conditionSql += ` AND pug.state < 0 `
		}
	}
	//开标时间
	if in.BidOpenTime != "" {
		startTime := strings.Split(in.BidOpenTime, "-")[0]
		entTime := strings.Split(in.BidOpenTime, "-")[1]
		if startTime != "" {
			startTimeInt, _ := strconv.ParseInt(startTime, 10, 64)
			conditionSql += ` AND pt.bid_open_time > '` + date.FormatDateByInt64(&startTimeInt, date.Date_Full_Layout) + `'`
		}
		if entTime != "" {
			entTimeInt, _ := strconv.ParseInt(entTime, 10, 64)
			conditionSql += ` AND pt.bid_open_time < '` + date.FormatDateByInt64(&entTimeInt, date.Date_Full_Layout) + `'`
		}
	}
	//开标状态1：未开标；2：已开标
	if in.BidOpenStatus > 0 {
		switch in.BidOpenStatus {
		case 1:
			conditionSql += ` AND pt.bid_open_time > '` + nowDate + `'`
		case 2:
			conditionSql += ` AND pt.bid_open_time < '` + nowDate + `'`
		}
	}
	//参标人  管理员权限
	if in.EntUserIds != "" && in.PositionType > 0 {
		var entUserIdsSql = ""
		for k, v := range strings.Split(in.EntUserIds, ",") {
			v = encrypt.SE.Decode4HexByCheck(v)
			if v == "" {
				continue
			}
			if k > 0 && entUserIdsSql != "" {
				entUserIdsSql += " OR "
			}
			entUserIdsSql += ` FIND_IN_SET(` + v + ` , pug.ent_user_id) `
		}
		if entUserIdsSql != "" {
			conditionSql += ` AND  (` + entUserIdsSql + `)`
		}
	}
	//默认按照投标截止日期正序排列、1：开标时间正序、2：更新状态时间倒序
	//投标结束时间和开标时间 很多项目数据没有这两个字段值
	switch in.OrderNum {
	case 1:
		conditionSql += ` ORDER BY (pt.bid_open_time IS NULL),pt.bid_open_time ASC,(pt.bid_end_time IS NULL),pt.bid_end_time ASC,pbr.create_date DESC`
	case 2:
		conditionSql += ` ORDER BY pbr.create_date DESC`
	default:
		conditionSql += ` ORDER BY (pt.bid_end_time IS NULL),pt.bid_end_time ASC,(pt.bid_open_time IS NULL),pt.bid_open_time ASC,pbr.create_date DESC`
	}
	log.Println(conditionSql)
	return conditionSql
}

// 个人或员工查询参标列表
func SingleParticipateList(in *bxcore.ParticipateListReq, conditionSql string) (data *bxcore.ParticipateData, err error) {
	defer MC.Catch()
	data = &bxcore.ParticipateData{
		NowTime: time.Now().Unix(),
		Count:   0,
		List:    []*bxcore.ParticipateList{},
	}
	//员工|个人列表
	singlePersonSql := `SELECT %s FROM ` + ParticipateUserTable + ` pug LEFT JOIN project pt ON pug.project_id = pt.id LEFT JOIN (SELECT project_id,position_id,MAX(create_date) AS create_date FROM participate_bid_records GROUP BY project_id,position_id) pbr ON pbr.project_id = pug.project_id AND pbr.position_id = pug.position_id WHERE pug.position_id = ? `
	//singlePersonSql += conditionSql
	countSql := fmt.Sprintf(singlePersonSql, " COUNT(pt.id) ") + conditionSql
	count := IC.BaseMysql.CountBySql(countSql, in.PositionId)
	log.Println(countSql, "---", count)
	if count > 0 {
		data.Count = count
		listSql := fmt.Sprintf(singlePersonSql, " pt.*,pbr.create_date,pug.state ") + conditionSql
		//分页
		listSql += fmt.Sprintf(` LIMIT %d,%d`, in.PageNum, in.PageSize)
		log.Println("listSql:", listSql)
		list := IC.BaseMysql.SelectBySql(listSql, in.PositionId)
		if list != nil && len(*list) > 0 {
			for _, v := range *list {
				bidTimeStr := MC.ObjToString(v["bid_time"])
				bidEndTimeStr := MC.ObjToString(v["bid_end_time"])
				bidOpenTimeStr := MC.ObjToString(v["bid_open_time"])
				updateStatusTimeStr := MC.ObjToString(v["create_date"])
				beTransferred := true
				//已终止参标
				stateInt64 := MC.Int64All(v["state"])
				if stateInt64 < 0 {
					beTransferred = false
				}
				var bidTime, bidEndTime, bidOpenTime, updateStatusTime int64
				if bidTimeStr != "" {
					bidTime_, _ := time.ParseInLocation(date.Date_Full_Layout, bidTimeStr, time.Local)
					bidTime = bidTime_.Unix()
				}
				if bidEndTimeStr != "" {
					bidEndTime_, _ := time.ParseInLocation(date.Date_Full_Layout, bidEndTimeStr, time.Local)
					bidEndTime = bidEndTime_.Unix()
					//招标结束时间小于当前时间
					if beTransferred && bidEndTime > 0 && bidEndTime < time.Now().Unix() {
						beTransferred = false
					}
				}
				if bidOpenTimeStr != "" {
					bidOpenTime_, _ := time.ParseInLocation(date.Date_Full_Layout, bidOpenTimeStr, time.Local)
					bidOpenTime = bidOpenTime_.Unix()
					//招标开始时间小于当前时间
					if beTransferred && bidOpenTime > 0 && bidOpenTime < time.Now().Unix() {
						beTransferred = false
					}
				}
				if updateStatusTimeStr != "" {
					updateStatusTime_, _ := time.ParseInLocation(date.Date_Full_Layout, updateStatusTimeStr, time.Local)
					updateStatusTime = updateStatusTime_.Unix()
				}
				data.List = append(data.List, &bxcore.ParticipateList{
					Id:               encrypt.EncodeArticleId2ByCheck(MC.ObjToString(v["id"])),
					ProjectName:      MC.ObjToString(v["name"]),
					Buyer:            MC.ObjToString(v["buyer"]),
					Budget:           MC.ObjToString(v["budget"]),
					BidTime:          bidTime,
					BidEndTime:       bidEndTime,
					BidOpenTime:      bidOpenTime,
					UpdateStatusTime: updateStatusTime,
					State:            stateInt64,
					BeTransferred:    beTransferred, //是否能划转
					//UpdateStatusCon:  GetParticipateContent("s", in.PositionId, MC.ObjToString(v["id"])), //查询最后一次 投标状态更新,
				})
			}
			return data, nil
		}
		return nil, fmt.Errorf("数据异常")
	}
	return data, nil
}

// 管理员获取参标列表数据
func AdminParticipateList(in *bxcore.ParticipateListReq, conditionSql string) (data *bxcore.ParticipateData, err error) {
	defer MC.Catch()
	data = &bxcore.ParticipateData{
		IsAllow: IsALLow(in.EntId),
		NowTime: time.Now().Unix(),
		Count:   0,
		List:    []*bxcore.ParticipateList{},
	}
	adminSql := `SELECT %s FROM (SELECT pu.ent_id, pu.project_id, GROUP_CONCAT(pu.ent_user_id SEPARATOR ',') ent_user_id,MAX(pu.state) state FROM ` + ParticipateUserTable + ` pu WHERE pu.ent_id = ? AND NOT EXISTS ( SELECT 1 FROM ` + ParticipateUserTable + ` ppu WHERE ppu.project_id = pu.project_id AND ppu.ent_id = pu.ent_id AND ppu.state > pu.state ) GROUP BY pu.project_id ) pug LEFT JOIN project pt ON pug.project_id = pt.id LEFT JOIN (SELECT project_id,ent_id,MAX(create_date) AS create_date FROM participate_bid_records GROUP BY project_id,ent_id) pbr ON pbr.project_id = pug.project_id AND pbr.ent_id = pug.ent_id  WHERE 1=1 `
	//maxStateSql := ``
	//stateSql := ``
	//if in.EntUserIds == "" {
	//	//maxStateSql = `,MAX(pu.state) state`
	//	stateSql = ``
	//}
	//adminSql = fmt.Sprintf(adminSql, "%s", stateSql)
	adminCountSql := fmt.Sprintf(adminSql, "COUNT(pt.id)") + conditionSql
	log.Println(adminCountSql)
	count := IC.BaseMysql.CountBySql(adminCountSql, in.EntId)
	if count > 0 {
		data.Count = count
		adminListSql := fmt.Sprintf(adminSql, " pt.*, pug.ent_user_id,pbr.create_date,pug.state ") + conditionSql + fmt.Sprintf(" LIMIT %d,%d", in.PageNum, in.PageSize)
		list := IC.BaseMysql.SelectBySql(adminListSql, in.EntId)
		if list != nil && len(*list) > 0 {
			for _, v := range *list {
				bidTimeStr := MC.ObjToString(v["bid_time"])
				bidEndTimeStr := MC.ObjToString(v["bid_end_time"])
				bidOpenTimeStr := MC.ObjToString(v["bid_open_time"])
				updateStatusTimeStr := MC.ObjToString(v["create_date"])
				beTransferred := true
				//已终止参标
				stateInt64 := MC.Int64All(v["state"])
				if stateInt64 < 0 {
					beTransferred = false
				}
				var bidTime, bidEndTime, bidOpenTime, updateStatusTime int64
				if bidTimeStr != "" {
					bidTime_, _ := time.ParseInLocation(date.Date_Full_Layout, bidTimeStr, time.Local)
					bidTime = bidTime_.Unix()
				}
				if bidEndTimeStr != "" {
					bidEndTime_, _ := time.ParseInLocation(date.Date_Full_Layout, bidEndTimeStr, time.Local)
					bidEndTime = bidEndTime_.Unix()
					//招标结束时间小于当前时间
					if beTransferred && bidEndTime > 0 && bidEndTime < time.Now().Unix() {
						beTransferred = false
					}
				}
				if bidOpenTimeStr != "" {
					bidOpenTime_, _ := time.ParseInLocation(date.Date_Full_Layout, bidOpenTimeStr, time.Local)
					bidOpenTime = bidOpenTime_.Unix()
					//招标开始时间小于当前时间
					if beTransferred && bidOpenTime > 0 && bidOpenTime < time.Now().Unix() {
						beTransferred = false
					}
				}
				if updateStatusTimeStr != "" {
					updateStatusTime_, _ := time.ParseInLocation(date.Date_Full_Layout, updateStatusTimeStr, time.Local)
					updateStatusTime = updateStatusTime_.Unix()
				}

				data.List = append(data.List, &bxcore.ParticipateList{
					Id:               encrypt.EncodeArticleId2ByCheck(MC.ObjToString(v["id"])),
					ProjectName:      MC.ObjToString(v["name"]),
					Buyer:            MC.ObjToString(v["buyer"]),
					Budget:           MC.ObjToString(v["budget"]),
					BidTime:          bidTime,
					BidEndTime:       bidEndTime,
					BidOpenTime:      bidOpenTime,
					UpdateStatusTime: updateStatusTime,
					State:            stateInt64,
					BeTransferred:    beTransferred, //是否能划转
					//UpdateStatusCon:  GetParticipateContent("e", in.EntId, MC.ObjToString(v["id"])), //查询最后一次 投标状态更新
					Participants: GetParticipateUserName(MC.ObjToString(v["id"]), MC.ObjToString(v["ent_user_id"]), in.EntUserIds != ""), //参标人信息
				})
			}
			return data, nil
		}
		return nil, fmt.Errorf("数据异常")
	}
	return data, nil
}

// 获取最新参标 更新内容
func GetParticipateContent(s string, id int64, projectId string) string {
	identitySql := `ent_id = ?`
	if s == "s" {
		identitySql = `position_id = ?`
	}
	recordsSql := `SELECT record_content,record_type FROM ` + ParticipateBidRecordsTable + ` WHERE ` + identitySql + ` AND project_id = ? ORDER BY create_date DESC LIMIT 1;`
	records := IC.BaseMysql.SelectBySql(recordsSql, id, projectId)
	if records != nil && len(*records) > 0 {
		rec := (*records)[0]
		switch MC.IntAll(rec["record_type"]) {
		case 0:
			return MC.ObjToString(rec["record_content"])
		case 1:
			recordContent := *MC.ObjToMap(rec["record_content"])
			rb, err := json.Marshal(recordContent)
			if err != nil {
				log.Println(err.Error())
				return ""
			}
			var rc = RecordsContent{
				After:  PartStatusContent{},
				Before: PartStatusContent{},
			}
			err1 := json.Unmarshal(rb, &rc)
			if err1 == nil {
				return rc.Content
			}
		}
	}
	return ""
}

// 根据ent_user_id 获取参标人昵称，企业管理员现在都是“我”
func GetParticipateUserName(projectId, entUserIdsFromData string, b bool) string {
	if entUserIdsFromData != "" {
		var userNames []string
		for _, v := range strings.Split(entUserIdsFromData, ",") {
			if b {
				//已终止参标
				if c := IC.BaseMysql.CountBySql(`SELECT count(id) FROM `+ParticipateUserTable+` WHERE project_id = ? AND ent_user_id = ? AND state <0`, projectId, v); c > 0 {
					continue
				}
			}
			entUserInfos := IC.MainMysql.SelectBySql(`SELECT * FROM entniche_user WHERE id = ?`, v)
			if entUserInfos != nil && len(*entUserInfos) > 0 {
				entUserInfo := (*entUserInfos)[0]
				if entUserInfo["name"] != nil {
					if userName := MC.ObjToString(entUserInfo["name"]); userName != "" {
						userNames = append(userNames, userName)
					}
				}
			}
		}
		return strings.Join(userNames, ",")
	}
	return ""
}

// GetBidContentEnt 企业版 获取投标状态更新内容
func GetBidContentEnt(projectId string, entId int64) *[]map[string]interface{} {
	// record_type '默认0：参标、划转、取消参标；1：投标状态更新存储'
	query := "SELECT * FROM " + ParticipateBidRecordsTable + " where project_id=? and ent_id=? and record_type=1 order by create_date desc limit 1; "
	return IC.BaseMysql.SelectBySql(query, projectId, entId)
}

// GetBidContentPersonal 个人版 获取投标状态更新内容
func GetBidContentPersonal(projectId string, positionId int64) *[]map[string]interface{} {
	query := "SELECT * FROM " + ParticipateBidRecordsTable + " where project_id=? and position_id=? and  record_type=1  order by create_date desc limit 1;"
	return IC.BaseMysql.SelectBySql(query, projectId, positionId)
}

// UpdateBidContent 更新投标状态信息以及操作记录
func UpdateBidContent(recordData map[string]interface{}) (flag bool) {
	r2 := IC.BaseMysql.Insert(ParticipateBidRecordsTable, recordData)
	return r2 > 0
}

// InsertBidContent 新增投标状态信息及操作记录
func InsertBidContent(recordData map[string]interface{}) (flag bool) {
	r2 := IC.BaseMysql.Insert(ParticipateBidRecordsTable, recordData)
	return r2 > 0
}

// GetBidRecordsEnt 获取操作记录列表企业
func GetBidRecordsEnt(projectId string, entId, page, pageSize int64) (rs *[]map[string]interface{}, total int64) {
	query := "SELECT * FROM " + ParticipateBidRecordsTable + " where project_id=? and ent_id=?   order by create_date desc limit ?,?"
	countQuery := "SELECT count(id) FROM " + ParticipateBidRecordsTable + " where project_id=? and ent_id=? ;"
	rs = IC.BaseMysql.SelectBySql(query, projectId, entId, (page-1)*pageSize, pageSize)
	total = IC.BaseMysql.CountBySql(countQuery, projectId, entId)
	return rs, total
}

// GetBidRecordsPersonal 获取操作记录列表个人
func GetBidRecordsPersonal(projectId string, positionId, page, pageSize int64) (rs *[]map[string]interface{}, total int64) {
	query := "SELECT * FROM " + ParticipateBidRecordsTable + " where project_id=? and position_id=?   order by create_date desc limit ?,?;"
	countQuery := "SELECT count(id) FROM " + ParticipateBidRecordsTable + " where project_id=? and position_id=? ;"
	rs = IC.BaseMysql.SelectBySql(query, projectId, positionId, (page-1)*pageSize, pageSize)
	total = IC.BaseMysql.CountBySql(countQuery, projectId, positionId)
	return rs, total
}

// GetUserMap 查询用户id的姓名
func GetUserMap(userIds string) (rs *[]map[string]interface{}) {
	query := fmt.Sprintf("select id,name from entniche_user where id in (%s)", userIds)
	rs = IC.MainMysql.SelectBySql(query)
	return rs
}

// CheckParticipateManager 验证项目id是否是该管理员企业下的参标项目
func CheckParticipateManager(projectId string, entId int64, valid bool) (flag bool) {
	stateStr := "" // 是否需要验证是正在参标
	if valid {
		stateStr = " and state=0"
	}
	query := "SELECT count(id) FROM " + ParticipateUserTable + " where project_id=? and ent_id=?" + stateStr
	return IC.BaseMysql.CountBySql(query, projectId, entId) > 0
}

// CheckParticipateEntUser 验证项目id是否是该企业用户参标的项目
func CheckParticipateEntUser(projectId string, entUserId int64, valid bool) (flag bool) {
	stateStr := "" // 是否需要验证是正在参标
	if valid {
		stateStr = " and state=0"
	}
	query := "SELECT count(id) FROM " + ParticipateUserTable + " where project_id=? and ent_user_id=?" + stateStr
	return IC.BaseMysql.CountBySql(query, projectId, entUserId) > 0

}

// CheckParticipatePersonal 查询项目id是否是该用户参标项目
func CheckParticipatePersonal(projectId string, positionId int64, valid bool) (flag bool) {
	stateStr := "" // 是否需要验证是正在参标 终止参标的用户还能查看记录，但是不能更新状态
	if valid {
		stateStr = " and state=0"
	}
	query := "SELECT count(id) FROM " + ParticipateUserTable + " where project_id=? and position_id=?" + stateStr
	return IC.BaseMysql.CountBySql(query, projectId, positionId) > 0
}

// GetNameByUserIds 获取用户名字符串
//
//	参数：逗号分割的用户id "11,22,333..."
//	返回: "张三,李四,王五..."
func GetNameByUserIds(ids string) *[]map[string]interface{} {
	query := "select  group_concat(name) as name  from " + EntnicheUserTable + " where id in (" + ids + ") "
	rs := IC.MainMysql.SelectBySql(query)
	return rs
}

// ParticipateProjectPersonal 查询给定项目id中已经参标的项目id
func ParticipateProjectPersonal(positionId int64, projectId []string) *[]map[string]interface{} {
	// 1. 查询出已经参标的
	var arg []string
	var value []interface{}
	value = append(value, positionId)
	for i := 0; i < len(projectId); i++ {
		arg = append(arg, "?")
		value = append(value, projectId[i])
	}
	argStr := strings.Join(arg, ",")
	query := "select project_id from " + ParticipateUserTable + " where position_id = ? and project_id in (%s)  and state=0"
	rs := IC.BaseMysql.SelectBySql(fmt.Sprintf(query, argStr), value...)
	return rs
}

// ParticipateProjectEnt 查询给定项目id中已经参标的项目id
func ParticipateProjectEnt(entId int64, projectId []string) *[]map[string]interface{} {
	// 1. 查询出已经参标的
	var arg []string
	var value []interface{}
	value = append(value, entId)
	for i := 0; i < len(projectId); i++ {
		arg = append(arg, "?")
		value = append(value, projectId[i])
	}
	argStr := strings.Join(arg, ",")
	query := "select GROUP_CONCAT(ent_user_id) as personIds ,project_id from " + ParticipateUserTable + " where ent_id=? and  project_id in (%s) and state=0  group by project_id "
	rs := IC.BaseMysql.SelectBySql(fmt.Sprintf(query, argStr), value...)
	return rs
}

// 查询企业人员信息
func GetPersonInfo(entId, entUserId int64, participateMap map[int64]bool) []*bxcore.ParticipatePerson {
	r := IC.MainMysql.SelectBySql(`SELECT a.id,a.pid,a.name,c.id as user_id,c.name as user_name,c.phone as user_phone,c.power as user_power,e.name as role from entniche_department a 
			INNER JOIN entniche_department_user b on (a.ent_id=? and a.id=b.dept_id) 
			INNER JOIN entniche_user c on (b.user_id=c.id) 
			LEFT JOIN entniche_user_role d on (c.id=d.user_id) 
			LEFT JOIN entniche_role e on (d.role_id=e.id) 
			order by a.id,convert(c.name using gbk) COLLATE gbk_chinese_ci asc`, entId)
	var (
		list   []*bxcore.ParticipatePerson
		prevId int64 = 0
	)
	for _, v := range *r {
		//if entUserId == MC.Int64All(v["user_id"]) {
		//	continue
		//}
		id := MC.Int64All(v["id"])
		userId := strconv.FormatInt(MC.Int64All(v["user_id"]), 10)
		user := &bxcore.ParticipatePerson{
			Id:    encrypt.SE.Encode2HexByCheck(userId),
			Power: MC.Int64All(v["user_power"]),
			Name:  MC.ObjToString(v["user_name"]),
			Phone: MC.ObjToString(v["user_phone"]),
			Role:  MC.ObjToString(v["role"]),
		}
		if participateMap != nil {
			if participateMap[MC.Int64All(v["user_id"])] {
				user.IsPart = 1
			}
		}
		if prevId == id {
			users := list[len(list)-1].Users
			users = append(users, user)
			list[len(list)-1].Users = users
		} else {
			seId := strconv.FormatInt(id, 10)
			list = append(list, &bxcore.ParticipatePerson{
				Id:    encrypt.SE.Encode2HexByCheck(seId),
				Name:  MC.ObjToString(v["name"]),
				Pid:   MC.Int64All(v["pid"]),
				Users: []*bxcore.ParticipatePerson{user},
			})
		}
		prevId = id
	}
	return list
}

// 是否允许多人参标
func IsALLow(entId int64) bool {
	return GetParticipateIsAllow(map[string]interface{}{
		"i_entid": entId,
	})
}
