package statistic_report

import (
	"errors"
	"github.com/rdlucklib/rdluck_tools/paging"
	"hongze/hz_crm_api/models"
	"hongze/hz_crm_api/models/data_manage"
	statisticModels "hongze/hz_crm_api/models/statistic_report"
	"hongze/hz_crm_api/models/system"
	"hongze/hz_crm_api/models/yb"
	"hongze/hz_crm_api/utils"
	"strconv"
	"strings"
	"sync"
	"time"
)

// GetYbLogWeekDataNum 周度数据
func GetYbLogWeekDataNum(nowWeekMonday time.Time, productId, productType, dataNum int) (adminDataList []SellerYbLogDataMap, firstDate time.Time, err error) {
	nowWeekSunday := nowWeekMonday.AddDate(0, 0, 7).Add(-1 * time.Second) //本周周日
	wg := sync.WaitGroup{}
	wg.Add(dataNum) //n个协程返回

	chanList := make([]chan SellerYbLogDataMap, 0)
	for i := 0; i < dataNum; i++ {
		tmpCh := make(chan SellerYbLogDataMap, 1)
		chanList = append(chanList, tmpCh)

		lastWeekMonday := nowWeekMonday.AddDate(0, 0, -7*i)
		lastWeekSunday := nowWeekSunday.AddDate(0, 0, -7*i)

		// 第一个开始日期
		firstDate = lastWeekMonday
		go getYbLogSectionData(productId, productType, lastWeekMonday, lastWeekSunday, tmpCh, &wg)
	}

	wg.Wait()
	adminDataList = make([]SellerYbLogDataMap, 0)
	for _, vChan := range chanList {
		var weekCompanyReportDataMap SellerYbLogDataMap
		weekCompanyReportDataMap = <-vChan
		close(vChan)
		adminDataList = append(adminDataList, weekCompanyReportDataMap)
	}

	return
}

// GetYbLogMonthDataNum 月度数据
func GetYbLogMonthDataNum(nowMonthFirstDay time.Time, productId, productType, dataNum int) (adminDataList []SellerYbLogDataMap, firstDate time.Time, err error) { //三个协程返回
	//nowMonthLastDay := nowMonthFirstDay.AddDate(0, 1, 0).Add(-1 * time.Second) //本月最后一天
	wg := sync.WaitGroup{}
	wg.Add(dataNum) //n个协程返回

	chanList := make([]chan SellerYbLogDataMap, 0)

	for i := 0; i < dataNum; i++ {
		tmpCh := make(chan SellerYbLogDataMap, 1)
		chanList = append(chanList, tmpCh)

		lastMonthFirstDay := nowMonthFirstDay.AddDate(0, -1*i, 0)                          //上个月第一天
		lastMonthLastDay := nowMonthFirstDay.AddDate(0, -1*(i-1), 0).Add(-1 * time.Second) //上个月最后一天

		// 第一个开始日期
		firstDate = lastMonthFirstDay
		go getYbLogSectionData(productId, productType, lastMonthFirstDay, lastMonthLastDay, tmpCh, &wg)
	}

	wg.Wait()
	adminDataList = make([]SellerYbLogDataMap, 0)
	for _, vChan := range chanList {
		var weekCompanyReportDataMap SellerYbLogDataMap
		weekCompanyReportDataMap = <-vChan
		close(vChan)
		adminDataList = append(adminDataList, weekCompanyReportDataMap)
	}

	return
}

// SellerYbLogRecordResp 总统计信息
type SellerYbLogRecordResp struct {
	List                     []GroupYbLogRecord     `description:"系统用户分组信息"`
	SellerYbLogRecordNumList []SellerYbLogRecordNum `description:"统计次数"`
}

// GroupYbLogRecord 分组统计信息
type GroupYbLogRecord struct {
	Item                     []AdminYbLogRecord     `description:"系统用户信息"`
	GroupId                  int                    `description:"系统用户分组id"`
	Name                     string                 `description:"分组名"`
	SellerYbLogRecordNumList []SellerYbLogRecordNum `description:"统计次数"`
}

type AdminYbLogRecord struct {
	Name                     string                 `description:"系统用户名"`
	AdminId                  int                    `description:"系统用户id"`
	SellerYbLogRecordNumList []SellerYbLogRecordNum `description:"统计次数"`
}

// SellerYbLogRecordNum 系统用户统计信息
type SellerYbLogRecordNum struct {
	TryOutNum int    `description:"试用客户数"`
	TryOutIds string `description:"试用客户ids"`
	FormalNum int    `description:"正式客户数"`
	FormalIds string `description:"正式客户ids"`
	AllNum    int    `description:"合计客户数"`
	AllIds    string `description:"合计客户数ids"`
	StartDate string `description:"开始日期"`
	EndDate   string `description:"结束日期"`
}

type SellerYbLogDataMap struct {
	TryOutMap   map[int]int    `description:"试用客户数"`
	TryOutIdMap map[int]string `description:"试用客户ids"`
	FormalMap   map[int]int    `description:"正式客户数"`
	FormalIdMap map[int]string `description:"正式客户ids"`
	AllMap      map[int]int    `description:"合计客户数"`
	AllIdMap    map[int]string `description:"合计客户数ids"`
	StartDate   string         `description:"开始日期"`
	EndDate     string         `description:"开始日期"`
}

// getYbLogSectionData 获取周期数据
func getYbLogSectionData(productId, productType int, startDate, endDate time.Time, ch chan SellerYbLogDataMap, wg *sync.WaitGroup) (adminDataMap SellerYbLogDataMap, err error) {
	defer func() {
		ch <- adminDataMap
		wg.Done()
	}()
	tryOutMap := make(map[int]int)
	formalMap := make(map[int]int)
	allMap := make(map[int]int)

	tryOutIdMap := make(map[int]string)
	formalIdMap := make(map[int]string)
	allIdMap := make(map[int]string)
	//正式客户
	{
		data, tmpErr := yb.GetSellerYbProductCountByProductType(productId, productType, "正式", startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		for _, v := range data {
			formalMap[v.SellerId] = v.Num
			formalIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
			allMap[v.SellerId] = v.Num
			allIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
		}
	}

	//试用客户
	{
		data, tmpErr := yb.GetSellerYbProductCountByProductType(productId, productType, "试用", startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		for _, v := range data {
			tryOutMap[v.SellerId] = v.Num
			tryOutIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
			allMap[v.SellerId] += v.Num
			allIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
		}
	}

	adminDataMap = SellerYbLogDataMap{
		TryOutMap:   tryOutMap,
		TryOutIdMap: tryOutIdMap,
		FormalMap:   formalMap,
		FormalIdMap: formalIdMap,
		AllMap:      allMap,
		AllIdMap:    allIdMap,
		StartDate:   startDate.Format(utils.FormatDate),
		EndDate:     endDate.Format(utils.FormatDate),
	}
	return
}

// YbProductUserList 分产品阅读统计用户详情
func YbProductUserList(sysUser *system.Admin, req yb.SellerYbUserLogReq) (resp YbProductUserListResp, err error, errMsg string) {
	// 分组查询用户的日志详情
	pageSize := req.PageSize
	currentIndex := req.CurrentIndex
	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	//排序参数
	sortParam := req.SortParam

	var total int64
	page := paging.GetPaging(currentIndex, pageSize, int(total))

	// 校验入参
	sellerIds := "(" + req.SellerIds + ")"
	startDate, _ := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
	endDateTmp, _ := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
	endDate := endDateTmp.AddDate(0, 0, 1)
	orderStr := ""
	if req.SortParam == "ybUserLog" {
		sortParam = ""
		//按照用户的点击量来排序
		if req.SortType == "" {
			req.SortType = "desc"
		}
		orderStr = " order by num " + req.SortType
	}
	userLogList, total, err := yb.GetSellerYbProductUserCountByProductType(req.ProductId, req.ProductType, req.CompanyStatus, startDate, endDate, sellerIds, startSize, pageSize, orderStr)
	if err != nil {
		errMsg = "查询用户点击量失败， Err: " + err.Error()
		err = errors.New("查询用户点击量失败")
		return
	}
	// 根据company_id，处理排序入参，特殊处理按照company_id 排序的情况，得到 company_list
	companyIds := ""
	userCompanyMap := make(map[int]*yb.SellerYbProductUserCount, 0)
	for _, v := range userLogList {
		companyIds += strconv.Itoa(v.CompanyId) + ","
		userCompanyMap[v.CompanyId] = v
	}

	companyReq := statisticModels.IncrementalCompanyListReq{
		PageSize:     req.PageSize * 10,
		CurrentIndex: 1,
		SortParam:    sortParam,
		SortType:     req.SortType,
		CompanyIds:   strings.Trim(companyIds, ","),
	}

	companyResp, err, errMsg := CompanyList(sysUser, companyReq)
	if err != nil {
		return
	}
	// 绑定 company_id和company详情
	companyFullMap := make(map[int]*CompanyListItem)
	for _, v := range companyResp.List {
		companyFullMap[v.CompanyId] = v
	}

	// 如果按照用户点击量排序，则先遍历user_id，再遍历company_id
	tmpList := make([]*YbProductUserListItem, 0)
	list := make([]*YbProductUserListItem, 0)
	for _, v := range userLogList {
		tmp := new(YbProductUserListItem)
		if full, ok := companyFullMap[v.CompanyId]; ok {
			tmp.CompanyId = full.CompanyId
			tmp.CompanyName = full.CompanyName
			tmp.CreditCode = full.CreditCode
			tmp.CompanyCode = full.CompanyCode
			tmp.StartDate = full.StartDate
			tmp.EndDate = full.EndDate
			tmp.LoseReason = full.LoseReason
			tmp.RenewalReason = full.RenewalReason
			tmp.FreezeReason = full.FreezeReason
			tmp.LossTime = full.LossTime
			tmp.Status = full.Status
			tmp.CompanyType = full.CompanyType
			tmp.ApproveStatus = full.ApproveStatus
			tmp.SellerName = full.SellerName
			tmp.SellerId = full.SellerId
			tmp.SellerIds = full.SellerIds
			tmp.FiccPackageType = full.FiccPackageType
			tmp.ExpireDay = full.ExpireDay
			tmp.FreezeTime = full.FreezeTime
			tmp.GroupId = full.GroupId
			tmp.GroupIds = full.GroupIds
			tmp.DepartmentId = full.DepartmentId
			tmp.IndustryName = full.IndustryName
			tmp.IsSuspend = full.IsSuspend
			tmp.CreatedTime = full.CreatedTime
			tmp.Source = full.Source
			tmp.Province = full.Province
			tmp.City = full.City
			tmp.Address = full.Address
			tmp.Reasons = full.Reasons
			tmp.FreezeStartDate = full.FreezeStartDate
			tmp.FreezeEndDate = full.FreezeEndDate
			tmp.FreezeExpireDays = full.FreezeExpireDays
			tmp.ProductId = full.ProductId
			tmp.FormalTime = full.FormalTime
			tmp.IsShared = full.IsShared
			tmp.RegionType = full.RegionType
			tmp.FiccView = full.FiccView
			tmp.RaiView = full.RaiView
			tmp.FiccLastViewTime = full.FiccLastViewTime
			tmp.RaiLastViewTime = full.RaiLastViewTime
			tmp.RoadShowTotal = full.RoadShowTotal
			tmp.TodoStatus = full.TodoStatus
			tmp.CanConfirm = full.CanConfirm
			tmp.HiddenConfirm = full.HiddenConfirm
			tmp.HiddenCreate = full.HiddenCreate
			tmp.TodoButtonColor = full.TodoButtonColor
			tmp.AllViewTotal = full.AllViewTotal
			tmp.Deadline = full.Deadline
			tmp.IsShow = full.IsShow
			tmp.TryStageSlice = full.TryStageSlice
		} else {
			tmp.CompanyId = v.CompanyId
			tmp.CompanyName = v.CompanyName
			tmp.Status = v.CompanyStatus
		}
		tmp.OldUserId = v.UserId
		tmp.OldRealName = v.RealName
		tmp.YbLogNum = v.Num
		tmpList = append(tmpList, tmp)
	}

	if req.SortParam == "ybUserLog" {
		list = tmpList
	} else {
		//处理company被删的数据的排序
		simpleList := make([]*YbProductUserListItem, 0)
		for _, v := range tmpList {
			if _, ok := companyFullMap[v.CompanyId]; !ok {
				simpleList = append(simpleList, v)
			}
		}
		if req.SortType == "asc" {
			list = append(list, simpleList...)
		}
		// 如果是普通排序，先遍历company_id, 再遍历user_id, 放到最终的数组中
		for _, v := range companyResp.List {
			for _, uv := range tmpList {
				if uv.CompanyId == v.CompanyId {
					list = append(list, uv)
				}
			}
		}

		if req.SortType == "desc" || req.SortType == "" {
			list = append(list, simpleList...)
		}
	}
	page = paging.GetPaging(currentIndex, pageSize, int(total))
	resp.List = list
	resp.Paging = page
	return
}

// GetCollectLogWeekDataNum 收藏统计-周度
func GetCollectLogWeekDataNum(nowWeekMonday time.Time, dataNum int) (adminDataList []SellerYbLogDataMap, firstDate time.Time, err error) {
	nowWeekSunday := nowWeekMonday.AddDate(0, 0, 7).Add(-1 * time.Second) //本周周日
	wg := sync.WaitGroup{}
	wg.Add(dataNum) //n个协程返回

	chanList := make([]chan SellerYbLogDataMap, 0)
	for i := 0; i < dataNum; i++ {
		tmpCh := make(chan SellerYbLogDataMap, 1)
		chanList = append(chanList, tmpCh)

		lastWeekMonday := nowWeekMonday.AddDate(0, 0, -7*i)
		lastWeekSunday := nowWeekSunday.AddDate(0, 0, -7*i)

		// 第一个开始日期
		firstDate = lastWeekMonday
		go getCollectLogSectionData(lastWeekMonday, lastWeekSunday, tmpCh, &wg)
	}

	wg.Wait()
	adminDataList = make([]SellerYbLogDataMap, 0)
	for _, vChan := range chanList {
		var weekCompanyReportDataMap SellerYbLogDataMap
		weekCompanyReportDataMap = <-vChan
		close(vChan)
		adminDataList = append(adminDataList, weekCompanyReportDataMap)
	}

	return
}

// GetCollectLogMonthDataNum 月度数据
func GetCollectLogMonthDataNum(nowMonthFirstDay time.Time, dataNum int) (adminDataList []SellerYbLogDataMap, firstDate time.Time, err error) { //三个协程返回
	//nowMonthLastDay := nowMonthFirstDay.AddDate(0, 1, 0).Add(-1 * time.Second) //本月最后一天
	wg := sync.WaitGroup{}
	wg.Add(dataNum) //n个协程返回

	chanList := make([]chan SellerYbLogDataMap, 0)

	for i := 0; i < dataNum; i++ {
		tmpCh := make(chan SellerYbLogDataMap, 1)
		chanList = append(chanList, tmpCh)

		lastMonthFirstDay := nowMonthFirstDay.AddDate(0, -1*i, 0)                          //上个月第一天
		lastMonthLastDay := nowMonthFirstDay.AddDate(0, -1*(i-1), 0).Add(-1 * time.Second) //上个月最后一天

		// 第一个开始日期
		firstDate = lastMonthFirstDay
		go getCollectLogSectionData(lastMonthFirstDay, lastMonthLastDay, tmpCh, &wg)
	}

	wg.Wait()
	adminDataList = make([]SellerYbLogDataMap, 0)
	for _, vChan := range chanList {
		var weekCompanyReportDataMap SellerYbLogDataMap
		weekCompanyReportDataMap = <-vChan
		close(vChan)
		adminDataList = append(adminDataList, weekCompanyReportDataMap)
	}

	return
}

// getCollectLogSectionData 获取收藏统计周期数据
func getCollectLogSectionData(startDate, endDate time.Time, ch chan SellerYbLogDataMap, wg *sync.WaitGroup) (adminDataMap SellerYbLogDataMap, err error) {
	defer func() {
		ch <- adminDataMap
		wg.Done()
	}()
	tryOutMap := make(map[int]int)
	formalMap := make(map[int]int)
	allMap := make(map[int]int)

	tryOutIdMap := make(map[int]string)
	formalIdMap := make(map[int]string)
	allIdMap := make(map[int]string)
	//正式客户
	{
		data, tmpErr := yb.GetSellerCollectCountByCompanyStatus("正式", startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		for _, v := range data {
			formalMap[v.SellerId] = v.Num
			formalIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
			allMap[v.SellerId] = v.Num
			allIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
		}
	}

	//试用客户
	{
		data, tmpErr := yb.GetSellerCollectCountByCompanyStatus("试用", startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		for _, v := range data {
			tryOutMap[v.SellerId] = v.Num
			tryOutIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
			allMap[v.SellerId] += v.Num
			allIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
		}
	}

	adminDataMap = SellerYbLogDataMap{
		TryOutMap:   tryOutMap,
		TryOutIdMap: tryOutIdMap,
		FormalMap:   formalMap,
		FormalIdMap: formalIdMap,
		AllMap:      allMap,
		AllIdMap:    allIdMap,
		StartDate:   startDate.Format(utils.FormatDate),
		EndDate:     endDate.Format(utils.FormatDate),
	}
	return
}

// YbCollectUserList 收藏统计用户详情
func YbCollectUserList(sysUser *system.Admin, req yb.SellerCollectUserLogReq) (resp YbCollectUserListResp, err error, errMsg string) {
	// 分组查询用户的日志详情
	pageSize := req.PageSize
	currentIndex := req.CurrentIndex
	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	//排序参数
	sortParam := req.SortParam

	var total int64
	page := paging.GetPaging(currentIndex, pageSize, int(total))

	// 校验入参
	sellerIds := "(" + req.SellerIds + ")"
	startDate, _ := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
	endDateTmp, _ := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
	endDate := endDateTmp.AddDate(0, 0, 1)
	orderStr := ""
	if req.SortParam == "ybCollectLog" {
		sortParam = ""
		//按照用户的点击量来排序
		if req.SortType == "" {
			req.SortType = "desc"
		}
		orderStr = " order by num " + req.SortType
	}
	userCollectList, total, err := yb.GetSellerUserCollectCountByCompanyStatus(req.CompanyStatus, startDate, endDate, sellerIds, startSize, pageSize, orderStr)
	if err != nil {
		errMsg = "查询用户收藏量失败， Err: " + err.Error()
		err = errors.New("查询用户收藏量失败")
		return
	}
	// 根据company_id，处理排序入参，特殊处理按照company_id 排序的情况，得到 company_list
	companyIds := ""
	userCompanyMap := make(map[int]*yb.SellerCollectCountListItem, 0)
	for _, v := range userCollectList {
		companyIds += strconv.Itoa(v.CompanyId) + ","
		userCompanyMap[v.CompanyId] = v
	}

	companyReq := statisticModels.IncrementalCompanyListReq{
		PageSize:     req.PageSize * 10,
		CurrentIndex: 1,
		SortParam:    sortParam,
		SortType:     req.SortType,
		CompanyIds:   strings.Trim(companyIds, ","),
	}

	companyResp, err, errMsg := CompanyList(sysUser, companyReq)
	if err != nil {
		return
	}
	// 绑定 company_id和company详情
	companyFullMap := make(map[int]*CompanyListItem)
	for _, v := range companyResp.List {
		companyFullMap[v.CompanyId] = v
	}

	// 如果按照用户点击量排序，则先遍历user_id，再遍历company_id
	tmpList := make([]*YbCollectUserListItem, 0)
	list := make([]*YbCollectUserListItem, 0)
	for _, v := range userCollectList {
		tmp := new(YbCollectUserListItem)
		if full, ok := companyFullMap[v.CompanyId]; ok {
			tmp.CompanyId = full.CompanyId
			tmp.CompanyName = full.CompanyName
			tmp.CreditCode = full.CreditCode
			tmp.CompanyCode = full.CompanyCode
			tmp.StartDate = full.StartDate
			tmp.EndDate = full.EndDate
			tmp.LoseReason = full.LoseReason
			tmp.RenewalReason = full.RenewalReason
			tmp.FreezeReason = full.FreezeReason
			tmp.LossTime = full.LossTime
			tmp.Status = full.Status
			tmp.CompanyType = full.CompanyType
			tmp.ApproveStatus = full.ApproveStatus
			tmp.SellerName = full.SellerName
			tmp.SellerId = full.SellerId
			tmp.SellerIds = full.SellerIds
			tmp.FiccPackageType = full.FiccPackageType
			tmp.ExpireDay = full.ExpireDay
			tmp.FreezeTime = full.FreezeTime
			tmp.GroupId = full.GroupId
			tmp.GroupIds = full.GroupIds
			tmp.DepartmentId = full.DepartmentId
			tmp.IndustryName = full.IndustryName
			tmp.IsSuspend = full.IsSuspend
			tmp.CreatedTime = full.CreatedTime
			tmp.Source = full.Source
			tmp.Province = full.Province
			tmp.City = full.City
			tmp.Address = full.Address
			tmp.Reasons = full.Reasons
			tmp.FreezeStartDate = full.FreezeStartDate
			tmp.FreezeEndDate = full.FreezeEndDate
			tmp.FreezeExpireDays = full.FreezeExpireDays
			tmp.ProductId = full.ProductId
			tmp.FormalTime = full.FormalTime
			tmp.IsShared = full.IsShared
			tmp.RegionType = full.RegionType
			tmp.FiccView = full.FiccView
			tmp.RaiView = full.RaiView
			tmp.FiccLastViewTime = full.FiccLastViewTime
			tmp.RaiLastViewTime = full.RaiLastViewTime
			tmp.RoadShowTotal = full.RoadShowTotal
			tmp.TodoStatus = full.TodoStatus
			tmp.CanConfirm = full.CanConfirm
			tmp.HiddenConfirm = full.HiddenConfirm
			tmp.HiddenCreate = full.HiddenCreate
			tmp.TodoButtonColor = full.TodoButtonColor
			tmp.AllViewTotal = full.AllViewTotal
			tmp.Deadline = full.Deadline
			tmp.IsShow = full.IsShow
			tmp.TryStageSlice = full.TryStageSlice
		} else {
			tmp.CompanyId = v.CompanyId
			tmp.CompanyName = v.CompanyName
			tmp.Status = v.CompanyStatus
		}
		tmp.OldUserId = v.UserId
		tmp.OldRealName = v.RealName
		tmp.CollectNum = v.Num
		tmpList = append(tmpList, tmp)
	}

	if req.SortParam == "ybCollectLog" {
		list = tmpList
	} else {
		//处理company被删的数据的排序
		simpleList := make([]*YbCollectUserListItem, 0)
		for _, v := range tmpList {
			if _, ok := companyFullMap[v.CompanyId]; !ok {
				simpleList = append(simpleList, v)
			}
		}
		if req.SortType == "asc" {
			list = append(list, simpleList...)
		}
		// 如果是普通排序，先遍历company_id, 再遍历user_id, 放到最终的数组中
		for _, v := range companyResp.List {
			for _, uv := range tmpList {
				if uv.CompanyId == v.CompanyId {
					list = append(list, uv)
				}
			}
		}

		if req.SortType == "desc" || req.SortType == "" {
			list = append(list, simpleList...)
		}
	}
	page = paging.GetPaging(currentIndex, pageSize, int(total))
	resp.List = list
	resp.Paging = page
	return
}

// YbCollectList 收藏详情
func YbCollectList(sysUser *system.Admin, req yb.CollectListReq) (resp CollectListResp, err error, errMsg string) {
	// 分组查询用户的日志详情
	pageSize := req.PageSize
	currentIndex := req.CurrentIndex
	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	var total int64
	var condition string
	pars := make([]interface{}, 0)
	page := paging.GetPaging(currentIndex, pageSize, int(total))

	// 校验入参
	if req.SellerIds != "" {
		condition += " and seller_id in (" + req.SellerIds + ")"
	}

	if req.StartDate != "" {
		startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if e != nil {
			errMsg = "起始时间格式错误， Err: " + e.Error()
			err = errors.New("起始时间格式错误")
			return
		}
		condition += " and create_time >= ?"
		pars = append(pars, startDate)
	}

	if req.EndDate != "" {
		endDateTmp, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if e != nil {
			errMsg = "截止时间格式错误， Err: " + e.Error()
			err = errors.New("截止时间格式错误")
			return
		}
		endDate := endDateTmp.AddDate(0, 0, 1)
		condition += " and create_time <= ?"
		pars = append(pars, endDate)
	}

	if req.CompanyStatus != "" {
		condition += " and company_status =?"
		pars = append(pars, req.CompanyStatus)
	}

	if req.UserId != 0 {
		condition += " and user_id =?"
		pars = append(pars, req.UserId)
	}

	if req.CollectionType != "" {
		condition += " and collection_type =?"
		pars = append(pars, req.CollectionType)
	}

	collections, total, err := yb.GetYbUserCollectionByCondition(condition, pars, startSize, pageSize)
	if err != nil {
		errMsg = "查询用户收藏量失败， Err: " + err.Error()
		err = errors.New("查询用户收藏量失败")
		return
	}
	// 遍历收藏列表取出各类型的ID
	reportIds := ""
	chapterIds := ""
	videoIds := make([]int, 0)
	roadVideoIds := make([]int, 0)
	for i := range collections {
		switch collections[i].CollectionType {
		case yb.CollectionTypeReport:
			if collections[i].ExtendId > 0 {
				chapterIds += strconv.Itoa(int(collections[i].ExtendId)) + ","
			} else {
				reportIds += strconv.Itoa(int(collections[i].PrimaryId)) + ","
			}
		case yb.CollectionTypeVideo:
			videoIds = append(videoIds, int(collections[i].PrimaryId))
		case yb.CollectionTypeRoadVideo:
			roadVideoIds = append(roadVideoIds, int(collections[i].PrimaryId))
		}
	}

	// 查询相应收藏类型详情
	var chapterErr, reportErr, videoErr, roadVideoErr error
	chapterMap := make(map[int]*models.ReportChapter, 0)
	reportMap := make(map[int]*models.ReportDetail, 0)
	videoMap := make(map[int]*yb.CommunityVideo, 0)
	roadVideoMap := make(map[int]*yb.RoadVideo, 0)

	wg := sync.WaitGroup{}

	if chapterIds != "" {
		// 章节
		wg.Add(1)
		go func() {
			defer wg.Done()
			chapterIds = strings.Trim(chapterIds, ",")
			chapters, e := models.GetChapterSimpleListByChapterIds(chapterIds)
			if e != nil {
				chapterErr = errors.New("获取章节失败, Err: " + e.Error())
				return
			}
			for i := range chapters {
				chapterMap[chapters[i].ReportChapterId] = chapters[i]
			}
		}()
	}

	if reportIds != "" {
		wg.Add(1)
		go func() {
			defer wg.Done()

			reportIds = "(" + strings.Trim(reportIds, ",") + ")"
			reports, e := models.GetReportByIds(reportIds)
			if e != nil {
				reportErr = errors.New("获取报告失败, Err: " + e.Error())
				return
			}
			for i := range reports {
				reportMap[reports[i].Id] = reports[i]
			}
		}()
	}

	if len(videoIds) > 0 {
		// 视频
		wg.Add(1)
		go func() {
			defer wg.Done()
			videos, e := yb.GetCommunityVideoListByIds(videoIds)
			if e != nil {
				videoErr = errors.New("获取视频失败, Err: " + e.Error())
				return
			}
			for i := range videos {
				videoMap[videos[i].CommunityVideoId] = videos[i]
			}
		}()
	}
	if len(roadVideoIds) > 0 {
		// 视频
		wg.Add(1)
		go func() {
			defer wg.Done()
			roadVideos, e := yb.GetRoadVideoListByIds(roadVideoIds)
			if e != nil {
				roadVideoErr = errors.New("获取视频失败, Err: " + e.Error())
				return
			}
			for i := range roadVideos {
				roadVideoMap[roadVideos[i].RoadVideoId] = roadVideos[i]
			}
		}()
	}
	wg.Wait()

	if chapterErr != nil {
		err = chapterErr
		return
	}
	if reportErr != nil {
		err = reportErr
		return
	}
	if videoErr != nil {
		err = videoErr
		return
	}
	if roadVideoErr != nil {
		err = roadVideoErr
		return
	}

	list := make([]*CollectListItem, 0)
	for i := range collections {
		v := &CollectListItem{
			CollectionId:   collections[i].CollectionId,
			CollectionType: collections[i].CollectionType,
			UserId:         collections[i].UserId,
			ModifyTime:     collections[i].ModifyTime.Format(utils.FormatDateTime),
		}
		// 收藏类型：1-研报; 2-视频社区; 3-微路演视频
		switch collections[i].CollectionType {
		case yb.CollectionTypeReport:
			// 晨周报章节
			if collections[i].ExtendId > 0 {
				if d, ok := chapterMap[int(collections[i].ExtendId)]; ok {
					v.Title = d.Title
				}
			} else {
				if d, ok := reportMap[int(collections[i].PrimaryId)]; ok {
					v.Title = d.Title
				}
			}
		case yb.CollectionTypeVideo:
			if d, ok := videoMap[int(collections[i].PrimaryId)]; ok {
				v.Title = d.Title
			}
		case yb.CollectionTypeRoadVideo:
			if d, ok := roadVideoMap[int(collections[i].PrimaryId)]; ok {
				v.Title = d.Title
			}
		default:
			break
		}
		list = append(list, v)
	}
	page = paging.GetPaging(currentIndex, pageSize, int(total))
	resp.List = list
	resp.Paging = page
	return
}

// getYbChartCollectLogSectionData 获取图收藏统计周期数据
func getYbChartCollectLogSectionData(startDate, endDate time.Time, ch chan SellerYbLogDataMap, wg *sync.WaitGroup) (adminDataMap SellerYbLogDataMap, err error) {
	defer func() {
		ch <- adminDataMap
		wg.Done()
	}()
	tryOutMap := make(map[int]int)
	formalMap := make(map[int]int)
	allMap := make(map[int]int)

	tryOutIdMap := make(map[int]string)
	formalIdMap := make(map[int]string)
	allIdMap := make(map[int]string)
	//正式客户
	{
		data, tmpErr := yb.GetSellerChartCollectCountByCompanyStatus("正式", startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		for _, v := range data {
			formalMap[v.SellerId] = v.Num
			formalIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
			allMap[v.SellerId] = v.Num
			allIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
		}
	}

	//试用客户
	{
		data, tmpErr := yb.GetSellerChartCollectCountByCompanyStatus("试用", startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		for _, v := range data {
			tryOutMap[v.SellerId] = v.Num
			tryOutIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
			allMap[v.SellerId] += v.Num
			allIdMap[v.SellerId] = strconv.Itoa(v.SellerId)
		}
	}

	adminDataMap = SellerYbLogDataMap{
		TryOutMap:   tryOutMap,
		TryOutIdMap: tryOutIdMap,
		FormalMap:   formalMap,
		FormalIdMap: formalIdMap,
		AllMap:      allMap,
		AllIdMap:    allIdMap,
		StartDate:   startDate.Format(utils.FormatDate),
		EndDate:     endDate.Format(utils.FormatDate),
	}
	return
}

// GetYbChartCollectLogWeekDataNum 图收藏统计-周度
func GetYbChartCollectLogWeekDataNum(nowWeekMonday time.Time, dataNum int) (adminDataList []SellerYbLogDataMap, firstDate time.Time, err error) {
	nowWeekSunday := nowWeekMonday.AddDate(0, 0, 7).Add(-1 * time.Second) //本周周日
	wg := sync.WaitGroup{}
	wg.Add(dataNum) //n个协程返回

	chanList := make([]chan SellerYbLogDataMap, 0)
	for i := 0; i < dataNum; i++ {
		tmpCh := make(chan SellerYbLogDataMap, 1)
		chanList = append(chanList, tmpCh)

		lastWeekMonday := nowWeekMonday.AddDate(0, 0, -7*i)
		lastWeekSunday := nowWeekSunday.AddDate(0, 0, -7*i)

		// 第一个开始日期
		firstDate = lastWeekMonday
		go getYbChartCollectLogSectionData(lastWeekMonday, lastWeekSunday, tmpCh, &wg)
	}

	wg.Wait()
	adminDataList = make([]SellerYbLogDataMap, 0)
	for _, vChan := range chanList {
		var weekCompanyReportDataMap SellerYbLogDataMap
		weekCompanyReportDataMap = <-vChan
		close(vChan)
		adminDataList = append(adminDataList, weekCompanyReportDataMap)
	}

	return
}

// GetYbChartCollectLogMonthDataNum 月度数据
func GetYbChartCollectLogMonthDataNum(nowMonthFirstDay time.Time, dataNum int) (adminDataList []SellerYbLogDataMap, firstDate time.Time, err error) { //三个协程返回
	//nowMonthLastDay := nowMonthFirstDay.AddDate(0, 1, 0).Add(-1 * time.Second) //本月最后一天
	wg := sync.WaitGroup{}
	wg.Add(dataNum) //n个协程返回

	chanList := make([]chan SellerYbLogDataMap, 0)

	for i := 0; i < dataNum; i++ {
		tmpCh := make(chan SellerYbLogDataMap, 1)
		chanList = append(chanList, tmpCh)

		lastMonthFirstDay := nowMonthFirstDay.AddDate(0, -1*i, 0)                          //上个月第一天
		lastMonthLastDay := nowMonthFirstDay.AddDate(0, -1*(i-1), 0).Add(-1 * time.Second) //上个月最后一天

		// 第一个开始日期
		firstDate = lastMonthFirstDay
		go getYbChartCollectLogSectionData(lastMonthFirstDay, lastMonthLastDay, tmpCh, &wg)
	}

	wg.Wait()
	adminDataList = make([]SellerYbLogDataMap, 0)
	for _, vChan := range chanList {
		var weekCompanyReportDataMap SellerYbLogDataMap
		weekCompanyReportDataMap = <-vChan
		close(vChan)
		adminDataList = append(adminDataList, weekCompanyReportDataMap)
	}

	return
}

// YbChartCollectUserList 图收藏统计用户详情
func YbChartCollectUserList(sysUser *system.Admin, req yb.SellerChartCollectUserLogReq) (resp YbCollectUserListResp, err error, errMsg string) {
	// 分组查询用户的日志详情
	pageSize := req.PageSize
	currentIndex := req.CurrentIndex
	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	//排序参数
	sortParam := req.SortParam

	var total int64
	page := paging.GetPaging(currentIndex, pageSize, int(total))

	// 校验入参
	sellerIds := "(" + req.SellerIds + ")"
	startDate, _ := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
	endDateTmp, _ := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
	endDate := endDateTmp.AddDate(0, 0, 1)
	orderStr := ""
	if req.SortParam == "ybCollectLog" {
		sortParam = ""
		//按照用户的点击量来排序
		if req.SortType == "" {
			req.SortType = "desc"
		}
		orderStr = " order by num " + req.SortType
	}
	userCollectList, total, err := yb.GetSellerUserChartCollectCountByCompanyStatus(req.CompanyStatus, startDate, endDate, sellerIds, startSize, pageSize, orderStr)
	if err != nil {
		errMsg = "查询用户收藏量失败， Err: " + err.Error()
		err = errors.New("查询用户收藏量失败")
		return
	}
	// 根据company_id，处理排序入参，特殊处理按照company_id 排序的情况，得到 company_list
	companyIds := ""
	userCompanyMap := make(map[int]*yb.SellerChartCollectCountListItem, 0)
	for _, v := range userCollectList {
		companyIds += strconv.Itoa(v.CompanyId) + ","
		userCompanyMap[v.CompanyId] = v
	}

	companyReq := statisticModels.IncrementalCompanyListReq{
		PageSize:     req.PageSize * 10,
		CurrentIndex: 1,
		SortParam:    sortParam,
		SortType:     req.SortType,
		CompanyIds:   strings.Trim(companyIds, ","),
	}

	companyResp, err, errMsg := CompanyList(sysUser, companyReq)
	if err != nil {
		return
	}
	// 绑定 company_id和company详情
	companyFullMap := make(map[int]*CompanyListItem)
	for _, v := range companyResp.List {
		companyFullMap[v.CompanyId] = v
	}

	// 如果按照用户点击量排序，则先遍历user_id，再遍历company_id
	tmpList := make([]*YbCollectUserListItem, 0)
	list := make([]*YbCollectUserListItem, 0)
	for _, v := range userCollectList {
		tmp := new(YbCollectUserListItem)
		if full, ok := companyFullMap[v.CompanyId]; ok {
			tmp.CompanyId = full.CompanyId
			tmp.CompanyName = full.CompanyName
			tmp.CreditCode = full.CreditCode
			tmp.CompanyCode = full.CompanyCode
			tmp.StartDate = full.StartDate
			tmp.EndDate = full.EndDate
			tmp.LoseReason = full.LoseReason
			tmp.RenewalReason = full.RenewalReason
			tmp.FreezeReason = full.FreezeReason
			tmp.LossTime = full.LossTime
			tmp.Status = full.Status
			tmp.CompanyType = full.CompanyType
			tmp.ApproveStatus = full.ApproveStatus
			tmp.SellerName = full.SellerName
			tmp.SellerId = full.SellerId
			tmp.SellerIds = full.SellerIds
			tmp.FiccPackageType = full.FiccPackageType
			tmp.ExpireDay = full.ExpireDay
			tmp.FreezeTime = full.FreezeTime
			tmp.GroupId = full.GroupId
			tmp.GroupIds = full.GroupIds
			tmp.DepartmentId = full.DepartmentId
			tmp.IndustryName = full.IndustryName
			tmp.IsSuspend = full.IsSuspend
			tmp.CreatedTime = full.CreatedTime
			tmp.Source = full.Source
			tmp.Province = full.Province
			tmp.City = full.City
			tmp.Address = full.Address
			tmp.Reasons = full.Reasons
			tmp.FreezeStartDate = full.FreezeStartDate
			tmp.FreezeEndDate = full.FreezeEndDate
			tmp.FreezeExpireDays = full.FreezeExpireDays
			tmp.ProductId = full.ProductId
			tmp.FormalTime = full.FormalTime
			tmp.IsShared = full.IsShared
			tmp.RegionType = full.RegionType
			tmp.FiccView = full.FiccView
			tmp.RaiView = full.RaiView
			tmp.FiccLastViewTime = full.FiccLastViewTime
			tmp.RaiLastViewTime = full.RaiLastViewTime
			tmp.RoadShowTotal = full.RoadShowTotal
			tmp.TodoStatus = full.TodoStatus
			tmp.CanConfirm = full.CanConfirm
			tmp.HiddenConfirm = full.HiddenConfirm
			tmp.HiddenCreate = full.HiddenCreate
			tmp.TodoButtonColor = full.TodoButtonColor
			tmp.AllViewTotal = full.AllViewTotal
			tmp.Deadline = full.Deadline
			tmp.IsShow = full.IsShow
			tmp.TryStageSlice = full.TryStageSlice
		} else {
			tmp.CompanyId = v.CompanyId
			tmp.CompanyName = v.CompanyName
			tmp.Status = v.CompanyStatus
		}
		tmp.OldUserId = v.UserId
		tmp.OldRealName = v.RealName
		tmp.CollectNum = v.Num
		tmpList = append(tmpList, tmp)
	}

	if req.SortParam == "ybCollectLog" {
		list = tmpList
	} else {
		//处理company被删的数据的排序
		simpleList := make([]*YbCollectUserListItem, 0)
		for _, v := range tmpList {
			if _, ok := companyFullMap[v.CompanyId]; !ok {
				simpleList = append(simpleList, v)
			}
		}
		if req.SortType == "asc" {
			list = append(list, simpleList...)
		}
		// 如果是普通排序，先遍历company_id, 再遍历user_id, 放到最终的数组中
		for _, v := range companyResp.List {
			for _, uv := range tmpList {
				if uv.CompanyId == v.CompanyId {
					list = append(list, uv)
				}
			}
		}

		if req.SortType == "desc" || req.SortType == "" {
			list = append(list, simpleList...)
		}
	}
	page = paging.GetPaging(currentIndex, pageSize, int(total))
	resp.List = list
	resp.Paging = page
	return
}

// YbChartCollectList 收藏详情
func YbChartCollectList(sysUser *system.Admin, req yb.ChartCollectListReq) (resp YbChartCollectListResp, err error, errMsg string) {
	// 分组查询用户的日志详情
	pageSize := req.PageSize
	currentIndex := req.CurrentIndex
	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	var total int64
	var condition string
	pars := make([]interface{}, 0)
	page := paging.GetPaging(currentIndex, pageSize, int(total))

	// 校验入参
	if req.SellerIds != "" {
		condition += " and seller_id in (" + req.SellerIds + ")"
	}

	if req.StartDate != "" {
		startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if e != nil {
			errMsg = "起始时间格式错误， Err: " + e.Error()
			err = errors.New("起始时间格式错误")
			return
		}
		condition += " and create_time >= ?"
		pars = append(pars, startDate)
	}

	if req.EndDate != "" {
		endDateTmp, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if e != nil {
			errMsg = "截止时间格式错误， Err: " + e.Error()
			err = errors.New("截止时间格式错误")
			return
		}
		endDate := endDateTmp.AddDate(0, 0, 1)
		condition += " and create_time <= ?"
		pars = append(pars, endDate)
	}

	if req.CompanyStatus != "" {
		condition += " and company_status =?"
		pars = append(pars, req.CompanyStatus)
	}

	if req.CompanyId != 0 {
		condition += " and company_id =?"
		pars = append(pars, req.CompanyId)
	}

	if req.UserId != 0 {
		condition += " and user_id =?"
		pars = append(pars, req.UserId)
	}

	collections, total, err := yb.GetYbChartByCondition(condition, pars, startSize, pageSize)
	if err != nil {
		errMsg = "查询用户收藏量失败， Err: " + err.Error()
		err = errors.New("查询用户收藏量失败")
		return
	}
	// 遍历收藏列表取出图表ID
	chartInfoIds := make([]string, 0)
	for i := range collections {
		chartInfoIds = append(chartInfoIds, strconv.Itoa(collections[i].ChartInfoId))
	}

	// 查询相应收藏类型详情
	chartList := make([]*data_manage.ChartInfoView, 0)
	chartInfoMap := make(map[int]*data_manage.ChartInfoView, 0)
	if len(chartInfoIds) > 0 {
		chartList, err = data_manage.GetChartInfoViewByIds(chartInfoIds)
		if err != nil {
			err = errors.New("获取图表信息失败, Err: " + err.Error())
			return
		}
		for _, v := range chartList {
			chartInfoMap[v.ChartInfoId] = v
		}
	}
	list := make([]YbChartCollectListItem, 0)
	for _, v := range collections {
		tmp := YbChartCollectListItem{
			Id:         v.MyChartId,
			ChartInfo:  nil,
			CreateTime: v.CreateTime.Format(utils.FormatDateTime),
		}
		if c, ok := chartInfoMap[v.ChartInfoId]; ok {
			tmp.ChartInfo = c
		}
		list = append(list, tmp)
	}

	page = paging.GetPaging(currentIndex, pageSize, int(total))
	resp.List = list
	resp.Paging = page
	return
}
