package controller

import (
	"strconv"

	"com.zhangmeng/go-wechat/common"
	"com.zhangmeng/go-wechat/models"
	"com.zhangmeng/go-wechat/service"
	"com.zhangmeng/go-wechat/service/impl"
	"github.com/gin-gonic/gin"
)

// GroupController 群组控制器
type GroupController struct {
	groupService service.IGroupService
}

// NewGroupController 创建控制器实例
func NewGroupController() *GroupController {
	return &GroupController{
		groupService: &impl.GroupService{},
	}
}

// RegisterGroupRoute 注册群组相关路由
func RegisterGroupRoute(r *gin.RouterGroup) {
	gc := NewGroupController()

	// 所有群组接口都需要登录
	apiGroup := r.Group("/api")
	apiGroup.Use(common.JWTAuth())
	{
		// 群组管理
		groupGroup := apiGroup.Group("/group")
		{
			groupGroup.POST("/create", gc.CreateGroup)
			groupGroup.PUT("/update", gc.UpdateGroup)
			groupGroup.DELETE("/dissolve/:id", gc.DissolveGroup)
			groupGroup.GET("/info/:id", gc.GetGroupInfo)
			groupGroup.GET("/search", gc.SearchGroups)
			groupGroup.GET("/list", gc.GetUserGroups)
			groupGroup.POST("/join-by-code", gc.JoinGroupByCode)
		}

		// 群成员管理
		memberGroup := apiGroup.Group("/group-member")
		{
			memberGroup.POST("/invite", gc.InviteToGroup)
			memberGroup.POST("/leave", gc.LeaveGroup)
			memberGroup.DELETE("/kick", gc.KickGroupMember)
			memberGroup.GET("/list/:id", gc.GetGroupMembers)
			memberGroup.PUT("/nickname", gc.UpdateGroupNickname)
			memberGroup.POST("/mute", gc.SetGroupMute)
			memberGroup.POST("/transfer", gc.TransferGroupOwner)
			memberGroup.POST("/set-admin", gc.SetGroupAdmin)
		}

		// 入群申请管理
		joinReqGroup := apiGroup.Group("/group-join")
		{
			joinReqGroup.POST("/handle", gc.HandleJoinRequest)
			joinReqGroup.GET("/requests/:id", gc.GetGroupJoinRequests)
			joinReqGroup.GET("/my-requests", gc.GetMyJoinRequests)
			joinReqGroup.GET("/pending-invites", gc.GetPendingInvites)
			joinReqGroup.GET("/pending-invites-count", gc.GetPendingInvitesCount)
		}
	}
}

// ============================================
// 群组管理接口
// ============================================

// CreateGroup 创建群组
func (gc *GroupController) CreateGroup(c *gin.Context) {
	var req models.CreateGroupRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	groupInfo, err := gc.groupService.CreateGroup(userID, &req)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(groupInfo))
}

// UpdateGroup 更新群组信息
func (gc *GroupController) UpdateGroup(c *gin.Context) {
	var req models.UpdateGroupRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.UpdateGroup(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("群组信息更新成功"))
}

// DissolveGroup 解散群组
func (gc *GroupController) DissolveGroup(c *gin.Context) {
	groupIDStr := c.Param("id")
	groupID, err := strconv.ParseUint(groupIDStr, 10, 64)
	if err != nil {
		c.JSON(200, common.Fail("群组ID格式错误"))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.DissolveGroup(userID, groupID); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("群组已解散"))
}

// GetGroupInfo 获取群组信息
func (gc *GroupController) GetGroupInfo(c *gin.Context) {
	groupIDStr := c.Param("id")
	groupID, err := strconv.ParseUint(groupIDStr, 10, 64)
	if err != nil {
		c.JSON(200, common.Fail("群组ID格式错误"))
		return
	}

	userID := c.MustGet("userID").(uint64)

	groupInfo, err := gc.groupService.GetGroupInfo(userID, groupID)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(groupInfo))
}

// SearchGroups 搜索群组
func (gc *GroupController) SearchGroups(c *gin.Context) {
	keyword := c.Query("keyword")
	if keyword == "" {
		c.JSON(200, common.Fail("搜索关键词不能为空"))
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	groups, total, err := gc.groupService.SearchGroups(keyword, page, pageSize)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(gin.H{
		"list":      groups,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	}))
}

// GetUserGroups 获取用户加入的群组列表
func (gc *GroupController) GetUserGroups(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	userID := c.MustGet("userID").(uint64)

	groups, total, err := gc.groupService.GetUserGroups(userID, page, pageSize)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(gin.H{
		"list":      groups,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	}))
}

// JoinGroupByCode 通过邀请码加入群组
func (gc *GroupController) JoinGroupByCode(c *gin.Context) {
	var req models.JoinGroupByCodeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.JoinGroupByCode(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("加入群组成功"))
}

// ============================================
// 群成员管理接口
// ============================================

// InviteToGroup 邀请加入群组
func (gc *GroupController) InviteToGroup(c *gin.Context) {
	var req models.InviteToGroupRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.InviteToGroup(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("邀请成功"))
}

// LeaveGroup 退出群组
func (gc *GroupController) LeaveGroup(c *gin.Context) {
	var req struct {
		GroupID uint64 `json:"group_id" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.LeaveGroup(userID, req.GroupID); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("已退出群组"))
}

// KickGroupMember 踢出群成员
func (gc *GroupController) KickGroupMember(c *gin.Context) {
	var req struct {
		GroupID  uint64 `json:"group_id" binding:"required"`
		MemberID uint64 `json:"member_id" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.KickGroupMember(userID, req.GroupID, req.MemberID); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("已将成员移出群组"))
}

// GetGroupMembers 获取群组成员列表
func (gc *GroupController) GetGroupMembers(c *gin.Context) {
	groupIDStr := c.Param("id")
	groupID, err := strconv.ParseUint(groupIDStr, 10, 64)
	if err != nil {
		c.JSON(200, common.Fail("群组ID格式错误"))
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "50"))

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 50
	}

	members, total, err := gc.groupService.GetGroupMembers(groupID, page, pageSize)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(gin.H{
		"list":      members,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	}))
}

// UpdateGroupNickname 修改群内昵称
func (gc *GroupController) UpdateGroupNickname(c *gin.Context) {
	var req models.UpdateGroupNicknameRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.UpdateGroupNickname(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("昵称修改成功"))
}

// SetGroupMute 设置群成员禁言
func (gc *GroupController) SetGroupMute(c *gin.Context) {
	var req models.SetGroupMuteRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.SetGroupMute(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	muteStatus := "取消禁言"
	if req.IsMuted {
		muteStatus = "禁言"
	}
	c.JSON(200, common.SuccessMsg(muteStatus+"成功"))
}

// TransferGroupOwner 转让群主
func (gc *GroupController) TransferGroupOwner(c *gin.Context) {
	var req models.TransferGroupOwnerRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.TransferGroupOwner(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("群主转让成功"))
}

// SetGroupAdmin 设置/取消管理员
func (gc *GroupController) SetGroupAdmin(c *gin.Context) {
	var req models.SetGroupAdminRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.SetGroupAdmin(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	adminStatus := "取消管理员"
	if req.IsAdmin {
		adminStatus = "设为管理员"
	}
	c.JSON(200, common.SuccessMsg(adminStatus+"成功"))
}

// ============================================
// 入群申请管理接口
// ============================================

// HandleJoinRequest 处理入群申请
func (gc *GroupController) HandleJoinRequest(c *gin.Context) {
	var req models.HandleJoinRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(200, common.Fail("参数错误: "+err.Error()))
		return
	}

	userID := c.MustGet("userID").(uint64)

	if err := gc.groupService.HandleJoinRequest(userID, &req); err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.SuccessMsg("处理成功"))
}

// GetGroupJoinRequests 获取群组的入群申请
func (gc *GroupController) GetGroupJoinRequests(c *gin.Context) {
	groupIDStr := c.Param("id")
	groupID, err := strconv.ParseUint(groupIDStr, 10, 64)
	if err != nil {
		c.JSON(200, common.Fail("群组ID格式错误"))
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	userID := c.MustGet("userID").(uint64)

	requests, total, err := gc.groupService.GetGroupJoinRequests(userID, groupID, page, pageSize)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(gin.H{
		"list":      requests,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	}))
}

// GetPendingInvites 获取待处理的群邀请列表
func (gc *GroupController) GetPendingInvites(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	userID := c.MustGet("userID").(uint64)

	requests, total, err := gc.groupService.GetPendingInvites(userID, page, pageSize)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(gin.H{
		"list":      requests,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	}))
}

// GetPendingInvitesCount 获取待处理邀请数量
func (gc *GroupController) GetPendingInvitesCount(c *gin.Context) {
	userID := c.MustGet("userID").(uint64)

	count := gc.groupService.GetPendingInvitesCount(userID)

	c.JSON(200, common.Success(gin.H{
		"count": count,
	}))
}

// GetMyJoinRequests 获取我的入群申请记录
func (gc *GroupController) GetMyJoinRequests(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	userID := c.MustGet("userID").(uint64)

	requests, total, err := gc.groupService.GetMyJoinRequests(userID, page, pageSize)
	if err != nil {
		c.JSON(200, common.Fail(err.Error()))
		return
	}

	c.JSON(200, common.Success(gin.H{
		"list":      requests,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	}))
}