package user

import (
	"encoding/xml"
	"eta/eta_mini_ht_api/common/component/cache"
	logger "eta/eta_mini_ht_api/common/component/log"
	"eta/eta_mini_ht_api/common/exception"
	authUtils "eta/eta_mini_ht_api/common/utils/auth"
	"eta/eta_mini_ht_api/controllers"
	userService "eta/eta_mini_ht_api/domian/user"
	"eta/eta_mini_ht_api/service/auth"
	"eta/eta_mini_ht_api/service/user"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// UserController Operations about Users
type UserController struct {
	controllers.BaseController
	redis *cache.RedisCache
}

func (u *UserController) Prepare() {
	u.redis = cache.GetInstance()
}

type LoginCode struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
}

// Get @Title GetAll
// @Description get all Users
// @Success 200 {object} models.User
// @router / [get]
func (u *UserController) Get() {
	logger.Warn("查询用户列表:%s")
	fmt.Print("查询用户列表")
	u.ServeJSON()
}

type FeedbackReq struct {
	Mobile  string `json:"mobile"`
	Message string `json:"message"`
}

type FollowAnalystReq struct {
	AnalystId   int    `json:"analystId"`
	AnalystName string `json:"analystName"`
	FollowType  string `json:"followType"`
	Mobile      string `json:"mobile"`
	ByName      bool   `json:"byName"`
}

// Feedback  用户意见反馈
// @Summary 用户意见反馈
// @Description 用户意见反馈
// @Success 200 {object} controllers.BaseResponse
// @router /feedback [post]
func (u *UserController) Feedback() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("提交反馈失败")
		feedback := new(FeedbackReq)
		u.GetPostParams(feedback)
		if !authUtils.IsValidMobile(feedback.Mobile) {
			u.FailedResult("手机号非法", result)
			err = exception.New(exception.IllegalPhoneNumber)
			return
		}
		var userInfo user.User
		userInfo = u.Data["user"].(user.User)
		if userInfo.Mobile != feedback.Mobile {
			u.FailedResult("非当前用户的手机号提交", result)
			err = exception.New(exception.NotCurrentUserError)
			return
		}
		if feedback.Message == "" {
			u.FailedResult("反馈信息不能为空", result)
			err = exception.New(exception.FeedBackMsgEmpty)
			return
		}
		err = user.FeedBack(userInfo.Id, feedback.Mobile, feedback.Message)
		if err != nil {
			err = exception.New(exception.FeedBackError)
			u.FailedResult("提交反馈失败", result)
			return
		}
		u.SuccessResult("提交反馈成功", nil, result)
		return
	})
}

type BatchFollowResp struct {
	FollowStatus string                  `json:"followStatus"`
	List         []userService.FollowDTO `json:"list"`
}
type FollowResp struct {
	AnalystId    int    `json:"analystId"`
	FollowedType string `json:"FollowedType"`
}

type FollowAnalystsReq struct {
	AnalystNames string `json:"analystNames"`
	FollowType   string `json:"followType"`
	Mobile       string `json:"mobile"`
}

// FollowAnalysts  批量关注研究员
// @Summary 批量关注研究员
// @Description 批量关注研究员
// @Success 200 {object} controllers.BaseResponse
// @router /followAnalysts [post]
func (u *UserController) FollowAnalysts() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("批量关注失败")
		followAnalyst := new(FollowAnalystsReq)
		u.GetPostParams(followAnalyst)
		if !authUtils.IsValidMobile(followAnalyst.Mobile) {
			u.FailedResult("手机号非法", result)
			err = exception.New(exception.IllegalPhoneNumber)
			return
		}
		var userInfo user.User
		userInfo = u.Data["user"].(user.User)
		if userInfo.Mobile != followAnalyst.Mobile {
			u.FailedResult("非当前用户的手机号提交", result)
			err = exception.New(exception.NotCurrentUserError)
			return
		}
		if !checkFollowType(followAnalyst.FollowType) {
			u.FailedResult("关注状态非法", result)
			err = exception.New(exception.IllegalFollowType)
			return
		}
		var msg string
		switch followAnalyst.FollowType {
		case "following":
			msg = "批量关注研究员"
		case "unfollowed":
			msg = "批量取消关注研究员"
		}
		var nameList []string
		names := followAnalyst.AnalystNames
		if strings.HasPrefix(names, ",") {
			names = names[1:]
		}
		if strings.HasSuffix(names, ",") {
			names = names[0 : len(names)-1]
		}
		if names == "" {
			nameList = []string{}
		} else {
			nameList = strings.Split(names, ",")
		}
		for i := 0; i < len(nameList); i++ {
			nameList[i] = strings.TrimSpace(nameList[i])
			if nameList[i] == "" {
				u.FailedResult("通过研究员姓名关注失败", result)
				err = exception.New(exception.AnalystNameEmptyError)
				return
			}
		}
		err = user.FollowAnalystsByName(userInfo.Id, nameList, followAnalyst.FollowType)
		if err != nil {
			u.FailedResult(msg+"失败", result)
			return
		}
		u.SuccessResult(msg+"成功", nil, result)
		return
	})
}

// CheckFollowStatus  获取关注状态
// @Summary 获取关注状态
// @Description 获取关注状态
// @Success 200 {object} controllers.BaseResponse
// @router /checkFollowStatus [get]
func (u *UserController) CheckFollowStatus(names string) {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取关注状态失败")
		var userInfo user.User
		userInfo = u.Data["user"].(user.User)
		var nameList []string
		if strings.HasPrefix(names, ",") {
			names = names[1:len(names)]
		}
		if strings.HasSuffix(names, ",") {
			names = names[0 : len(names)-1]
		}
		if names == "" {
			nameList = []string{}
		} else {
			nameList = strings.Split(names, ",")
		}
		for i := 0; i < len(nameList); i++ {
			nameList[i] = strings.TrimSpace(nameList[i])
		}
		list, err := user.CheckFollowStatusByNames(userInfo.Id, nameList)
		status := true
		data := BatchFollowResp{
			List: list,
		}
		for i := 0; i < len(list); i++ {
			if !checkFollowing(list[i].FollowType) {
				status = false
				break
			}
		}
		if status {
			data.FollowStatus = "following"
		} else {
			data.FollowStatus = "unfollowed"
		}
		if err != nil {
			u.FailedResult("获取关注状态失败", result)
			return
		}
		u.SuccessResult("获取关注状态成功", data, result)
		return
	})
}
func checkFollowing(followType string) bool {
	return followType == "following"
}

// FollowAnalyst  关注研究员
// @Summary 关注研究员
// @Description 关注研究员
// @Success 200 {object} controllers.BaseResponse
// @router /followAnalyst [post]
func (u *UserController) FollowAnalyst() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("")
		followAnalyst := new(FollowAnalystReq)
		u.GetPostParams(followAnalyst)
		if !authUtils.IsValidMobile(followAnalyst.Mobile) {
			u.FailedResult("手机号非法", result)
			err = exception.New(exception.IllegalPhoneNumber)
			return
		}
		var userInfo user.User
		userInfo = u.Data["user"].(user.User)
		if userInfo.Mobile != followAnalyst.Mobile {
			u.FailedResult("非当前用户的手机号提交", result)
			err = exception.New(exception.NotCurrentUserError)
			return
		}
		if !checkFollowType(followAnalyst.FollowType) {
			u.FailedResult("关注状态非法", result)
			err = exception.New(exception.IllegalFollowType)
			return
		}
		var msg string
		switch followAnalyst.FollowType {
		case "following":
			msg = "关注研究员"
		case "unfollowed":
			msg = "取消关注研究员"
		}
		if followAnalyst.ByName {
			logger.Info("通过研究员姓名关注")
			if followAnalyst.AnalystName == "" {
				u.FailedResult("通过研究员姓名关注失败", result)
				err = exception.New(exception.AnalystNameEmptyError)
				return
			}
			err = user.FollowAnalystByName(userInfo.Id, followAnalyst.AnalystName, followAnalyst.FollowType)
		} else {
			if followAnalyst.AnalystId <= 0 {
				u.FailedResult("通过研究员姓名关注失败", result)
				err = exception.New(exception.IllegalAnalystIdError)
				return
			}
			err = user.FollowAnalyst(userInfo.Id, followAnalyst.AnalystId, followAnalyst.FollowType)
		}
		if err != nil {
			u.FailedResult(msg+"失败", result)
			return
		}
		resp := FollowResp{
			AnalystId:    followAnalyst.AnalystId,
			FollowedType: followAnalyst.FollowType,
		}
		u.SuccessResult(msg+"成功", resp, result)
		return
	})
}

func checkFollowType(followType string) bool {
	return followType == "following" || followType == "unfollowed"
}

// FollowingAnalysts  关注研究员
// @Summary 关注研究员
// @Description 关注研究员
// @Success 200 {object} controllers.BaseResponse
// @router /followingAnalysts [get]
func (u *UserController) FollowingAnalysts(analystId int) {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("关注研究员列表失败")
		fmt.Println(analystId)
		userInfo := u.Data["user"].(user.User)
		detail, err := user.GetAnalystDetail(userInfo.Id, analystId)
		if err != nil {
			u.FailedResult("关注研究员失败", result)
			return
		}
		u.SuccessResult("关注研究员成功", detail, result)
		return
	})
}

type UserProfileReq struct {
	UserName string `json:"userName"`
	Mobile   string `json:"mobile"`
}

// Profile  获取用户信息
// @Summary 获取用户信息
// @Description 获取用户信息
// @Success 200 {object} controllers.BaseResponse
// @router /profile [get]
func (u *UserController) Profile() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取用户信息详情失败")
		userInfo := u.Data["user"].(user.User)
		u.SuccessResult("获取研究员详情成功", covertToUserProfile(userInfo), result)
		return
	})
}

// FollowingAnalystList  获取关注动态列表
// @Summary 获取关注动态列表
// @Description 获取关注动态列表
// @Success 200 {object} controllers.BaseResponse
// @router /followingAnalystList [get]
func (u *UserController) FollowingAnalystList() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取研究员详情失败")
		userInfo := u.Data["user"].(user.User)
		detail, err := user.GetFollowingAnalystList(userInfo.Id)
		if err != nil {
			u.FailedResult("获取关注研究员列表失败", result)
			return
		}
		u.SuccessResult("获取关注研究员列表成功", detail, result)
		return
	})
}

// UnReadMessageList  获取未读消息
// @Summary 获取未读消息
// @Description 获取未读消息
// @Success 200 {object} controllers.BaseResponse
// @router /message [get]
func (u *UserController) UnReadMessageList() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取我的未读消息失败")
		userInfo := u.Data["user"].(user.User)
		messages, err := user.GetUnReadMessageList(userInfo.Id)
		if err != nil {
			u.FailedResult("获取我的未读消息失败", result)
			return
		}
		u.SuccessResult("获取我的未读消息成功", messages, result)
		return
	})
}

type ReadMessageReq struct {
	AnalystId int `json:"analystId"`
	MessageId int `json:"MessageId"`
}

// ReadMessage  获取未读消息
// @Summary 获取未读消息
// @Description 获取未读消息
// @Success 200 {object} controllers.BaseResponse
// @router /readMessage [post]
func (u *UserController) ReadMessage() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取我的未读消息失败")
		readMessageReq := new(ReadMessageReq)
		u.GetPostParams(readMessageReq)
		if readMessageReq.MessageId <= 0 {
			logger.Error("消息Id非法")
			err = exception.New(exception.IllegalMessageId)
			u.FailedResult("已读消息失败", result)
			return
		}
		userInfo := u.Data["user"].(user.User)
		if user.ReadMessage(userInfo.Id, readMessageReq.MessageId) {
			u.SuccessResult("已读消息成功", nil, result)
			return
		} else {
			err = exception.New(exception.ReadMessageFailed)
			u.FailedResult("已读消息失败", result)
			return
		}
	})
}

// ReadMessages  获取未读消息
// @Summary 获取未读消息
// @Description 获取未读消息
// @Success 200 {object} controllers.BaseResponse
// @router /readMessages [post]
func (u *UserController) ReadMessages() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取我的未读消息失败")
		readMessageReq := new(ReadMessageReq)
		u.GetPostParams(readMessageReq)
		if readMessageReq.AnalystId <= 0 {
			logger.Error("研究员Id非法")
			err = exception.New(exception.IllegalAnalystId)
			u.FailedResult("已读消息失败", result)
			return
		}
		userInfo := u.Data["user"].(user.User)
		if user.ReadMessages(userInfo.Id, readMessageReq.AnalystId) {
			u.SuccessResult("已读消息成功", nil, result)
			return
		} else {
			err = exception.New(exception.ReadMessageFailed)
			u.FailedResult("已读消息失败", result)
			return
		}
	})
}
func covertToUserProfile(user user.User) UserProfileReq {
	return UserProfileReq{
		UserName: user.Username,
		Mobile:   user.Mobile,
	}
}

// ReadMessages  绑定微信公众号
// @Summary 绑定微信公众号
// @Description 绑定微信公众号
// @Success 200 {object} controllers.BaseResponse
// @router /bind_gzh [post]
func (u *UserController) BindGzh() {
	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
		result = u.InitWrapData("获取我的未读消息失败")
		bindReq := new(BindGzhReq)
		u.GetPostParams(bindReq)
		code := bindReq.Code
		isBind, err := auth.BindWxGzh(code)
		if err != nil {
			logger.Error("绑定公众号失败:%v", err)
			u.FailedResult("绑定公众号失败", result)
			return
		}
		u.SuccessResult("绑定成功", IsBindGzhRes{
			IsBind: isBind,
		}, result)
		return
	})
}

type IsBindGzhRes struct {
	IsBind bool `json:"isBind"`
}

type BindGzhReq struct {
	Code string `json:"Code"`
}

// Notify  微信公众号回调
// @Summary 微信公众号回调
// @Description 微信公众号回调
// @Success 200 {object} controllers.BaseResponse
// @router /wx/notify [get,post]
func (u *UserController) Notify() {
	echostr := u.GetString("echostr")
	method := u.Ctx.Input.Method()
	if method == "POST" {
		body := u.Ctx.Input.RequestBody
		item := new(Notify)
		err := xml.Unmarshal(body, &item)
		if err != nil {
			logger.Info("xml.Unmarshal:" + err.Error())
		}
		contactMsg := "你好，欢迎关注期海通行-投研点金!"

		var openId, returnResult string
		if item.MsgType != "" {
			openId = item.FromUserName
		}
		xmlTpl := `<xml>
		<ToUserName><![CDATA[%s]]></ToUserName>
		<FromUserName><![CDATA[%s]]></FromUserName>
		<CreateTime>%s</CreateTime>
		<MsgType><![CDATA[text]]></MsgType>
		<Content><![CDATA[%s]]></Content>
		</xml>`
		createTime := strconv.FormatInt(time.Now().Unix(), 10)
		// WxId := "gh_5dc508325c6f" // 弘则投研公众号原始id
		xmlTpl = fmt.Sprintf(xmlTpl, openId, auth.HT_WX_ID, createTime, contactMsg)

		if item.MsgType == "event" {
			switch item.Event {
			case "subscribe":
				fmt.Println("关注")
				go auth.BindWxGzhByOpenId(openId)
			case "unsubscribe":
				fmt.Println("取消关注")
				go auth.UnSubscribeWxGzhByOpenId(openId)
			case "CLICK":
				//returnResult = xmlTpl
			default:
				logger.Info("wechat notify event:" + item.Event)
			}
			u.Ctx.WriteString(xmlTpl)
		} else {
			returnResult = xmlTpl
		}
		u.Ctx.WriteString(returnResult)
	} else {
		u.Ctx.WriteString(echostr)
	}
}

type Notify struct {
	ToUserName   string `xml:"ToUserName"`
	FromUserName string `xml:"FromUserName"`
	CreateTime   int    `xml:"CreateTime"`
	MsgType      string `xml:"MsgType"`
	Event        string `xml:"Event"`
	EventKey     string `xml:"EventKey"`
	Content      string `xml:"Content"`
}
