package services

import (
	"errors"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/paging"
	"hongze/hz_crm_api/models"
	"hongze/hz_crm_api/models/yb"
	"hongze/hz_crm_api/services/alarm_msg"
	"hongze/hz_crm_api/utils"
	"strconv"
	"strings"
	"time"
)

// TagTreeItem 标签树
type TagTreeItem struct {
	ClassifyId   int        `json:"classify_id" description:"分类ID"`
	ClassifyName string     `json:"classify_name" description:"分类名称"`
	TagId        int        `json:"tag_id" description:"分类ID(用于前端组件)"`
	TagName      string     `json:"tag_name" description:"分类名称(用于前端组件)"`
	Sort         int        `json:"sort" description:"排序"`
	Tags         []*TagItem `json:"tags" description:"标签"`
}

// TagItem 标签
type TagItem struct {
	TagId             int              `json:"tag_id" description:"标签ID"`
	TagName           string           `json:"tag_name" description:"标签名称"`
	Sort              int              `json:"sort" description:"排序"`
	ClassifyId        int              `json:"classify_id" description:"分类ID"`
	ChartPermissionId int              `json:"chart_permission_id" description:"品种权限ID"`
	PriceDrivenState  int              `json:"price_driven_state" description:"价格驱动状态：0-关闭 1-开启"`
	ResearcherList    []*TagResearcher `json:"researcher_list" description:"研究员列表"`
}

// TagResearcher 研究员信息
type TagResearcher struct {
	AdminId     int    `json:"admin_id"`
	AdminName   string `json:"admin_name"`
	AllowSelect bool   `json:"allow_select" description:"是否允许选中"`
}

// 获取标签树
func GetTagTree(hasResearcher, include, questionId int) (respList []*TagTreeItem, err error) {
	respList = make([]*TagTreeItem, 0)
	var hasForbiddenTag bool
	if include == 1 { //如果包含被禁用的研究员，也要包含状态被禁用的分类
		hasForbiddenTag = true
	}
	// 获取标签分类
	classifyList, e := models.GetEnableVarietyClassifyList(hasForbiddenTag)
	if e != nil {
		err = errors.New("获取标签分类列表失败, Err: " + e.Error())
		return
	}
	classifyLen := len(classifyList)
	if classifyLen == 0 {
		return
	}

	tagList, e := models.GetEnableVarietyTagList(hasForbiddenTag)
	if e != nil {
		err = errors.New("获取标签列表失败, Err: " + e.Error())
		return
	}
	// 标签研究员组
	var relationList []*models.ResearchVarietyTagRelationItem
	if hasResearcher == 1 {
		relationList, e = models.GetResearchVarietyTagRelationList(include)
		if e != nil {
			err = errors.New("获取研究员标签关系失败, Err:" + e.Error())
			return
		}
	}

	// 价格驱动标签
	priceTagList, e := yb.GetPriceDrivenTagList()
	if e != nil {
		err = errors.New("获取价格驱动标签列表失败, Err:" + e.Error())
		return
	}
	priceTagLen := len(priceTagList)
	priceTagMap := make(map[int]int, 0)
	for i := 0; i < priceTagLen; i++ {
		priceTagMap[priceTagList[i].VarietyTagId] = priceTagList[i].State
	}

	// 问答社区-研究员是否允许被二次选中
	processMap := make(map[string]bool)
	if questionId > 0 {
		processList, e := yb.GetCommunityQuestionProcessItemList(questionId)
		if e != nil {
			err = errors.New("获取问答流程列表失败, Err:" + e.Error())
			return
		}
		for i := range processList {
			k := fmt.Sprintf("%d-%d", processList[i].VarietyTagId, processList[i].ReplierAdminId)
			processMap[k] = true
		}
	}

	// 标签成员、价格驱动状态
	tagsArr := make([]*TagItem, 0)
	tagLen := len(tagList)
	for i := 0; i < tagLen; i++ {
		item := tagList[i]
		// 价格驱动
		priceState := priceTagMap[item.VarietyTagId]
		tmp := &TagItem{
			TagId:             item.VarietyTagId,
			TagName:           item.TagName,
			Sort:              item.Sort,
			ClassifyId:        item.VarietyClassifyId,
			ChartPermissionId: item.ChartPermissionId,
			PriceDrivenState:  priceState,
		}
		members := make([]*TagResearcher, 0)
		if hasResearcher == 1 {
			for _, r := range relationList {
				if item.VarietyTagId == r.VarietyTagId {
					k := fmt.Sprintf("%d-%d", item.VarietyTagId, r.AdminId)
					as := true
					if processMap[k] {
						as = false
					}
					members = append(members, &TagResearcher{
						AdminId:     r.AdminId,
						AdminName:   r.AdminName,
						AllowSelect: as,
					})
				}
			}
			if len(members) > 0 {
				tmp.ResearcherList = members
				tagsArr = append(tagsArr, tmp)
			}
		} else {
			tagsArr = append(tagsArr, tmp)
		}
	}
	// 分类标签
	for i := 0; i < classifyLen; i++ {
		classifyItem := new(TagTreeItem)
		classifyItem.ClassifyId = classifyList[i].VarietyClassifyId
		classifyItem.ClassifyName = classifyList[i].ClassifyName
		classifyItem.TagId = classifyList[i].VarietyClassifyId
		classifyItem.TagName = classifyList[i].ClassifyName
		classifyItem.Sort = classifyList[i].Sort
		classifyItem.Tags = make([]*TagItem, 0)
		for _, t := range tagsArr {
			if classifyItem.ClassifyId == t.ClassifyId {
				classifyItem.Tags = append(classifyItem.Tags, t)
			}
		}
		if hasResearcher == 1 {
			if len(classifyItem.Tags) > 0 {
				respList = append(respList, classifyItem)
			}
		} else {
			respList = append(respList, classifyItem)
		}
	}
	return
}

// UpdateResearcherTagGroup 更新研究员标签分组
func UpdateResearcherTagGroup(adminId int, groupIds string) (err error) {
	if adminId == 0 {
		return
	}
	items := make([]*models.ResearchVarietyTagRelation, 0)
	groupIdArr := strings.Split(groupIds, ",")
	if groupIds != "" {
		for _, v := range groupIdArr {
			groupId, e := strconv.Atoi(v)
			if e != nil {
				err = errors.New("分组ID有误")
				return
			}
			items = append(items, &models.ResearchVarietyTagRelation{
				VarietyTagId: groupId,
				AdminId:      adminId,
			})
		}
	}
	if e := models.UpdateAdminVarietyTagRelation(adminId, items); e != nil {
		err = errors.New("更新研究员标签分组失败, Err:" + e.Error())
	}
	return
}

// VarietyClassifyPageResp 标签分类分页列表响应体
type VarietyClassifyPageResp struct {
	Paging *paging.PagingItem
	List   []*VarietyClassifyPageItem `description:"列表数据"`
}

// VarietyClassifyPageItem 标签分类分页列表数据
type VarietyClassifyPageItem struct {
	VarietyClassifyId int    `json:"variety_classify_id" description:"标签分类ID"`
	ClassifyName      string `json:"classify_name" description:"标签分类名称"`
	Sort              int    `json:"sort" description:"排序"`
	State             int    `json:"state" description:"显示状态 0-禁用 1-启用"`
	CreateTime        string `json:"create_time" description:"创建时间"`
	ModifyTime        string `json:"modify_time" description:"更新时间"`
}

// GetVarietyClassifyPageList 分类分页列表
func GetVarietyClassifyPageList(condition string, pars []interface{}, orderStr string, startSize, pageSize int) (total int, resp *VarietyClassifyPageResp, err error) {
	resp = new(VarietyClassifyPageResp)
	total, list, e := models.GetVarietyClassifyPageList(condition, pars, orderStr, startSize, pageSize)
	if e != nil {
		err = errors.New("获取分类列表失败, Err:" + e.Error())
		return
	}
	if len(list) == 0 {
		return
	}
	respList := make([]*VarietyClassifyPageItem, 0)
	for _, v := range list {
		item := &VarietyClassifyPageItem{
			VarietyClassifyId: v.VarietyClassifyId,
			ClassifyName:      v.ClassifyName,
			Sort:              v.Sort,
			State:             v.State,
			CreateTime:        v.CreateTime.Format(utils.FormatDateTime),
			ModifyTime:        v.ModifyTime.Format(utils.FormatDateTime),
		}
		respList = append(respList, item)
	}
	resp.List = respList
	return
}

// VarietyClassifySaveReq 保存标签分类请求体
type VarietyClassifySaveReq struct {
	VarietyClassifyId int    `json:"variety_classify_id" description:"标签分类ID"`
	ClassifyName      string `json:"classify_name" description:"标签分类名称"`
}

// SaveVarietyClassify 保存标签分类
func SaveVarietyClassify(varietyClassifyId int, classifyName string) (errMsg string, err error) {
	// 重名校验
	exists, e := models.GetVarietyClassifyByName(classifyName)
	if e != nil && e.Error() != utils.ErrNoRow() {
		errMsg = "获取分类失败"
		err = errors.New("获取分类失败, Err: " + e.Error())
		return
	}
	if exists != nil {
		if varietyClassifyId == 0 || (varietyClassifyId > 0 && exists.VarietyClassifyId != varietyClassifyId) {
			errMsg = "该标签分类已存在, 请重新输入"
			err = errors.New("该标签分类已存在, 请重新输入")
			return
		}
	}
	nowTime := time.Now().Local()
	if varietyClassifyId > 0 {
		// 更新
		item, e := models.GetVarietyClassifyById(varietyClassifyId)
		if e != nil {
			errMsg = "分类信息有误"
			err = errors.New("获取分类失败, Err: " + e.Error())
			return
		}
		updateCols := make([]string, 0)
		updateCols = append(updateCols, "ClassifyName", "ModifyTime")
		item.ClassifyName = classifyName
		item.ModifyTime = nowTime
		if e = item.Update(updateCols); e != nil {
			errMsg = "保存失败"
			err = errors.New("更新分类失败, Err: " + e.Error())
			return
		}
	} else {
		// 新增
		newClassify := &models.VarietyClassify{
			ClassifyName: classifyName,
			State:        1,
			CreateTime:   nowTime,
			ModifyTime:   nowTime,
		}
		if _, e = newClassify.Add(); e != nil {
			errMsg = "保存失败"
			err = errors.New("新增分类失败, Err: " + e.Error())
			return
		}
	}
	return
}

// VarietyClassifyStateReq 切换标签分类状态请求体
type VarietyClassifyStateReq struct {
	VarietyClassifyId int `json:"variety_classify_id" description:"标签分类ID"`
	State             int `json:"state" description:"状态：0-禁用 1-开启"`
}

// SwitchVarietyClassifyState 切换标签分类状态
func SwitchVarietyClassifyState(varietyClassifyId, state int) (errMsg string, err error) {
	item, e := models.GetVarietyClassifyById(varietyClassifyId)
	if e != nil {
		errMsg = "分类信息有误"
		err = errors.New("获取分类失败, Err: " + e.Error())
		return
	}
	// 禁用操作校验是否还有其他启用分类
	if state == 0 {
		countEnable, e := models.GetCountEnableClassifyByClassifyId(varietyClassifyId)
		if e != nil {
			errMsg = "操作失败"
			err = errors.New("获取启用分类数失败, Err: " + e.Error())
			return
		}
		if countEnable == 0 {
			errMsg = "请至少保留一个标签分类"
			err = errors.New("请至少保留一个标签分类")
			return
		}
	}
	// 更新
	updateCols := make([]string, 0)
	updateCols = append(updateCols, "State", "ModifyTime")
	item.State = state
	item.ModifyTime = time.Now().Local()
	if e = item.Update(updateCols); e != nil {
		errMsg = "保存失败"
		err = errors.New("更新分类失败, Err: " + e.Error())
		return
	}
	return
}

// VarietyTagPageResp 标签分页列表响应体
type VarietyTagPageResp struct {
	Paging *paging.PagingItem
	List   []*VarietyTagPageItem `description:"列表数据"`
}

// VarietyClassifyPageItem 标签分类分页列表数据
type VarietyTagPageItem struct {
	VarietyTagId                int    `json:"variety_tag_id" description:"标签ID"`
	VarietyClassifyId           int    `json:"variety_classify_id" description:"标签分类ID"`
	VarietyClassifyName         string `json:"variety_classify_name" description:"标签分类名称"`
	TagName                     string `json:"tag_name" description:"标签名称"`
	ChartPermissionClassifyName string `json:"chart_permission_classify_name" description:"品种权限分类名"`
	ChartPermissionId           int    `json:"chart_permission_id" description:"品种权限ID"`
	ChartPermissionName         string `json:"chart_permission_name" description:"品种权限名称"`
	Sort                        int    `json:"sort" description:"排序"`
	State                       int    `json:"state" description:"显示状态 0-禁用 1-启用"`
	CreateTime                  string `json:"create_time" description:"创建时间"`
	ModifyTime                  string `json:"modify_time" description:"更新时间"`
}

// GetVarietyTagPageList 分类分页列表
func GetVarietyTagPageList(condition string, pars []interface{}, orderStr string, startSize, pageSize int) (total int, resp *VarietyTagPageResp, err error) {
	resp = new(VarietyTagPageResp)
	total, list, e := models.GetVarietyTagPageList(condition, pars, orderStr, startSize, pageSize)
	if e != nil {
		err = errors.New("获取标签列表失败, Err:" + e.Error())
		return
	}
	if len(list) == 0 {
		return
	}
	respList := make([]*VarietyTagPageItem, 0)
	for _, v := range list {
		item := &VarietyTagPageItem{
			VarietyTagId:                v.VarietyTagId,
			VarietyClassifyId:           v.VarietyClassifyId,
			VarietyClassifyName:         v.VarietyClassifyName,
			TagName:                     v.TagName,
			ChartPermissionClassifyName: v.ChartPermissionClassifyName,
			ChartPermissionId:           v.ChartPermissionId,
			ChartPermissionName:         v.ChartPermissionName,
			Sort:                        v.Sort,
			State:                       v.State,
			CreateTime:                  v.CreateTime.Format(utils.FormatDateTime),
			ModifyTime:                  v.ModifyTime.Format(utils.FormatDateTime),
		}
		respList = append(respList, item)
	}
	resp.List = respList
	return
}

// VarietyTagSaveReq 保存标签请求体
type VarietyTagSaveReq struct {
	VarietyTagId      int    `json:"variety_tag_id" description:"标签ID"`
	VarietyClassifyId int    `json:"variety_classify_id" description:"标签分类ID"`
	TagName           string `json:"tag_name" description:"标签名称"`
	ChartPermissionId int    `json:"chart_permission_id" description:"品种权限ID"`
}

// SaveVarietyTag 保存标签
func SaveVarietyTag(varietyTagId, varietyClassifyId, chartPermissionId int, tagName string) (errMsg string, err error) {
	// 分类信息
	classify, e := models.GetVarietyClassifyById(varietyClassifyId)
	if e != nil {
		errMsg = "分类信息有误"
		err = errors.New("获取分类信息失败, Err: " + e.Error())
		return
	}
	// 品种信息
	chartPermission, e := models.GetChartPermissionById(chartPermissionId)
	if e != nil {
		errMsg = "品种信息有误"
		err = errors.New("获取品种信息失败, Err: " + e.Error())
		return
	}
	nowTime := time.Now().Local()
	tagId := 0
	if varietyTagId > 0 {
		// 更新
		item, e := models.GetVarietyTagById(varietyTagId)
		if e != nil {
			errMsg = "标签信息有误"
			err = errors.New("获取标签信息失败, Err: " + e.Error())
			return
		}
		updateCols := make([]string, 0)
		updateCols = append(updateCols, "VarietyClassifyId", "VarietyClassifyName", "TagName", "ChartPermissionClassifyName",
			"ChartPermissionId", "ChartPermissionName", "ModifyTime")
		item.VarietyClassifyId = classify.VarietyClassifyId
		item.VarietyClassifyName = classify.ClassifyName
		item.TagName = tagName
		item.ChartPermissionClassifyName = chartPermission.ClassifyName
		item.ChartPermissionId = chartPermission.ChartPermissionId
		item.ChartPermissionName = chartPermission.PermissionName
		item.ModifyTime = nowTime
		if e = item.Update(updateCols); e != nil {
			errMsg = "保存失败"
			err = errors.New("更新分类信息失败, Err: " + e.Error())
			return
		}
		tagId = item.VarietyTagId
	} else {
		// 新增
		newTag := &models.VarietyTag{
			VarietyClassifyId:           classify.VarietyClassifyId,
			VarietyClassifyName:         classify.ClassifyName,
			TagName:                     tagName,
			ChartPermissionClassifyName: chartPermission.ClassifyName,
			ChartPermissionId:           chartPermission.ChartPermissionId,
			ChartPermissionName:         chartPermission.PermissionName,
			State:                       1,
			CreateTime:                  nowTime,
			ModifyTime:                  nowTime,
		}
		if _, e = newTag.Add(); e != nil {
			errMsg = "保存失败"
			err = errors.New("新增标签失败, Err: " + e.Error())
			return
		}
		tagId = newTag.VarietyTagId
	}
	// 更新价格驱动标签
	go func() {
		_ = SavePriceDrivenTag(tagId)
	}()
	return
}

// VarietyTagStateReq 切换标签状态请求体
type VarietyTagStateReq struct {
	VarietyTagId int `json:"variety_tag_id" description:"标签分类ID"`
	State        int `json:"state" description:"状态：0-禁用 1-开启"`
}

// SwitchVarietyTagState 切换标签状态
func SwitchVarietyTagState(varietyTagId, state int) (errMsg string, err error) {
	item, e := models.GetVarietyTagById(varietyTagId)
	if e != nil {
		errMsg = "分类信息有误"
		err = errors.New("获取分类信息失败, Err: " + e.Error())
		return
	}
	// 禁用操作校验是否还有其他启用标签
	if state == 0 {
		countEnable, e := models.GetCountEnableTagByTagId(varietyTagId)
		if e != nil {
			errMsg = "操作失败"
			err = errors.New("获取启用标签数失败, Err: " + e.Error())
			return
		}
		if countEnable == 0 {
			errMsg = "请至少保留一个标签"
			err = errors.New("请至少保留一个标签")
			return
		}
	}
	// 更新
	updateCols := make([]string, 0)
	updateCols = append(updateCols, "State", "ModifyTime")
	item.State = state
	item.ModifyTime = time.Now().Local()
	if e = item.Update(updateCols); e != nil {
		errMsg = "保存失败"
		err = errors.New("更新分类信息失败, Err: " + e.Error())
		return
	}
	// 如果是禁用操作, 同时修改价格驱动标签状态
	if state == 0 {
		go func() {
			_ = SavePriceDrivenTag(varietyTagId)
		}()
	}
	return
}

// SavePriceDrivenTag 保存价格驱动标签
func SavePriceDrivenTag(varietyTagId int) (err error) {
	defer func() {
		if err != nil {
			utils.FileLog.Info(err.Error())
			go alarm_msg.SendAlarmMsg("保存价格驱动标签失败-SavePriceDrivenTag, ErrMsg: "+err.Error(), 3)
		}
	}()
	// 获取品种标签
	varietyTag, e := models.GetVarietyTagById(varietyTagId)
	if e != nil {
		err = errors.New("获取品种标签失败, Err: " + e.Error())
		return
	}
	// 获取价格驱动标签
	priceTag, e := yb.GetPriceDrivenTagByTagId(varietyTagId)
	if e != nil && e.Error() != utils.ErrNoRow() {
		err = errors.New("获取价格驱动标签失败, Err: " + e.Error())
		return
	}
	nowTime := time.Now().Local()
	if priceTag != nil {
		updateCols := make([]string, 0)
		updateCols = append(updateCols, "VarietyTagName", "State", "ModifyTime")
		priceTag.VarietyTagName = varietyTag.TagName
		priceTag.State = varietyTag.State
		priceTag.ModifyTime = nowTime
		if e = priceTag.Update(updateCols); e != nil {
			err = errors.New("更新价格驱动标签失败, Err: " + e.Error())
			return
		}
	} else {
		newPriceTag := &yb.PriceDrivenTag{
			VarietyTagId:   varietyTag.VarietyTagId,
			VarietyTagName: varietyTag.TagName,
			State:          varietyTag.State,
			CreateTime:     nowTime,
			ModifyTime:     nowTime,
		}
		if _, e = newPriceTag.Add(); e != nil {
			err = errors.New("新增价格驱动标签失败, Err: " + e.Error())
			return
		}
	}
	return
}
