package common

import (
	"fmt"
	"mtp2_if/db"
	"mtp2_if/global/app"
	"mtp2_if/global/e"
	"mtp2_if/logger"
	"mtp2_if/models"
	"mtp2_if/utils"
	"net/http"
	"sort"

	"github.com/gin-gonic/gin"
)

// QueryNoticeReq 通知公告系统消息查询请求参数
type QueryNoticeReq struct {
	app.PageInfo
	LoginID    int  `form:"loginID"`    // 登录账号
	MsgType    int  `form:"msgType"`    // 消息类型 - 1:公告通知 2:系统消息
	OnlyUnRead bool `form:"onlyUnRead"` // 是否未读信息
	LastID     int  `form:"lastID"`     // 自增ID
}

// QueryNoticeRsp 通知公告系统消息查询返回模型
type QueryNoticeRsp struct {
	models.Noticemsg `xorm:"extends"`
	Readed           bool `json:"readed" xorm:"-"` // 是否已读
}

// QueryNotice 通知公告系统消息查询
// @Summary 通知公告系统消息查询
// @Produce json
// @Security ApiKeyAuth
// @Param page query int false "页码"
// @Param pagesize query int false "每页条数"
// @Param loginID query int true "登录账号"
// @Param msgType query int false "消息类型 - 1:公告通知 2:系统消息"
// @Param onlyUnRead query bool false "是否只获取未读信息"
// @Param lastID query int false "自增ID，传入后会返回这个ID后面的记录"
// @Success 200 {object} QueryNoticeRsp
// @Failure 500 {object} app.Response
// @Router /Common/QueryNotice [get]
// @Tags 通用服务
func QueryNotice(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryNoticeReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryNotice failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	rst := make([]QueryNoticeRsp, 0)
	engine := db.GetEngine()
	// 获取登录账号所属会员信息
	var userAccount models.Useraccount
	if has, _ := engine.Join("LEFT", "LOGINACCOUNT", "LOGINACCOUNT.USERID = USERACCOUNT.USERID").
		Where("LOGINACCOUNT.LOGINID = ?", req.LoginID).Get(&userAccount); !has {
		// 查询失败
		logger.GetLogger().Errorf("QueryNotice failed: %s", "获取登录账号所属会员ID失败")
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 获取登录账号已读公告ID, 这里要使用的是个人的UserID来查询
	var msgReceivers []int
	engine.Table("MSGRECEIVER").Select("AUTOID").Where("RECEIVERTYPE = 2 and MANAGERID = ?", userAccount.Userid).Find(&msgReceivers)

	// 查询SENDTYPE = 1的数据
	datas1 := make([]QueryNoticeRsp, 0)
	s := engine.Where("SENDTYPE = 1 and SYSDATE > SCHEDULETIME and SYSDATE < ENDTIME and SENTSTATUS=1").
		And("PUBLISHER = ? or PUBLISHER in (select USERACCOUNT.USERID from USERACCOUNT where USERACCOUNT.USERTYPE = 1)", userAccount.Memberuserid)
	if req.MsgType > 0 {
		s = s.And("MSGTYPE = ?", req.MsgType)
	}
	if req.LastID != 0 {
		s = s.And("AUTOID > ?", req.LastID)
	}
	if req.OnlyUnRead && len(msgReceivers) > 0 {
		s = s.NotIn("AUTOID", msgReceivers)
	}
	if err := s.Find(&datas1); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryNotice failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	rst = append(rst, datas1...)

	// 查询SENDTYPE = 2的数据
	datas2 := make([]QueryNoticeRsp, 0)
	s = engine.Where(fmt.Sprintf(`AUTOID in (select MEMBERRECV.MSGID from MEMBERRECV where MEMBERRECV.MEMBERID = %d)`, userAccount.Memberuserid)).
		And("SENDTYPE = 2 and SYSDATE > SCHEDULETIME and SYSDATE < ENDTIME and SENTSTATUS=1")
	if req.MsgType > 0 {
		s = s.And("MSGTYPE = ?", req.MsgType)
	}
	if req.LastID != 0 {
		s = s.And("AUTOID > ?", req.LastID)
	}
	if req.OnlyUnRead && len(msgReceivers) > 0 {
		s = s.NotIn("AUTOID", msgReceivers)
	}
	if err := s.Find(&datas2); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryNotice failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	rst = append(rst, datas2...)

	// 查询SENDTYPE = 3的数据
	datas3 := make([]QueryNoticeRsp, 0)
	s = engine.Where(fmt.Sprintf(`USERID = (SELECT USERID FROM LOGINACCOUNT WHERE LOGINID = %d)`, req.LoginID)).
		And("SENDTYPE = 3 and SYSDATE > SCHEDULETIME and SYSDATE < ENDTIME and SENTSTATUS=1")
	if req.MsgType > 0 {
		s = s.And("MSGTYPE = ?", req.MsgType)
	}
	if req.LastID != 0 {
		s = s.And("AUTOID > ?", req.LastID)
	}
	if req.OnlyUnRead && len(msgReceivers) > 0 {
		s = s.NotIn("AUTOID", msgReceivers)
	}
	if err := s.Find(&datas3); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryNotice failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}
	rst = append(rst, datas3...)

	// 排序
	sort.Slice(rst, func(i int, j int) bool {
		return rst[i].Scheduletime.After(rst[j].Scheduletime)
	})

	// 分页
	total := len(rst)
	if req.PageSize > 0 {
		rstByPage := make([]QueryNoticeRsp, 0)
		// 开始上标
		start := req.Page * req.PageSize
		// 结束下标
		end := start + req.PageSize

		if start <= len(rst) {
			// 判断结束下标是否越界
			if end > len(rst) {
				end = len(rst)
			}
			rstByPage = rst[start:end]
		} else {
			rstByPage = rst[0:0]
		}

		rst = rstByPage
	}

	// 设置已读标志
	for i, v := range rst {
		if utils.SortInIntSlice(msgReceivers, int(v.Autoid)) {
			item := &rst[i]
			item.Readed = true
		}
	}

	// 查询成功返回
	if req.PageSize > 0 {
		logger.GetLogger().Debugln("QueryNotice successed: %v", rst)
		appG.ResponseByPage(http.StatusOK, e.SUCCESS, rst, app.PageInfo{Page: req.Page, PageSize: req.PageSize, Total: total})
	} else {
		logger.GetLogger().Debugln("QueryNotice successed: %v", rst)
		appG.Response(http.StatusOK, e.SUCCESS, rst)
	}
}

// NoticeReadedReq 通知公告设置已读请求参数
type NoticeReadedReq struct {
	LoginID  int `form:"loginID" binding:"required"`  // 登录账号
	NoticeID int `form:"noticeID" binding:"required"` // 通知公告ID
}

// NoticeReaded 通知公告设置已读请求
// @Summary 通知公告设置已读请求
// @Produce json
// @Security ApiKeyAuth
// @Param loginID query int true "登录账号"
// @Param noticeID query int true "通知公告ID"
// @Success 200 {object} app.Response
// @Failure 500 {object} app.Response
// @Router /Common/NoticeReaded [post]
// @Tags 通用服务
func NoticeReaded(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req NoticeReadedReq
	if err := appG.C.ShouldBind(&req); err != nil {
		logger.GetLogger().Errorf("NoticeReaded failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	engine := db.GetEngine()
	// 获取登录账号所属会员信息
	var userAccount models.Useraccount
	if has, _ := engine.Join("LEFT", "LOGINACCOUNT", "LOGINACCOUNT.USERID = USERACCOUNT.USERID").
		Where("LOGINACCOUNT.LOGINID = ?", req.LoginID).Get(&userAccount); !has {
		// 查询失败
		logger.GetLogger().Errorf("NoticeReaded failed: %s", "获取登录账号所属会员ID失败")
		appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
		return
	}

	// 尝试获取指定已读数据
	msgReceiver := &models.Msgreceiver{Autoid: int32(req.NoticeID), Managerid: userAccount.Userid, Receivertype: 2}
	has, err := engine.Get(msgReceiver)
	if err != nil {
		// 执行失败
		logger.GetLogger().Errorf("NoticeReaded failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
		return
	}
	if has {
		// 找到记录则更新已读状态
		msgReceiver.Readstatus = 2
		if _, err := engine.Update(msgReceiver); err != nil {
			// 执行失败
			logger.GetLogger().Errorf("NoticeReaded failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
			return
		}
	} else {
		// 找不到记录则新建一条
		m := new(models.Msgreceiver)
		m.Autoid = int32(req.NoticeID)
		m.Managerid = userAccount.Userid
		m.Readstatus = 2
		m.Receivertype = 2
		// m.Updatetime = time.Now()
		if _, err := engine.Insert(m); err != nil {
			// 执行失败
			logger.GetLogger().Errorf("NoticeReaded failed: %s", err.Error())
			appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
			return
		}
	}

	// 执行成功
	logger.GetLogger().Debugln("NoticeReaded successed: %v", "ok")
	appG.Response(http.StatusOK, e.SUCCESS, "")
}
