package service

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

const (
	//角色
	Role_admin_system     = 1 //系统管理员
	Role_admin_department = 2 //部门管理员
)

type ParticipateStatistics struct {
	PositionId int64
	EntId      int64
	DeptId     int64
	EntUserId  int64
}

func (in *ParticipateStatistics) PushStatistics(entUserIdArr []string, startTime, endTime int64, source []int64, isMobile bool) (result []*bxcore.PushStatisticsData) {
	//判断是企业、部门还是个人
	isAdmin, personArrStr, users, userInfo := in.PersonHandle(entUserIdArr)
	//时间处理
	query := QueryHandle(isAdmin, startTime, endTime, personArrStr, source, 0)
	//推送数据查询
	dataList := IC.BaseMysql.SelectBySql(fmt.Sprintf("select  * from  participate_push_statistics where %s order  by ymd", strings.Join(query, " and ")))
	isManage := false
	if users != nil && len(*users) > 0 {
		if userInfo != nil {
			isManage = userInfo.Role_admin_department || userInfo.Role_admin_system
		}

		result = PushHandle(dataList, users, isAdmin, isManage, isMobile)
	}
	return
}

func (in *ParticipateStatistics) ProjectStatistics(entUserIdArr []string, startTime, endTime, bidWay int64) (result []*bxcore.ProjectStatisticsData) {
	//判断是企业、部门还是个人
	isAdmin, personArrStr, users, _ := in.PersonHandle(entUserIdArr)
	query := QueryHandle(isAdmin, startTime, endTime, personArrStr, []int64{}, bidWay)
	//订阅推送数处理
	//推送数据查询
	dataList := IC.BaseMysql.SelectBySql(fmt.Sprintf("select  * from  participate_project_statistics where %s order  by ymd  ", strings.Join(query, "and ")))
	if users != nil && len(*users) > 0 {
		result = ProjectHandle(dataList, users, isAdmin, bidWay)
	}
	return
}

var (
	SourceMap = map[string]string{
		"1": "个人订阅",
		"2": "企业自动分发",
		"3": "企业手动分发",
	}
)

// GetSourceItem 获取标讯项目来源筛选项
func (in *ParticipateStatistics) GetSourceItem(entId, positionId int) (result []*bxcore.SourceItem) {
	redisKey := "sourceItem%s_%d"
	query := "select group_concat(distinct(source))  as `source` from participate_push_statistics where  "
	// 个人用户
	if entId == 0 {
		// 查职位id
		query += fmt.Sprintf(" position_id =%d", positionId)
		redisKey = fmt.Sprintf(redisKey, "personal", positionId)
	} else {
		// 企业用户 用企业id查
		query += fmt.Sprintf(" ent_id =%d", entId)
		redisKey = fmt.Sprintf(redisKey, "ent", entId)
	}
	if data, err := redis.GetBytes("other", redisKey); err == nil && data != nil {
		err := json.Unmarshal(*data, &result)
		if err == nil {
			return
		} else {
			log.Println("序列化失败", redisKey, err)
		}
	}
	rs := IC.BaseMysql.SelectBySql(query)
	if rs == nil || len(*rs) == 0 {
		//emtpy := make([]*bxcore.SourceItem, 0)
		return
	}
	existMap := map[string]struct{}{}
	source_ := common.InterfaceToStr((*rs)[0]["source"])
	splitSource := strings.Split(source_, ",")
	for i := 0; i < len(splitSource); i++ {
		value := splitSource[i]
		if value == "" {
			continue
		}
		if _, ok := existMap[value]; ok {
			continue
		} else {
			existMap[value] = struct{}{}
		}
		if name, ok := SourceMap[value]; ok {
			value_, err := strconv.Atoi(value)
			if err == nil {
				result = append(result, &bxcore.SourceItem{
					Name:  name,
					Value: int64(value_),
				})
			} else {
				log.Println("转换失败：", err, value)
			}
		}

	}
	if len(result) > 0 {
		//  存缓存
		rsByte, _ := json.Marshal(result)
		redis.PutBytes("other", redisKey, &rsByte, 60*60*2)
	}
	return
}

// 注意：该方法返回值中第一个虽然名字叫IsAdmin 但是实际是指是否是企业版 用于区分企业和个人版 不能用于是否是管理员
func (in *ParticipateStatistics) PersonHandle(entUserIdArr []string) (isAdmin bool, idStr string, users *[]map[string]interface{}, userEnt *CurrentUser) {
	userEnt = EntInfo(common.IntAll(in.EntId), common.IntAll(in.EntUserId))
	if len(entUserIdArr) > 0 {
		//查询所选人的部门以及人员信息
		users = GetUser(entUserIdArr)
		//返回所选人的信息
		isAdmin = true
		idStr = strings.Join(entUserIdArr, ",")
	} else {
		if userEnt.Role_admin_department || userEnt.Role_admin_system { //
			// 部门管理员 获取所有部门和子部门员工
			users = GetDisUsers(common.IntAll(in.EntId), userEnt.Dept.Id)
			var staffs []string
			if users != nil && len(*users) > 0 {
				for _, v := range *users {
					staffs = append(staffs, common.InterfaceToStr(v["id"]))
				}
			}
			isAdmin = true
			idStr = strings.Join(staffs, ",")
		} else {
			if userEnt.Dept.Id != 0 {
				entUserIdArr = append(entUserIdArr, common.InterfaceToStr(in.EntUserId))
				users = GetUser(entUserIdArr)
				//返回所选人的信息
				isAdmin = true
				idStr = strings.Join(entUserIdArr, ",")
			} else {
				isAdmin = false
				idStr = common.InterfaceToStr(in.PositionId)
				users = &[]map[string]interface{}{
					map[string]interface{}{
						"id":   in.PositionId,
						"name": "个人",
					},
				}
			}

		}
	}
	return
}

type PushData struct {
	PersonName      string
	entUserId       string
	DepartmentName  string
	PushNumb        map[string]interface{}
	ParticipateNumb map[string]interface{}
	BidNumb         map[string]interface{}
	WinNumb         map[string]interface{}
	BrowseNumb      map[string]interface{}
	SourceMap       map[string]sourceStruct
}
type sourceStruct struct {
	PushNumb        map[string]interface{}
	ParticipateNumb map[string]interface{}
	BidNumb         map[string]interface{}
	WinNumb         map[string]interface{}
	BrowseNumb      map[string]interface{}
}
type ProjectData struct {
	PersonName             string
	DepartmentName         string
	entUserId              string
	BidNumb                map[string]interface{} //投标数量
	DirectBidNumb          map[string]interface{} //直接投标数
	ChannelBidNumb         map[string]interface{} //渠道投标数
	WinNumb                map[string]interface{}
	DirectWinNumb          map[string]interface{} //直接中标数
	ChannelWinNumb         map[string]interface{} //渠道中标数
	NotBidNumber           map[string]interface{} //未中标数量
	EndNumb                map[string]interface{} //终止数量
	participateProjectNumb map[string]interface{} // 参标数量
	Stage                  map[string]map[string]interface{}
	StageStr               map[string]string   // 字符串处理
	EndProject             map[string]struct{} // 终止参标项目不参与统计
}

func PushHandle(data *[]map[string]interface{}, users *[]map[string]interface{}, isAdmin bool, isManager bool, isMobile bool) []*bxcore.PushStatisticsData {
	result := &map[int64]*PushData{}
	for k, v := range *users {
		(*result)[common.Int64All(v["id"])] = &PushData{
			PersonName:     fmt.Sprintf("%s_%d", common.InterfaceToStr(v["name"]), k),
			DepartmentName: common.InterfaceToStr(v["dept_name"]),
			entUserId:      common.InterfaceToStr(v["id"]),
		}
	}
	if data != nil && len(*data) > 0 {
		for _, v := range *data {
			userId := int64(0)
			if isAdmin {
				userId = common.Int64All(v["ent_user_id"])
			} else {
				userId = common.Int64All(v["position_id"])
			}
			if (*result)[userId] != nil {
				//浏览总数处理处理
				project_id := common.InterfaceToStr(common.InterfaceToStr(v["project_id"]))
				if common.Int64All(v["isvisit"]) > 0 {
					(*result)[userId].BrowseNumb = DataHanle((*result)[userId].BrowseNumb, project_id)
				}
				//推送总数处理
				(*result)[userId].PushNumb = DataHanle((*result)[userId].PushNumb, project_id)
				//参标总数处理
				if common.Int64All(v["isparticipate"]) > 0 {
					(*result)[userId].ParticipateNumb = DataHanle((*result)[userId].ParticipateNumb, project_id)
				}
				//投标总数处理
				if common.Int64All(v["isbid"]) > 0 {
					(*result)[userId].BidNumb = DataHanle((*result)[userId].BidNumb, project_id)
				}
				//中标总数处理
				if common.Int64All(v["win_status"]) != 0 {
					win_status := common.Int64All(v["win_status"])
					if win_status == 1 {
						(*result)[userId].WinNumb = DataHanle((*result)[userId].WinNumb, project_id)
					} else {
						delete((*result)[userId].WinNumb, project_id)
					}
				}
				// 如果是个人处理  按照source分开统计
				if !isManager && common.InterfaceToStr(common.InterfaceToStr(v["source"])) != "" && !isMobile {
					splitSource := strings.Split(common.InterfaceToStr(common.InterfaceToStr(v["source"])), ",")
					for i := 0; i < len(splitSource); i++ {
						//
						if (*result)[userId].SourceMap == nil {
							(*result)[userId].SourceMap = map[string]sourceStruct{}
						}
						if _, ok := (*result)[userId].SourceMap[splitSource[i]]; !ok {
							(*result)[userId].SourceMap[splitSource[i]] = sourceStruct{}
						}
						tmp := (*result)[userId].SourceMap[splitSource[i]]
						//浏览总数处理处理
						if common.Int64All(v["isvisit"]) > 0 {
							tmp.BrowseNumb = DataHanle(tmp.BrowseNumb, project_id)
						}
						//推送总数处理
						tmp.PushNumb = DataHanle(tmp.PushNumb, project_id)
						//参标总数处理
						if common.Int64All(v["isparticipate"]) > 0 {
							tmp.ParticipateNumb = DataHanle(tmp.ParticipateNumb, project_id)
						}
						//投标总数处理
						if common.Int64All(v["isbid"]) > 0 {
							tmp.BidNumb = DataHanle(tmp.BidNumb, project_id)
						}
						//中标总数处理
						if common.Int64All(v["win_status"]) != 0 {
							win_status := common.Int64All(v["win_status"])
							if win_status == 1 {
								tmp.WinNumb = DataHanle(tmp.WinNumb, project_id)
							} else {
								delete(tmp.WinNumb, project_id)
							}
						}
						(*result)[userId].SourceMap[splitSource[i]] = tmp
					}

				}
			}
		}
	}
	pushStatisticsList := []*bxcore.PushStatisticsData{}
	if !isManager && !isMobile {
		for _, v := range *result {
			for sourceK, sourceV := range v.SourceMap {
				personName := strings.Split(v.PersonName, "_")[0]
				pushStatisticsList = append(pushStatisticsList, &bxcore.PushStatisticsData{
					PersonName:      personName,
					DepartmentName:  v.DepartmentName,
					EntUserId:       encrypt.SE.Encode2Hex(v.entUserId),
					ParticipateNumb: int64(len(sourceV.ParticipateNumb)),
					BrowseNumb:      int64(len(sourceV.BrowseNumb)),
					BidNumb:         int64(len(sourceV.BidNumb)),
					WinNumb:         int64(len(sourceV.WinNumb)),
					PushNumb:        int64(len(sourceV.PushNumb)),
					Source:          common.InterfaceToStr(SourceMap[sourceK]),
				})
			}
		}
	} else {
		pushStatisticsList = make([]*bxcore.PushStatisticsData, len(*result))
		for _, v := range *result {
			personName := strings.Split(v.PersonName, "_")[0]
			k := common.Int64All(strings.Split(v.PersonName, "_")[1])
			pushStatisticsList[k] = &bxcore.PushStatisticsData{
				PersonName:      personName,
				DepartmentName:  v.DepartmentName,
				EntUserId:       encrypt.SE.Encode2Hex(v.entUserId),
				PushNumb:        common.Int64All(len(v.PushNumb)),
				ParticipateNumb: common.Int64All(len(v.ParticipateNumb)),
				BidNumb:         common.Int64All(len(v.BidNumb)),
				WinNumb:         common.Int64All(len(v.WinNumb)),
				BrowseNumb:      common.Int64All(len(v.BrowseNumb)),
			}
		}
	}
	return pushStatisticsList
}

var stageNameArr = map[int64][]string{
	1: []string{"已报名", "投标决策", "编制投标文件", "递交投标文件", "中标公示", "签合同", "已结束"},
	2: []string{"已报名", "中标公示", "签合同", "已结束"},
}

func ProjectHandle(data *[]map[string]interface{}, users *[]map[string]interface{}, isAdmin bool, bidWay int64) []*bxcore.ProjectStatisticsData {
	result := &map[int64]*ProjectData{}
	for k, v := range *users {
		(*result)[common.Int64All(v["id"])] = &ProjectData{
			PersonName:     fmt.Sprintf("%s_%d", common.InterfaceToStr(v["name"]), k),
			DepartmentName: common.InterfaceToStr(v["dept_name"]),
			entUserId:      common.InterfaceToStr(v["id"]),
		}
	}
	if data != nil && len(*data) > 0 {
		for _, v := range *data {
			userId := int64(0)
			if isAdmin {
				userId = common.Int64All(v["ent_user_id"])
			} else {
				userId = common.Int64All(v["position_id"])
			}
			project_id := common.InterfaceToStr(common.InterfaceToStr(v["project_id"]))
			if (*result)[userId] != nil {
				stage := common.ObjToString(v["bid_stage"])
				if (*result)[userId].StageStr == nil {
					(*result)[userId].StageStr = map[string]string{}
				}
				(*result)[userId].StageStr[project_id] = stage
				isEnd_ := common.IntAll(v["isend"])
				if isEnd_ == 1 {
					if (*result)[userId].EndProject == nil {
						(*result)[userId].EndProject = map[string]struct{}{}
					}
					// 标记成已结束
					(*result)[userId].EndProject[project_id] = struct{}{}
				}
			}

		}
		existProject := map[string]struct{}{}
		for _, v := range *data {
			userId := int64(0)
			if isAdmin {
				userId = common.Int64All(v["ent_user_id"])
			} else {
				userId = common.Int64All(v["position_id"])
			}
			project_id := common.InterfaceToStr(common.InterfaceToStr(v["project_id"]))
			if (*result)[userId] != nil {
				//终止参保统计
				if common.Int64All(v["isend"]) != 0 {
					(*result)[userId].EndNumb = DataHanle((*result)[userId].EndNumb, project_id)
				}
				// 已经终止的不参与统计数量
				if _, ok := (*result)[userId].EndProject[project_id]; ok {
					continue
				}
				//  参标数量
				(*result)[userId].participateProjectNumb = DataHanle((*result)[userId].participateProjectNumb, project_id)
				//投标数量
				if common.Int64All(v["isbid"]) > 0 {
					(*result)[userId].BidNumb = DataHanle((*result)[userId].BidNumb, project_id)
				}
				//直接投标数
				if common.Int64All(v["bid_way"]) > 0 {
					if common.Int64All(v["bid_way"]) == 2 {
						(*result)[userId].ChannelBidNumb = DataHanle((*result)[userId].ChannelBidNumb, project_id)
						delete((*result)[userId].DirectBidNumb, project_id)
					} else {
						(*result)[userId].DirectBidNumb = DataHanle((*result)[userId].DirectBidNumb, project_id)
						delete((*result)[userId].ChannelBidNumb, project_id)
					}
				}
				//中标总数处理
				if common.Int64All(v["win_status"]) != 0 {
					if common.Int64All(v["win_status"]) > 0 {
						//中标数量
						(*result)[userId].WinNumb = DataHanle((*result)[userId].WinNumb, project_id)
						delete((*result)[userId].NotBidNumber, project_id)
					} else {
						//未中标数量
						(*result)[userId].NotBidNumber = DataHanle((*result)[userId].NotBidNumber, project_id)
						delete((*result)[userId].WinNumb, project_id)
					}
				}
				//中标方式处理
				if common.Int64All(v["win_bidway"]) != 0 {
					if common.Int64All(v["win_bidway"]) == 1 {
						//直接投标数量
						(*result)[userId].DirectWinNumb = DataHanle((*result)[userId].DirectWinNumb, project_id)
						delete((*result)[userId].ChannelWinNumb, project_id)
					} else {
						//渠道投标数量
						(*result)[userId].ChannelWinNumb = DataHanle((*result)[userId].ChannelWinNumb, project_id)
						delete((*result)[userId].DirectWinNumb, project_id)
					}
				}

				if bidWay == 0 {
					// 投标类型为全部时不需要统计勾选的数量
					continue
				}
				existKey := fmt.Sprintf("%d_%s", userId, project_id)
				if _, ok := existProject[existKey]; !ok {
					existProject[existKey] = struct{}{}
				} else {
					continue
				}
				// 阶段勾选数量统计
				stage := common.InterfaceToStr((*result)[userId].StageStr[project_id])
				if stage != "" {
					stageSplit := strings.Split(stage, ",")
					if (*result)[userId].Stage == nil {
						(*result)[userId].Stage = map[string]map[string]interface{}{}
					}
					for i := 0; i < len(stageSplit); i++ {
						stageK := stageSplit[i]
						(*result)[userId].Stage[stageK] = DataHanle((*result)[userId].Stage[stageSplit[i]], project_id)
					}
				}
			}
		}
	}
	projectStatisticsList := make([]*bxcore.ProjectStatisticsData, len(*result))

	stageName := []string{}
	if bidWay != 0 {
		stageName = stageNameArr[bidWay]
	}
	for _, v := range *result {
		personName := strings.Split(v.PersonName, "_")[0]
		k := common.Int64All(strings.Split(v.PersonName, "_")[1])
		tmpStage := []*bxcore.StageValue{}
		if bidWay != 0 && len(stageName) > 0 {
			for i := 0; i < len(stageName); i++ {
				name_ := fmt.Sprintf("%s（阶段）", stageName[i])
				if stageV, ok := v.Stage[stageName[i]]; ok {
					tmpStage = append(tmpStage, &bxcore.StageValue{
						Name:  name_,
						Value: fmt.Sprintf("%d", len(stageV)),
					})
				} else {
					tmpStage = append(tmpStage, &bxcore.StageValue{
						Name:  name_,
						Value: "-",
					})
				}
			}
		}
		projectStatisticsList[k] = &bxcore.ProjectStatisticsData{
			PersonName:             personName,
			DepartmentName:         v.DepartmentName,
			EntUserId:              encrypt.SE.Encode2Hex(v.entUserId),
			BidNumb:                common.Int64All(len(v.BidNumb)),
			DirectBidNumb:          common.Int64All(len(v.DirectBidNumb)),
			ChannelBidNumb:         common.Int64All(len(v.ChannelBidNumb)),
			WinNumb:                common.Int64All(len(v.WinNumb)),
			DirectWinNumb:          common.Int64All(len(v.DirectWinNumb)),
			ChannelWinNumb:         common.Int64All(len(v.ChannelWinNumb)),
			NotBidNumber:           common.Int64All(len(v.NotBidNumber)),
			EndNumb:                common.Int64All(len(v.EndNumb)),
			ParticipateProjectNumb: common.Int64All(len(v.participateProjectNumb)),
			Stage:                  tmpStage,
		}
	}
	return projectStatisticsList
}
func EntInfo(entId, entUserId int) *CurrentUser {
	currentUser := &CurrentUser{
		Dept: &Department{},
	}
	user := IC.MainMysql.SelectBySql(`SELECT a.name as user_name from entniche_user a INNER JOIN entniche_user_role b on (a.id=b.user_id) where a.id=? and b.role_id=? limit 1`, entUserId, Role_admin_system)
	if user != nil && len(*user) > 0 {
		currentUser.Role_admin_system = true
		currentUser.User_name, _ = (*user)[0]["user_name"].(string)
		currentUser.User_power = 1
		r := IC.MainMysql.SelectBySql(`SELECT id,name,subdis,nodiff from entniche_department where ent_id=? and pid=0 limit 1`, entId)
		if r != nil && len(*r) == 1 {
			department := JsonUnmarshal((*r)[0], &Department{}).(*Department)
			if department != nil {
				department.Pid = department.Id
				currentUser.Dept = department
			}
		}
	} else {
		//角色、权限
		r := IC.MainMysql.SelectBySql(`SELECT a.name as user_name,a.power as user_power,b.role_id,d.id as dept_id,d.name as dept_name,d.subdis as dept_subdis,d.nodiff as dept_nodiff,e.id as dept_pid from entniche_user a 
			LEFT JOIN entniche_user_role b on (b.user_id=?) 
			INNER JOIN entniche_department_user c on (a.id=? and a.id=c.user_id) 
			INNER JOIN entniche_department d on (c.dept_id=d.id) 
			INNER JOIN entniche_department e on (e.ent_id=? and e.pid=0) 
			order by a.id desc limit 1`, entUserId, entUserId, entId)
		if r != nil && len(*r) == 1 {
			currentUser.User_name, _ = (*r)[0]["user_name"].(string)
			currentUser.User_power = common.IntAll((*r)[0]["user_power"])
			if common.IntAll((*r)[0]["role_id"]) == Role_admin_department {
				currentUser.Role_admin_department = true
			}
			currentUser.Dept.Id = common.IntAll((*r)[0]["dept_id"])
			currentUser.Dept.Pid = common.IntAll((*r)[0]["dept_pid"])
			currentUser.Dept.Name = common.ObjToString((*r)[0]["dept_name"])
			currentUser.Dept.Subdis = common.IntAll((*r)[0]["dept_subdis"])
			currentUser.Dept.Nodiff = common.IntAll((*r)[0]["dept_nodiff"])
		}
	}
	return currentUser
}

// map转结构体
func JsonUnmarshal(m interface{}, s interface{}) interface{} {
	var b []byte
	if v, ok := m.(string); ok {
		b = []byte(v)
	} else if v, ok := m.([]byte); ok {
		b = v
	} else {
		b, _ = json.Marshal(m)
	}
	json.Unmarshal(b, &s)
	return s
}

// 获取部门下可以进行分发的人员(不包含部门名称和部门id)
func GetDisUsers(entId, deptId int) *[]map[string]interface{} {
	r := IC.MainMysql.SelectBySql(`select DISTINCT c.id,c.name,c.phone,c.power,b.dept_id,d.name as dept_name
		from entniche_department_parent a 
		INNER JOIN entniche_department_user b on (b.dept_id=? or (a.pid=? and a.id=b.dept_id)) 
		INNER JOIN entniche_user c on (c.ent_id=? and b.user_id=c.id) 
		INNER JOIN entniche_department d  on  d.id=b.dept_id
		order by b.dept_id , convert(c.name using gbk) COLLATE gbk_chinese_ci asc`, deptId, deptId, entId)
	return r
}
func GetUser(entUserIdArr []string) *[]map[string]interface{} {
	r := IC.MainMysql.SelectBySql("SELECT DISTINCT  a.id,  a.name,  a.phone,  d.id AS dept_id,  d.NAME AS dept_name  " +
		"FROM  entniche_user a " +
		" INNER JOIN entniche_department_user b ON  FIND_IN_SET(a.id,'" + strings.Join(entUserIdArr, ",") +
		"') and  b.user_id = a.id  " +
		" INNER JOIN entniche_department d ON d.id = b.dept_id " +
		" ORDER BY  d.id,  CONVERT ( a.NAME USING gbk ) COLLATE gbk_chinese_ci ASC",
	)
	return r
}

type User struct {
	Id        int
	Name      string //员工姓名
	Mail      string //邮箱
	Phone     string //手机号
	Dept_id   int    //部门id
	Dept_name string //部门名称
	//Role      string //角色
	Power int //权限
}

type CurrentUser struct {
	Role_admin_department bool        //是否是部门管理员
	Role_admin_system     bool        //是否是系统管理员
	Dept                  *Department //部门信息
	BondPhone             string      //手机号
	NickName              string      //昵称
	HeadImageUrl          string      //头像
	PersonalAuth          int         //个人认证
	PersonalAuthReason    string      //个人认证不通过原因
	User_power            int         //是否分配权限
	User_name             string      //用户姓名
}
type Department struct {
	Id         int
	Name       string //部门名
	Pid        int    //上级部门id
	Pname      string //上级部门名称
	Nodiff     int    //全员无差别接收 0：关闭 1：打开
	Subdis     int    //订阅分发 0：关闭 1：打开
	Aid        int    //管理员id
	Aname      string //管理员姓名
	Rname      string //角色名
	User_count int    //该部门下员工的总数
	Dept_count int    //该部门下子部门总数
	Ent_id     int    //公司id
}

func DataHanle(data map[string]interface{}, project_id string) map[string]interface{} {
	if data == nil {
		data = map[string]interface{}{project_id: 1}
	} else {
		data[project_id] = 1
	}
	return data
}
func QueryHandle(isAdmin bool, startTime, endTime int64, personArrStr string, source []int64, bidWay int64) []string {
	//时间处理
	query := []string{}
	if isAdmin {
		//是管理员
		query = append(query, fmt.Sprintf(" ent_user_id in (%s) ", personArrStr))
	} else {
		//不是管理员
		query = append(query, fmt.Sprintf(" position_id = %s ", personArrStr))
	}
	if startTime == 0 && endTime == 0 {
		//没有传时间，默认时间处理
		var start = time.Now().AddDate(0, 0, -30)
		query = append(query, fmt.Sprintf(" ymd >= %s ", start.Format("20060102")))
	}
	if startTime != 0 {
		query = append(query, fmt.Sprintf(" ymd >= %d ", startTime))
	}
	if endTime != 0 {
		query = append(query, fmt.Sprintf(" ymd <= %d ", endTime))
	}
	if len(source) > 0 {
		sourceArr := []string{}
		for i := 0; i < len(source); i++ {
			sourceArr = append(sourceArr, fmt.Sprintf(" FIND_IN_SET('%d', source)", source[i]))
		}
		query = append(query, fmt.Sprintf(" (%s) ", strings.Join(sourceArr, " or ")))
	}
	if bidWay != 0 {
		query = append(query, fmt.Sprintf("bid_way = %d", bidWay))
	}
	return query
}
func (in *ParticipateStatistics) ProjectDetails(entUserIdArr []string, detailReq *bxcore.ProjectDetailsReq) (result bxcore.DetailData) {
	//判断是企业、还是个人
	isEnt, personArrStr, _, _ := in.PersonHandle(entUserIdArr)
	queryType := GetQueryType(detailReq)
	query, countQuery := GetDetailQuery(isEnt, personArrStr, detailReq, queryType)
	totalCount := IC.BaseMysql.CountBySql(countQuery)
	if totalCount <= 0 {
		return
	}
	// 处理数据  这里只是筛选出项目id和阶段信息
	dataList := IC.BaseMysql.SelectBySql(query)
	if dataList == nil || len(*dataList) == 0 {
		return
	}
	// 处理数据 补充项目名称、推送表字段 、格式化数据
	rs := ProjectDetailHandle(detailReq, *dataList)
	result = bxcore.DetailData{
		List:  rs,
		Total: totalCount,
	}
	// 处理数据
	return
}

// 这个查询只用查出符合筛选条件的项目id 以及该项目对应的stage
// 查询类型   1查左边 连右表查stage 2只查右表 3内连接
func GetDetailQuery(isEnt bool, personArrStr string, req *bxcore.ProjectDetailsReq, queryType int) (string, string) {
	// 处理分页
	if req.PageNum == 0 || req.PageSize == 0 {
		req.PageNum = 1
		req.PageSize = 50
	}
	// 这是因为数据库中 0是未参标 1是已参标， 接收参数时和其他默认参数保持一致 0-全部 1 是未参标 2 是已参标
	req.IsParticipate -= 1
	//if queryType == 0 {
	//	// 空搜索调整
	//	query1, query2 := []string{}, []string{}
	//	query3 := ""
	//	//没有传时间，默认时间处理
	//	var start = time.Now().AddDate(0, 0, -10)
	//	query1 = append(query1, fmt.Sprintf(" a.ymd >= %s ", start.Local().Format("20060102")))
	//	query2 = append(query2, fmt.Sprintf(" b.update_date >= '%s' ", start.Local().Format(date.Date_Full_Layout)))
	//	if isEnt {
	//		//是企业版
	//		query1 = append(query1, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
	//		personArr := []string{}
	//		personArrStrSplit := strings.Split(personArrStr, ",")
	//		for i := 0; i < len(personArrStrSplit); i++ {
	//			personArr = append(personArr, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_ids)", personArrStrSplit[i]))
	//		}
	//		if len(personArr) > 0 {
	//			personStr := strings.Join(personArr, " or ")
	//			query2 = append(query2, fmt.Sprintf(" (%s)", personStr))
	//		}
	//		query3 = fmt.Sprintf("b.ent_id='%d'", req.EntId) // 连接时右表的条件
	//	} else {
	//		//不是企业版
	//		query1 = append(query1, fmt.Sprintf(" a.position_id = %s ", personArrStr))
	//		personArr := []string{}
	//		personArrStrSplit := strings.Split(personArrStr, ",")
	//		for i := 0; i < len(personArrStrSplit); i++ {
	//			personArr = append(personArr, fmt.Sprintf(" FIND_IN_SET('%s', b.position_ids)", personArrStrSplit[i]))
	//		}
	//		if len(personArr) > 0 {
	//			personStr := strings.Join(personArr, " or ")
	//			query2 = append(query2, fmt.Sprintf(" (%s)", personStr))
	//		}
	//		query3 = fmt.Sprintf("b.position_ids='%d'", req.PositionId) // 连接时右表的条件
	//	}
	//	q := `SELECT A.project_id, B.stage
	//			FROM
	//			(SELECT DISTINCT(project_id)
	//			FROM
	//				(SELECT project_id FROM participate_push_statistics a
	//				WHERE %s UNION
	//				SELECT project_id
	//				FROM participate_stage_statistics b
	//				WHERE %s) order by project_id
	//			LIMIT %d , %d) A
	//            LEFT JOIN
	//			participate_stage_statistics B ON A.project_id = B.project_id and  %s` // and 连接前对右表过滤
	//	q2 := "select count(project_id) from (select distinct(project_id) from participate_push_statistics a where %s union select project_id from participate_stage_statistics b where %s )"
	//	q1Str := strings.Join(query1, " and ")
	//	q2Str := strings.Join(query2, " and ")
	//	return fmt.Sprintf(q, q1Str, q2Str, (req.PageNum-1)*req.PageSize, req.PageSize, query3), fmt.Sprintf(q2, q1Str, q2Str)
	//}
	var q, qCount string
	query := []string{}
	joinStr := ""
	particiLeftJoin := ""
	if queryType == 1 {
		if isEnt {
			//是企业版
			query = append(query, fmt.Sprintf(" pps.ent_user_id in (%s) ", personArrStr))
			joinStr = fmt.Sprintf("and pss.ent_id = %d", req.EntId)
		} else {
			query = append(query, fmt.Sprintf(" pps.position_id = %s ", personArrStr))
			//不是企业版
			joinStr = fmt.Sprintf("and pss.position_ids =%d", req.PositionId)
		}
		if req.StartTime != 0 {
			query = append(query, fmt.Sprintf(" pps.ymd >= %d ", req.StartTime))
		}
		if req.EndTime != 0 {
			query = append(query, fmt.Sprintf(" pps.ymd <= %d ", req.EndTime))
		}
		if req.StartTime == 0 && req.EndTime == 0 {
			//没有传时间，默认时间处理
			var start = time.Now().AddDate(0, 0, -30)
			query = append(query, fmt.Sprintf(" pps.ymd >= %s ", start.Local().Format("20060102")))
		}
		// 标讯/项目来源
		if len(req.Source) > 0 {
			sourceArr := []string{}
			for i := 0; i < len(req.Source); i++ {
				if req.Source[i] == 0 {
					sourceArr = append(sourceArr, "NOT FIND_IN_SET('3', pps.source)")
				} else {
					sourceArr = append(sourceArr, fmt.Sprintf(" FIND_IN_SET('%d', pps.source)", req.Source[i]))
				}
			}
			query = append(query, fmt.Sprintf(" (%s) ", strings.Join(sourceArr, " or ")))
		}
		//参标状态：-1全部，0未参标、1已参标
		if req.IsParticipate != -1 {
			query = append(query, " (pss.project_id is null or pss.is_participate=0)")
			particiLeftJoin = fmt.Sprintf(" left join participate_stage_statistics pss on  (pps.project_id=pss.project_id  %s)", joinStr)
		}
		q = `select A.project_id, pss.stage from (SELECT project_id, MAX(ymd) as max_ymd
			FROM (
				SELECT DISTINCT pps.project_id, pps.ymd
				FROM participate_push_statistics pps %s
				WHERE %s
			) AS subquery
			GROUP BY project_id
			ORDER BY max_ymd ,project_id DESC limit %d,%d) A left join participate_stage_statistics pss on (A.project_id=pss.project_id  %s);`
		qCount = `SELECT 
					COUNT(DISTINCT (pps.project_id))
				  FROM
					participate_push_statistics pps
					   %s where %s`
		q = fmt.Sprintf(q, particiLeftJoin, strings.Join(query, " and "), (req.PageNum-1)*req.PageSize, req.PageSize, joinStr)
		qCount = fmt.Sprintf(qCount, particiLeftJoin, strings.Join(query, " and "))
		return q, qCount
	} else if queryType == 2 {
		if isEnt {
			//是企业版
			personArr := []string{}
			personArrStrSplit := strings.Split(personArrStr, ",")
			for i := 0; i < len(personArrStrSplit); i++ {
				personArr = append(personArr, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_ids)", personArrStrSplit[i]))
			}
			if len(personArr) > 0 {
				personStr := strings.Join(personArr, " or ")
				query = append(query, fmt.Sprintf("(%s)", personStr))
			}
		} else {
			//不是企业版
			query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.position_ids)", personArrStr))
		}
		//// 无默认时间时
		if req.BidUpdateStartTime == 0 && req.BidUpdateEndTime == 0 {
			var start = time.Now().AddDate(0, 0, -30)
			query = append(query, fmt.Sprintf(" b.update_date >= '%s' ", start.Local().Format(date.Date_Full_Layout)))
		}
		// 参标状态更新时间
		if req.BidUpdateStartTime != 0 {
			bidStart_, err := time.ParseInLocation(date.Date_yyyyMMdd, fmt.Sprintf("%d", req.BidUpdateStartTime), time.Local)
			if err != nil {
				bidStart_ = time.Now().AddDate(0, 0, -30)
				log.Println("时间转换失败,使用默认值：", err)
			}
			bidStart := date.FormatDate(&bidStart_, date.Date_Full_Layout)
			query = append(query, fmt.Sprintf("b.update_date >= '%s'", bidStart))
		}
		if req.BidUpdateEndTime != 0 {
			bidEnd_, err := time.ParseInLocation("20060102 15:04:05", fmt.Sprintf("%d 23:59:59", req.BidUpdateEndTime), time.Local)
			if err != nil {
				bidEnd_ = time.Now().AddDate(0, 0, -30)
				log.Println("时间转换失败,使用默认值：", err)
			}
			bidEnd := date.FormatDate(&bidEnd_, date.Date_Full_Layout)
			query = append(query, fmt.Sprintf("b.update_date <= '%s'", bidEnd))
		}
		if req.BidWay != 0 {
			query = append(query, fmt.Sprintf("b.bid_way = %d", req.BidWay))
		}
		//参标状态：-1全部，0未参标、1已参标
		if req.IsParticipate == 1 {
			query = append(query, fmt.Sprintf("b.is_participate = %d", req.IsParticipate))
		}
		q = "select b.project_id,b.stage    from  participate_stage_statistics b where %s %s order by b.update_date desc"
		qCount = "select count(b.project_id)   from  participate_stage_statistics b where %s %s"
	} else {
		if isEnt {
			//是企业版
			query = append(query, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
			joinStr = "and a.ent_id = b.ent_id"
		} else {
			query = append(query, fmt.Sprintf(" a.position_id = %s ", personArrStr))
			//不是企业版
			// 个人版
			joinStr = "and a.position_id = b.position_ids"
		}
		if req.StartTime != 0 && req.EndTime == 0 && req.BidUpdateStartTime == 0 && req.BidUpdateEndTime == 0 {
			var start = time.Now().AddDate(0, 0, -30)
			query = append(query, fmt.Sprintf(" a.ymd >= %s ", start.Local().Format("20060102")))
		}
		if req.StartTime != 0 {
			query = append(query, fmt.Sprintf(" a.ymd >= %d ", req.StartTime))
		}
		if req.EndTime != 0 {
			query = append(query, fmt.Sprintf(" a.ymd <= %d ", req.EndTime))
		}
		if len(req.Source) > 0 {
			sourceArr := []string{}
			for i := 0; i < len(req.Source); i++ {
				if req.Source[i] == 0 {
					sourceArr = append(sourceArr, "NOT FIND_IN_SET('3', a.source)")
				} else {
					sourceArr = append(sourceArr, fmt.Sprintf(" FIND_IN_SET('%d', a.source)", req.Source[i]))
				}
			}
			query = append(query, fmt.Sprintf(" (%s) ", strings.Join(sourceArr, " or ")))
		}
		//参标状态：-1全部，0未参标、1已参标
		if req.IsParticipate != -1 {
			query = append(query, fmt.Sprintf("a.isparticipate = %d", req.IsParticipate))
		}
		// 投标类型 投标方式；1：直接投标 2：渠道投标',
		if req.BidWay != 0 {
			query = append(query, fmt.Sprintf("b.bid_way = %d", req.BidWay))
		}
		//  参标状态更新时间
		if req.BidUpdateStartTime != 0 {
			bidStart_, err := time.ParseInLocation(date.Date_yyyyMMdd, fmt.Sprintf("%d", req.BidUpdateStartTime), time.Local)
			if err != nil {
				bidStart_ = time.Now().AddDate(0, 0, -30)
				log.Println("时间转换失败,使用默认值：", err)
			}
			bidStart := date.FormatDate(&bidStart_, date.Date_Full_Layout)
			query = append(query, fmt.Sprintf("b.update_date >= '%s'", bidStart))
		}
		if req.BidUpdateEndTime != 0 {
			bidEnd_, err := time.ParseInLocation("20060102 15:04:05", fmt.Sprintf("%d 23:59:59", req.BidUpdateEndTime), time.Local)
			if err != nil {
				bidEnd_ = time.Now().AddDate(0, 0, -30)
				log.Println("时间转换失败,使用默认值：", err)
			}
			bidEnd := date.FormatDate(&bidEnd_, date.Date_Full_Layout)
			query = append(query, fmt.Sprintf("b.update_date <= '%s'", bidEnd))
		}
		q = "select distinct(a.project_id),b.stage,b.update_date   from participate_push_statistics a inner join  participate_stage_statistics b on(b.project_id=a.project_id %s) where %s order by  b.update_date desc"
		qCount = "select count(distinct(a.project_id))   from participate_push_statistics a inner join participate_stage_statistics b on(b.project_id=a.project_id %s) where %s"
	}
	if len(query) > 0 {
		q = fmt.Sprintf(q, joinStr, strings.Join(query, " and "))
		qCount = fmt.Sprintf(qCount, joinStr, strings.Join(query, " and "))
	}
	q = fmt.Sprintf("%s limit %d,%d", q, (req.PageNum-1)*req.PageSize, req.PageSize)
	return q, qCount
}

type PushInfoStruct struct {
	Source       string
	VisitDate    string
	DisDate      string
	IsDistribute int
}

func ProjectDetailHandle(req *bxcore.ProjectDetailsReq, dataList []map[string]interface{}) []*bxcore.ProjectDetailData {
	//dataList 里面包含 项目id、各阶段信息
	// 处理项目名称
	projectIdList := []string{}
	for i := 0; i < len(dataList); i++ {
		projectIdList = append(projectIdList, common.ObjToString(dataList[i]["project_id"]))
	}
	// 项目名称处理成map用于后续使用
	projectNameMap := map[string]string{}
	projectNameRs := es.GetProjectNameByProjectId(projectIdList)
	if projectNameRs != nil && len(*projectNameRs) > 0 {
		for i := 0; i < len(*projectNameRs); i++ {
			projectId_ := common.ObjToString((*projectNameRs)[i]["_id"])
			projectName_ := (*projectNameRs)[i]["projectname"]
			projectNameMap[projectId_] = common.ObjToString(projectName_)
		}
	}
	// 获取推送最新状态
	newPushInfo := getNewPushInfo(projectIdList, req)
	newPushInfoMap := map[string]PushInfoStruct{}
	// 处理推送最新状态
	if newPushInfo != nil && len(*newPushInfo) > 0 {
		for i := 0; i < len(*newPushInfo); i++ {
			project_ := common.ObjToString((*newPushInfo)[i]["project_id"])
			info := PushInfoStruct{
				Source:    common.ObjToString((*newPushInfo)[i]["source"]),
				VisitDate: common.ObjToString((*newPushInfo)[i]["visit_date"]),
				DisDate:   common.ObjToString((*newPushInfo)[i]["dis_date"]),
			}
			newPushInfoMap[project_] = info
		}
	}
	results := []*bxcore.ProjectDetailData{}
	// 处理成最后的数据
	for i := 0; i < len(dataList); i++ {
		projectId := common.ObjToString(dataList[i]["project_id"])
		tmp := bxcore.ProjectDetailData{
			ProjectName: projectNameMap[projectId],
		}
		isDistribute_ := ""
		// 处理推送表相关字段
		if pushInfo_, ok := newPushInfoMap[projectId]; ok {
			sourceStr := []string{}
			sourceExist := map[string]struct{}{}
			if pushInfo_.Source != "" {
				isDistribute_ = "未分发"
				sourceSplit := strings.Split(pushInfo_.Source, ",")
				for j := 0; j < len(sourceSplit); j++ {
					if _, ok := sourceExist[sourceSplit[j]]; ok {
						continue
					}
					sourceExist[sourceSplit[j]] = struct{}{}
					if sourceSplit[j] == "3" {
						isDistribute_ = "已分发"
					}
					if sourceName, ok := SourceMap[sourceSplit[j]]; ok {
						sourceStr = append(sourceStr, sourceName)
					}
				}
			}
			tmp.Source = strings.Join(sourceStr, ",") //  处理成中文
			tmp.ViewDate = pushInfo_.VisitDate
			tmp.IsDistribute = isDistribute_
			tmp.DisDate = pushInfo_.DisDate
		} //
		// 处理阶段勾选信息和参标、终止参标信息
		s := common.ObjToString(dataList[i]["stage"])
		if s == "" {
			s = `[{"name":"参标状态","value":"-","date":""},{"name":"投标类型","value":"-","date":""},{"name":"已报名（阶段）","value":"-","date":""},{"name":"投标决策（阶段）","value":"-","date":""},{"name":"编制投标文件（阶段）","value":"-","date":""},{"name":"递交投标文件（阶段）","value":"-","date":""},{"name":"中标公示（阶段）","value":"-","date":""},{"name":"签合同（阶段）","value":"-","date":""},{"name":"已结束","value":"-","date":""},{"name":"终止参标","value":"-","date":""}]`
		}
		err := json.Unmarshal([]byte(strings.Replace(s, "'", "\"", -1)), &tmp.Stage)
		if err != nil {
			log.Println("stage 反序列失败", err)
		}
		tmp.Id = encrypt.EncodeArticleId2ByCheck(projectId)
		results = append(results, &tmp)
	}
	return results
}

// 获取项目的最新推送状态信息
func getNewPushInfo(projectIds []string, req *bxcore.ProjectDetailsReq) *[]map[string]interface{} {
	q := []string{}
	if req.PositionType == 0 {
		q = append(q, fmt.Sprintf("position_id=%d", req.PositionId))
	} else {
		q = append(q, fmt.Sprintf("ent_id=%d", req.EntId))
	}
	if req.StartTime == 0 && req.EndTime == 0 {
		//没有传时间，默认时间处理
		var start = time.Now().AddDate(0, 0, -30)
		q = append(q, fmt.Sprintf(" ymd >= %s ", start.Local().Format("20060102")))
	}
	if req.StartTime != 0 {
		q = append(q, fmt.Sprintf(" ymd >= %d ", req.StartTime))

	}
	if req.EndTime != 0 {
		q = append(q, fmt.Sprintf(" ymd <= %d ", req.EndTime))

	}
	s := strings.Join(q, " and ")
	sql := `
SELECT 
     project_id,
  GROUP_CONCAT(distinct(source))  as source,
    DATE_FORMAT(min(visit_date), '%%Y.%%m.%%d') AS visit_date,
  DATE_FORMAT( min(dis_date), '%%Y.%%m.%%d') AS dis_date
FROM  participate_push_statistics 
        WHERE
            %s
            AND project_id IN ( "` + strings.Join(projectIds, "\",\"") + `" )
        GROUP BY project_id
`

	query := fmt.Sprintf(sql, s)
	return IC.BaseMysql.SelectBySql(query)
}

// GetQueryType 查询类型    1查左边 连右表查stage 2只查右表 3内连接
// IsParticipate 接收参数时 0 全部 1 未参标 2已参标  数据库中 未参标是0
func GetQueryType(in *bxcore.ProjectDetailsReq) int {
	// 空搜索  查左边  加时间范围
	if in.BidUpdateStartTime == 0 && in.BidUpdateEndTime == 0 && in.StartTime == 0 && in.EndTime == 0 && in.IsParticipate == 0 && in.BidWay == 0 && len(in.Source) == 0 {
		return 1
	}
	if in.IsParticipate == 1 {
		// 未参标只筛选推送表 右表条件无效
		in.BidWay = 0
		in.BidUpdateStartTime = 0
		in.BidUpdateEndTime = 0
		return 1
	}
	if (in.StartTime != 0 || in.EndTime != 0 || len(in.Source) > 0) && (in.BidUpdateStartTime == 0 && in.BidUpdateEndTime == 0 && in.IsParticipate != 2 && in.BidWay == 0) {
		return 1
	}
	if (in.StartTime == 0 && in.EndTime == 0 && len(in.Source) == 0) && (in.BidUpdateStartTime != 0 || in.BidUpdateEndTime == 0 || in.IsParticipate == 2 || in.BidWay != 0) {
		return 2
	}
	return 3
}
