package yb

import (
	"encoding/json"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/paging"
	"hongze/hz_crm_api/controllers"
	"hongze/hz_crm_api/models"
	ybModels "hongze/hz_crm_api/models/yb"
	"hongze/hz_crm_api/models/yb/request"
	"hongze/hz_crm_api/services"
	"hongze/hz_crm_api/services/yb"
	"hongze/hz_crm_api/utils"
	"strings"
	"time"
)

// RoadVideoController 研报视频社区
type RoadVideoController struct {
	controllers.BaseAuthController
}

// List
// @Title 视频列表
// @Description 视频列表
// @Param   Keywords  query  string  false  "关键词"
// @Param   SortParam   query   string  false     "排序字段参数，用来排序的字段， 枚举值：'ClickNum':点击量"
// @Param   SortType   query   string  true       "如何排序，是正序还是倒序，枚举值：`asc 正序`,`desc 倒叙`"
// @Success 200 {object} response.CommunityQuestionListResp
// @router /road/video/list [get]
func (r *RoadVideoController) List() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	condition := ""
	pars := make([]interface{}, 0)
	keywords := r.GetString("Keywords", "")
	if keywords != "" {
		keywords = "%" + keywords + "%"
		condition += ` AND v.title LIKE ? `
		pars = append(pars, keywords)
	}

	var startSize int
	pageSize, _ := r.GetInt("PageSize")
	currentIndex, _ := r.GetInt("CurrentIndex")
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	// 排序相关
	sortParam := r.GetString("SortParam")
	sortType := r.GetString("SortType")
	orderStr := ""
	if sortType != "" && strings.ToLower(sortType) != "desc" && strings.ToLower(sortType) != "asc" {
		br.Msg = "请输入正确的排序类型"
		return
	}
	if sortParam == "ClickNum" {
		orderStr = "  ORDER BY l.click_num"
		if sortType != "" {
			orderStr += " " + sortType
		} else {
			orderStr += " DESC"
		}

		orderStr += ", v.modify_time DESC"
	}
	total, resp, err, errMsg := yb.GetRoadVideoList(condition, pars, orderStr, startSize, pageSize)
	if err != nil {
		br.Msg = errMsg
		br.ErrMsg = err.Error()
		return
	}

	page := paging.GetPaging(currentIndex, pageSize, total)
	resp.Paging = page
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// Save
// @Title 保存视频
// @Description 保存视频
// @Param	request  body  request.RoadVideoSaveReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/video/save [post]
func (r *RoadVideoController) Save() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RoadVideoSaveReq
	if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	if req.Title == "" {
		br.Msg = "请输入标题"
		return
	}
	if req.ChartPermissionIds == "" {
		br.Msg = "请选择品种"
		return
	}
	if req.CoverImgUrl == "" {
		br.Msg = "请上传封面图"
		return
	}
	if req.VideoUrl == "" {
		br.Msg = "请上传视频"
		return
	}
	data, errMsg, err := yb.SaveRoadVideo(sysUser, req.VideoId, req.ReportId, req.ChartPermissionIds, req.Title, req.CoverImgUrl, req.VideoUrl, req.VideoSeconds)
	if err != nil {
		br.Msg = errMsg
		br.ErrMsg = "Yb-SaveVideo ErrMsg:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
	br.Data = data
}

// Delete
// @Title 删除视频
// @Description 删除视频
// @Param	request  body  request.RoadVideoOptionReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/video/delete [post]
func (r *RoadVideoController) Delete() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RoadVideoOptionReq
	if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	if req.VideoId <= 0 {
		br.Msg = "参数有误"
		return
	}
	errMsg, err := yb.SoftDeleteRoadVideo(req.VideoId)
	if err != nil {
		br.Msg = errMsg
		br.ErrMsg = "Yb-DeleteVideo ErrMsg:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Publish
// @Title 发布/取消视频
// @Description 发布/取消视频
// @Param	request  body  request.RoadVideoPublishReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/video/publish [post]
func (r *RoadVideoController) Publish() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RoadVideoPublishReq
	if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	if req.VideoId <= 0 {
		br.Msg = "参数有误"
		return
	}
	errMsg, err := yb.PublishRoadVideo(req.VideoId, req.PublishState)
	if err != nil {
		br.Msg = errMsg
		br.ErrMsg = "Yb-PublishVideo ErrMsg:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// SendThs
// @Title 推送客群消息
// @Description 推送客群消息
// @Param	request  body  request.RoadVideoOptionReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/video/send_ths [post]
func (r *RoadVideoController) SendThs() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RoadVideoOptionReq
	if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	if req.VideoId <= 0 {
		br.Msg = "参数有误"
		return
	}
	errMsg, err := yb.SendRoadVideoThsMsg(req.VideoId)
	if err != nil {
		br.Msg = errMsg
		br.ErrMsg = "Yb-SendVideoThsMsg ErrMsg:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// VideoPlayLogList
// @Title 获取视频点击量列表
// @Description 获取视频点击量列表
// @Param   VideoId	query	int	false	"视频ID"
// @Param   SortType	query	int	false	"播放时长排序：默认倒序; 1-倒序(多一个数方便前端回显); 2-正序"
// @Success 200 {object} response.QuestionClickLogListResp
// @router /road/video/click/logs [get]
func (r *RoadVideoController) VideoPlayLogList() {
	br := new(models.BaseResponse).Init()
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	videoId, _ := r.GetInt("VideoId")
	if videoId <= 0 {
		br.Msg = "请输入正确的视频ID"
		return
	}
	// 播放时长排序：1-DESC; 2-ASC;
	sortType, _ := r.GetInt("SortType")

	var startSize int
	pageSize, _ := r.GetInt("PageSize")
	currentIndex, _ := r.GetInt("CurrentIndex")
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	total, resp, err := yb.GetVideoPlayLogList(videoId, 2, startSize, pageSize, sortType)
	if err != nil {
		br.Msg = "获取点击量详情列表失败"
		br.ErrMsg = "VideoPlayLogList ErrMsg:" + err.Error()
		return
	}

	page := paging.GetPaging(currentIndex, pageSize, int(total))
	resp.Paging = page
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// SendTemplateMsg
// @Title 推送模板消息
// @Description 推送模板消息
// @Param	request  body  request.RoadVideoOptionReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/video/send_template_msg [post]
func (r *RoadVideoController) SendTemplateMsg() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RoadVideoOptionReq
	if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	if req.VideoId <= 0 {
		br.Msg = "参数有误"
		return
	}
	errMsg, err := yb.SendRoadVideoTemplateMsg(req.VideoId)
	if err != nil {
		br.Msg = errMsg
		br.ErrMsg = "Yb-SendRoadVideoTemplateMsg ErrMsg:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// GetPermission
// @Title 查询品种权限
// @Description 查询品种权限
// @Param	request  body  request.RoadVideoOptionReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/permission [get]
func (r *RoadVideoController) GetPermission() {
	br := new(models.BaseResponse).Init()
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	ret, err := yb.GetFiccPermission()
	if err != nil {
		br.Msg = "查询权限出错"
		br.ErrMsg = "Yb-SendVideoThsMsg ErrMsg:" + err.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
	br.Data = ret
}

// TwoWeekClassifyList
// @Title 路演视频-关联报告类型列表
// @Description 路演视频-关联报告类型列表
// @Success 200 {object} models.SimpleClassifyList
// @router /road/video/two_week_classify_list [get]
func (r *RoadVideoController) TwoWeekClassifyList() {
	br := new(models.BaseResponse).Init()
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	// 2023-04-19 取classify表relate_video=1的二级分类, 但是需要分层级, 所以对应的一级分类也要组合起来
	list, e := models.GetAllClassifyByRelateVideo()
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取路演视频可选报告分类失败, Err: " + e.Error()
		return
	}

	// 获取父级的分类
	{
		idMap := make(map[int]bool)

		currParentClassifyIdList := make([]int, 0)
		for _, v := range list {
			idMap[v.Id] = true
			if v.ParentId > 0 {
				currParentClassifyIdList = append(currParentClassifyIdList, v.ParentId)
			}
		}

		findList := list
		list = make([]*models.Classify, 0)

		tmpList, tmpErr := services.GetParentClassifyListByParentIdList(currParentClassifyIdList)
		if tmpErr != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取上级分类信息失败，Err:" + tmpErr.Error()
			return
		}
		for _, v := range tmpList {
			if _, ok := idMap[v.Id]; !ok {
				list = append(list, v)
			}
		}

		list = append(list, findList...)
	}

	allList := make([]*models.SimpleClassifyList, 0)
	for _, v := range list {
		allList = append(allList, &models.SimpleClassifyList{
			Id:           v.Id,
			ClassifyName: v.ClassifyName,
			ParentId:     v.ParentId,
			Sort:         v.Sort,
			CreateTime:   v.CreateTime,
			Child:        make([]*models.SimpleClassifyList, 0),
		})
	}

	// 先将分类列表排序
	services.SortClassifyListBySortAndCreateTime(allList)
	// 接着转换结构
	allList = services.GetClassifyListTreeRecursive(allList, 0)

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
	br.Data = allList
}

// SimpleReportList
// @Title 路演视频选择报告-列表
// @Description 路演视频选择报告-列表
// @Param	ClassifyIdSecond  query  int  false  "二级分类ID"
// @Param	Keyword  query  string  false  "关键词-报告标题"
// @Success 200 string "获取成功"
// @router /road/video/simple_report_list [get]
func (r *RoadVideoController) SimpleReportList() {
	br := new(models.BaseResponse).Init()
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	cond := ` AND state = 2`
	pars := make([]interface{}, 0)
	classifyIdSecond, _ := r.GetInt("ClassifyIdSecond", 0)
	if classifyIdSecond <= 0 {
		// 2023-03-03 直接取classify表relate_video=1的二级分类下的报告
		//classifyCond := ` AND parent_id > 0 AND relate_video = 1`
		classifyCond := ` AND relate_video = 1`
		classifyPars := make([]interface{}, 0)
		classifyList, e := models.GetClassifyByCondition(classifyCond, "", classifyPars)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取路演视频可选报告分类失败, Err: " + e.Error()
			return
		}
		var hasChild bool
		firstClassifyIds := make([]int, 0)
		secondClassifyIds := make([]int, 0)
		thirdClassifyIds := make([]int, 0)
		for _, c := range classifyList {
			switch c.Level {
			case 1:
				firstClassifyIds = append(firstClassifyIds, c.Id)
				hasChild = true
			case 2:
				secondClassifyIds = append(secondClassifyIds, c.Id)
				hasChild = true
			case 3:
				thirdClassifyIds = append(thirdClassifyIds, c.Id)
				hasChild = true
			}
		}
		if hasChild {
			classifyCondList := make([]string, 0)
			if len(firstClassifyIds) > 0 {
				classifyCondList = append(classifyCondList, ` classify_id_first IN ( `+utils.GetOrmInReplace(len(firstClassifyIds))+` ) `)
				pars = append(pars, firstClassifyIds)
			}
			if len(secondClassifyIds) > 0 {
				classifyCondList = append(classifyCondList, ` classify_id_second IN ( `+utils.GetOrmInReplace(len(secondClassifyIds))+` ) `)
				pars = append(pars, secondClassifyIds)
			}
			if len(thirdClassifyIds) > 0 {
				classifyCondList = append(classifyCondList, ` classify_id_third IN ( `+utils.GetOrmInReplace(len(thirdClassifyIds))+` ) `)
				pars = append(pars, thirdClassifyIds)
			}
			cond += fmt.Sprintf(` AND (%s) `, strings.Join(classifyCondList, " OR "))
		} else {
			cond += ` AND 1 = 2`
		}
	} else {
		classifyItem, err := models.GetClassifyById(classifyIdSecond)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取分类失败, Err: " + err.Error()
			return
		}
		switch classifyItem.Level {
		case 1:
			cond += ` AND classify_id_first = ? `
			pars = append(pars, classifyIdSecond)
		case 2:
			cond += ` AND classify_id_second = ? `
			pars = append(pars, classifyIdSecond)
		case 3:
			cond += ` AND classify_id_third = ? `
			pars = append(pars, classifyIdSecond)
		}
	}

	keyword := r.GetString("Keyword", "")
	if keyword != "" {
		kw := fmt.Sprint("%", keyword, "%")
		cond += ` AND title LIKE ?`
		pars = append(pars, kw)
	}
	fieldArr := []string{"id", "classify_id_first", "classify_id_second", "classify_id_third", "title", "publish_time"}
	orderRule := ` ORDER BY publish_time DESC, id DESC`
	reports, e := models.GetReportByCondition(cond, pars, fieldArr, orderRule, true, 0, 5)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取双周报列表失败, Err: " + e.Error()
		return
	}

	// 查询报告权限
	classifyPermissions := make(map[int][]int, 0)
	{
		classifyIds := make([]int, 0)
		for _, v := range reports {
			minClassifyId, _, e := services.GetMinClassify(v)
			if e != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取报告的最小分类失败, Err: " + e.Error()
				return
			}
			if utils.InArrayByInt(classifyIds, minClassifyId) {
				continue
			}
			classifyIds = append(classifyIds, minClassifyId)
		}
		if len(classifyIds) > 0 {
			classifyIdsPermissions, e := models.GetPermissionsByClassifyIds(classifyIds)
			if e != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取分类权限失败, Err: " + e.Error()
				return
			}
			for _, v := range classifyIdsPermissions {
				classifyPermissions[v.ClassifyId] = append(classifyPermissions[v.ClassifyId], v.ChartPermissionId)
			}
		}
	}

	type SimpleReportListResp struct {
		ReportId       int
		Title          string
		PublishTime    string
		BindVideo      int
		BindVideoTitle string
		PermissionIds  []int
	}
	respList := make([]*SimpleReportListResp, 0)
	if len(reports) > 0 {
		reportIds := make([]int, 0)
		for i := range reports {
			reportIds = append(reportIds, reports[i].Id)
		}
		// 是否绑定
		videos, e := ybModels.GetRoadVideoListByReportIds(reportIds)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取路演视频列表失败, Err: " + e.Error()
			return
		}
		bindMap := make(map[int]int)
		bindTitleMap := make(map[int]string)
		for i := range videos {
			bindMap[videos[i].ReportId] = videos[i].RoadVideoId
			bindTitleMap[videos[i].ReportId] = videos[i].Title
		}

		for i := range reports {
			tmpReport := reports[i]
			minClassifyId, _, e := services.GetMinClassify(tmpReport)
			if e != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取报告的最小分类失败, Err: " + e.Error()
				return
			}
			respList = append(respList, &SimpleReportListResp{
				ReportId:       tmpReport.Id,
				Title:          tmpReport.Title,
				PublishTime:    tmpReport.PublishTime.Format(utils.FormatDateTime),
				BindVideo:      bindMap[tmpReport.Id],
				BindVideoTitle: bindTitleMap[tmpReport.Id],
				PermissionIds:  classifyPermissions[minClassifyId],
			})
		}
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
	br.Data = respList
}

// SendMsg
// @Title 推送消息(模板/客群)
// @Description 推送消息(模板/客群)
// @Param	request  body  request.RoadVideoOptionReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /road/video/send_msg [post]
func (r *RoadVideoController) SendMsg() {
	br := new(models.BaseResponse).Init()
	br.IsSendEmail = false
	defer func() {
		r.Data["json"] = br
		r.ServeJSON()
	}()
	sysUser := r.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RoadVideoOptionReq
	if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	if req.VideoId <= 0 {
		br.Msg = "参数有误"
		return
	}

	// 加锁，避免重复点击造成的多次推送
	{
		redisKey := fmt.Sprint("road_video:send:msg:", req.VideoId)
		ok := utils.Rc.SetNX(redisKey, 1, time.Second*300)
		if !ok {
			br.Msg = "消息已推送, 请勿重复推送"
			return
		}
		defer func() {
			_ = utils.Rc.Delete(redisKey)
		}()
	}

	item, e := ybModels.GetRoadVideoById(req.VideoId)
	if e != nil {
		br.Msg = "视频不存在或已被删除"
		br.ErrMsg = "获取路演视频失败, Err: " + e.Error()
		return
	}
	if item.PublishState != 1 {
		br.Msg = "视频未发布, 不可推送"
		return
	}
	if item.SendThsState == 1 && item.SendTemplateState == 1 {
		br.Msg = "请勿重复推送"
		return
	}

	nowTime := time.Now().Local()
	updateCols := make([]string, 0)
	// 可能存在历史数据两个只推了一个所以此处加个判断
	// 模板消息
	if item.SendTemplateState == 0 {
		updateCols = append(updateCols, "SendTemplateState", "SendTemplateTime")
		item.SendTemplateState = 1
		item.SendTemplateTime = nowTime
		go func() {
			_ = services.SendYbRoadVideoWxMsg(item.RoadVideoId, item.Title, item.PublishTime.Format(utils.FormatDateTime), item.ChartPermissionIds)
		}()
	}

	// 客群消息
	if item.SendThsState == 0 {
		updateCols = append(updateCols, "SendThsState", "SendThsTime")
		item.SendThsState = 1
		item.SendThsTime = nowTime
		//go func() {
		//	_ = services.SendYbRoadVideoThs(item.RoadVideoId, item.Title, item.ChartPermissionIds)
		//}()
	}

	// 更新状态
	if e := item.Update(updateCols); e != nil {
		br.Msg = "推送失败"
		br.ErrMsg = "更新路演视频信息失败, Err: " + e.Error()
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}
