package controller

import (
	"github.com/mitchellh/mapstructure"
	"log/slog"
	"slgserver/constant"
	"slgserver/db"
	"slgserver/middleware"
	"slgserver/net"
	"slgserver/server/slgserver/model"
	"slgserver/server/slgserver/proto"
)

var DefaultWar = War{}

type War struct {
}

func (this *War) InitRouter(r *net.Router) {
	g := r.Group("war").Use(middleware.ElapsedTime(),
		middleware.Log(), middleware.CheckRole())
	g.AddRouter("report", this.report)
	g.AddRouter("read", this.read)
}

func (this *War) report(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
	reqObj := &proto.WarReportReq{}
	rspObj := &proto.WarReportRsp{}

	mapstructure.Decode(req.Body.Msg, reqObj)
	rsp.Body.Msg = rspObj
	rsp.Body.Code = constant.OK

	r, _ := req.Conn.GetProperty("role")
	role := r.(*model.Role)

	//查询最近30条战报吧
	l := make([]*model.WarReport, 0)
	err := db.MasterDB.Table(model.WarReport{}).Where("a_rid=? or d_rid=?",
		role.RId, role.RId).Desc("ctime").Limit(100, 0).Find(&l)

	if err != nil {
		slog.Warn("db error", "error", err)
		rsp.Body.Code = constant.DBError
		return
	}

	rspObj.List = make([]proto.WarReport, len(l))
	for i, v := range l {
		rspObj.List[i] = v.ToProto().(proto.WarReport)
	}
}

func (this *War) read(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
	reqObj := &proto.WarReadReq{}
	rspObj := &proto.WarReadRsp{}

	mapstructure.Decode(req.Body.Msg, reqObj)
	rsp.Body.Msg = rspObj
	rsp.Body.Code = constant.OK
	rspObj.Id = reqObj.Id

	r, _ := req.Conn.GetProperty("role")
	role := r.(*model.Role)

	if reqObj.Id == 0 {
		// 批量标记所有战报为已读 - 使用事务优化
		m := model.WarReport{AttackIsRead: true, DefenseIsRead: true}
		sess := db.MasterDB.NewSession()
		defer sess.Close()

		if err := sess.Begin(); err != nil {
			slog.Error("begin transaction error", "error", err)
			rsp.Body.Code = constant.DBError
			return
		}

		// 更新攻击方战报
		if _, err := sess.Table(model.WarReport{}).Where("a_rid=?", role.RId).Cols("a_is_read").Update(m); err != nil {
			slog.Error("update attack reports error", "error", err)
			sess.Rollback()
			rsp.Body.Code = constant.DBError
			return
		}

		// 更新防守方战报
		if _, err := sess.Table(model.WarReport{}).Where("d_rid=?", role.RId).Cols("d_is_read").Update(m); err != nil {
			slog.Error("update defense reports error", "error", err)
			sess.Rollback()
			rsp.Body.Code = constant.DBError
			return
		}

		if err := sess.Commit(); err != nil {
			slog.Error("commit transaction error", "error", err)
			rsp.Body.Code = constant.DBError
			return
		}
	} else {
		wr := &model.WarReport{}
		ok, err := db.MasterDB.Table(model.WarReport{}).Where("id=?",
			reqObj.Id).Get(wr)

		if err != nil {
			slog.Warn("db error", "error", err)
			rsp.Body.Code = constant.DBError
			return
		}

		if ok {
			if wr.AttackRid == role.RId {
				wr.AttackIsRead = true
				db.MasterDB.Table(wr).ID(wr.Id).Cols("a_is_read").Update(wr)
				rsp.Body.Code = constant.OK
			} else if wr.DefenseRid == role.RId {
				wr.DefenseIsRead = true
				db.MasterDB.Table(wr).ID(wr.Id).Cols("d_is_read").Update(wr)
				rsp.Body.Code = constant.OK
			} else {
				rsp.Body.Code = constant.InvalidParam
			}
		}
	}

}
