package message

import (
	"github.com/gin-gonic/gin"
	"go-admin/app/admin/models"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools/app"
	"net/http"
	"time"
)

// SysMessageCreate 公告消息-新增
// @Summary 公告消息-新增
// @Tags 消息中心
// @Produce json
// @Accept json
// @Param request body models.SysMessageCreateReq true "新增公告消息模型"
// @Success 200 {object} models.SysMessageCreateResp
// @Router /api/v1/sys_message/create [post]
func SysMessageCreate(c *gin.Context) {
	var req models.SysMessageCreateReq

	// 1. 参数绑定
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	// 2. 解析时间
	var startTimePtr, endTimePtr *time.Time
	var parsedStartTime, parsedEndTime time.Time
	var err error

	if req.StartTime != "" {
		parsedStartTime, err = time.Parse("2006-01-02 15:04:05", req.StartTime)
		if err != nil {
			app.Error(c, http.StatusBadRequest, nil, "StartTime 格式错误，应为 YYYY-MM-DD HH:MM:SS:111")
			return
		}
		startTimePtr = &parsedStartTime
	}

	if req.EndTime != "" {
		parsedEndTime, err = time.Parse("2006-01-02 15:04:05", req.EndTime)
		if err != nil {
			app.Error(c, http.StatusBadRequest, nil, "EndTime 格式错误，应为 YYYY-MM-DD HH:MM:SS")
			return
		}
		endTimePtr = &parsedEndTime
	}

	if req.Status != 0 && req.Status != 1 {
		app.Error(c, http.StatusBadRequest, nil, "不支持的目标状态")
		return
	}

	// 3. 插入 system_message_config（公告）
	message := models.SystemMessageConfig{
		MessageType:     models.AnnouncementMessageType,
		Title:           req.Title,
		ContentTemplate: req.ContentTemplate,
		Level:           req.Level,
		DisplayMode:     req.DisplayMode,
		StartTime:       startTimePtr,
		EndTime:         endTimePtr,
		Status:          req.Status,
	}

	if err = orm.Eloquent.Create(&message).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "创建公告失败: "+err.Error())
		return
	}

	// 4. 插入 system_message_target
	for _, id := range req.TargetID {
		target := models.SystemMessageTarget{
			MessageConfigID: uint(message.ID),
			TargetType:      req.TargetType,
			TargetID:        id,
		}
		if err = orm.Eloquent.Create(&target).Error; err != nil {
			app.Error(c, http.StatusInternalServerError, nil, "接收对象配置失败: "+err.Error())
			return
		}
	}

	// 5. 判断是否需要立即下发用户消息
	needPushNow := (startTimePtr == nil || !parsedStartTime.After(time.Now())) && req.Status == 1
	if needPushNow {
		var userIDs []int64

		switch req.TargetType {
		case models.TargetTypeByAll: // 全员
			err = orm.Eloquent.Table("sys_user").Where("deleted_at IS NULL").Pluck("user_id", &userIDs).Error
			if err != nil {
				app.Error(c, http.StatusInternalServerError, nil, "获取全员用户失败: "+err.Error())
				return
			}
		case models.TargetTypeByRole: // 角色
			err = orm.Eloquent.Table("sys_user").
				Where("role_id in ? AND deleted_at IS NULL", req.TargetID).
				Pluck("user_id", &userIDs).Error
			if err != nil {
				app.Error(c, http.StatusInternalServerError, nil, "获取角色用户失败: "+err.Error())
				return
			}
		case models.TargetTypeByUser: // 单个用户
			if len(req.TargetID) != 0 {
				userIDs = req.TargetID
			}
		default:
			app.Error(c, http.StatusInternalServerError, nil, "接收对象类型有误，不在取值范围")
			return
		}

		// 构造 system_user_message 批量插入
		var userMessages []models.SystemUserMessage
		for _, uid := range userIDs {
			userMessages = append(userMessages, models.SystemUserMessage{
				UserID:          uid,
				MessageConfigID: uint(message.ID),
				MessageType:     models.AnnouncementMessageType,
				Title:           message.Title,
				Content:         message.ContentTemplate,
				IsRead:          false,
				IsVisible:       true,
			})
		}

		if len(userMessages) > 0 {
			if err = orm.Eloquent.Create(&userMessages).Error; err != nil {
				app.Error(c, http.StatusInternalServerError, nil, "写入用户消息失败: "+err.Error())
				return
			}
		}
	}

	// 6. 成功响应
	app.OK(c, models.SysMessageCreateResp{ID: message.ID}, "新增成功")
}

// SysMessageEdit 公告消息-编辑
// @Summary 公告消息-编辑
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.SysMessageEditReq true "编辑公告消息模型"
// @Success 200 {object} models.SysMessageCreateResp
// @Router /api/v1/sys_message/edit [post]
func SysMessageEdit(c *gin.Context) {
	var req models.SysMessageEditReq

	// 1. 参数绑定
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}
	if req.ID == 0 {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: 缺少ID")
		return
	}

	// 2. 查询原公告（草稿）
	var message models.SystemMessageConfig
	if err := orm.Eloquent.Where("id = ? AND message_type = ?", req.ID, models.AnnouncementMessageType).First(&message).Error; err != nil {
		app.Error(c, http.StatusBadRequest, nil, "公告不存在")
		return
	}
	if message.Status != models.MessageStatusOnDraft {
		app.Error(c, http.StatusBadRequest, nil, "仅草稿状态的公告可以编辑")
		return
	}

	// 3. 解析时间
	var startTimePtr, endTimePtr *time.Time
	var parsedStartTime, parsedEndTime time.Time
	var err error

	if req.StartTime != "" {
		parsedStartTime, err = time.Parse("2006-01-02 15:04:05", req.StartTime)
		if err != nil {
			app.Error(c, http.StatusBadRequest, nil, "StartTime 格式错误，应为 YYYY-MM-DD HH:MM:SS")
			return
		}
		startTimePtr = &parsedStartTime
	}
	if req.EndTime != "" {
		parsedEndTime, err = time.Parse("2006-01-02 15:04:05", req.EndTime)
		if err != nil {
			app.Error(c, http.StatusBadRequest, nil, "EndTime 格式错误，应为 YYYY-MM-DD HH:MM:SS")
			return
		}
		endTimePtr = &parsedEndTime
	}

	begin := orm.Eloquent.Begin()
	// 4. 更新公告主表
	update := map[string]interface{}{
		"title":            req.Title,
		"content_template": req.ContentTemplate,
		"level":            req.Level,
		"display_mode":     req.DisplayMode,
		"start_time":       startTimePtr,
		"end_time":         endTimePtr,
		"status":           req.Status,
	}
	if err := begin.Model(&models.SystemMessageConfig{}).Where("id = ?", req.ID).Updates(update).Error; err != nil {
		begin.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "更新公告失败: "+err.Error())
		return
	}

	// 5. 更新接收对象（删除再插入）
	if err := begin.Where("message_config_id = ?", req.ID).Delete(&models.SystemMessageTarget{}).Error; err != nil {
		begin.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "更新接收对象失败: "+err.Error())
		return
	}

	// 4. 插入 system_message_target
	for _, id := range req.TargetID {
		target := models.SystemMessageTarget{
			MessageConfigID: uint(message.ID),
			TargetType:      req.TargetType,
			TargetID:        id,
		}
		if err = begin.Create(&target).Error; err != nil {
			begin.Rollback()
			app.Error(c, http.StatusInternalServerError, nil, "接收对象配置失败: "+err.Error())
			return
		}
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("SysMessageDelete commit err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, nil, "编辑公告失败")
		return
	}

	// 6. 判断是否需要立即下发消息
	needPushNow := (startTimePtr == nil || !parsedStartTime.After(time.Now())) && req.Status == models.MessageStart
	if needPushNow {
		var userIDs []int64
		switch req.TargetType {
		case models.TargetTypeByAll:
			err = orm.Eloquent.Table("sys_user").
				Where("deleted_at IS NULL").
				Pluck("user_id", &userIDs).Error
		case models.TargetTypeByRole:
			err = orm.Eloquent.Table("sys_user").
				Where("role_id = ? AND deleted_at IS NULL", req.TargetID).
				Pluck("user_id", &userIDs).Error
		case models.TargetTypeByUser:
			if len(req.TargetID) != 0 {
				userIDs = req.TargetID
			}
		default:
			app.Error(c, http.StatusInternalServerError, nil, "接收对象类型无效")
			return
		}
		if err != nil {
			app.Error(c, http.StatusInternalServerError, nil, "获取用户失败: "+err.Error())
			return
		}

		// 构建用户消息记录
		var userMessages []models.SystemUserMessage
		for _, uid := range userIDs {
			userMessages = append(userMessages, models.SystemUserMessage{
				UserID:          uid,
				MessageConfigID: req.ID,
				MessageType:     models.AnnouncementMessageType,
				Title:           req.Title,
				Content:         req.ContentTemplate,
				IsRead:          false,
				IsVisible:       true,
			})
		}
		if len(userMessages) > 0 {
			if err := orm.Eloquent.Create(&userMessages).Error; err != nil {
				app.Error(c, http.StatusInternalServerError, nil, "写入用户消息失败: "+err.Error())
				return
			}
		}
	}

	app.OK(c, models.SysMessageCreateResp{ID: uint32(req.ID)}, "编辑成功")
}

// SysMessageSetStatus 公告消息-设置公告消息状态（启用/禁用）
// @Summary 公告消息-设置公告消息状态（启用/禁用）
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.SysMessageSetStatusReq true "状态更新请求"
// @Success 200 {object} app.Response
// @Router /api/v1/sys_message/set_status [post]
func SysMessageSetStatus(c *gin.Context) {
	var req models.SysMessageSetStatusReq
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	var config models.SystemMessageConfig
	if err := orm.Eloquent.Where("id = ? AND message_type = ?", req.ID, 1).First(&config).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "公告不存在")
		return
	}

	// 校验状态切换合法性
	switch req.Status {
	case 1: // 启用
		if config.Status != models.MessageStatusOnDraft && config.Status != models.MessageStatusOnDisable {
			app.Error(c, http.StatusBadRequest, nil, "只有草稿或禁用状态才能启用")
			return
		}
	case 2: // 禁用
		if config.Status != models.MessageStatusOnStart {
			app.Error(c, http.StatusBadRequest, nil, "只有启用状态才能禁用")
			return
		}
	default:
		app.Error(c, http.StatusBadRequest, nil, "不支持的目标状态")
		return
	}

	// 状态更新
	if err := orm.Eloquent.Model(&config).Update("status", req.Status).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "状态更新失败")
		return
	}

	// 状态逻辑处理
	if req.Status == models.MessageStart {
		// ✅ 启用逻辑：若 start_time 已开始 → 插入或恢复用户消息
		if config.StartTime == nil || config.StartTime.Before(time.Now()) {
			var target models.SystemMessageTarget
			if err := orm.Eloquent.Where("message_config_id = ?", config.ID).First(&target).Error; err != nil {
				app.Error(c, http.StatusInternalServerError, nil, "接收对象未配置")
				return
			}

			var userIDs []int64
			switch target.TargetType {
			case models.TargetTypeByAll: // 全员
				err := orm.Eloquent.Table("sys_user").Where("deleted_at IS NULL").Pluck("user_id", &userIDs).Error
				if err != nil {
					app.Error(c, http.StatusInternalServerError, nil, "获取全员用户失败: "+err.Error())
					return
				}
			case models.TargetTypeByRole: // 角色
				err := orm.Eloquent.Table("sys_user").
					Where("role_id = ? AND deleted_at IS NULL", target.TargetID).
					Pluck("user_id", &userIDs).Error
				if err != nil {
					app.Error(c, http.StatusInternalServerError, nil, "获取角色用户失败: "+err.Error())
					return
				}
			case models.TargetTypeByUser: // 单个用户
				if target.TargetType != 0 {
					userIDs = []int64{target.TargetID}
				}
			default:
				app.Error(c, http.StatusInternalServerError, nil, "接收对象类型有误，不在取值范围")
				return
			}

			// 已存在的 user_id
			var existedUserIDs []int64
			orm.Eloquent.Table("system_user_message").
				Where("message_config_id = ? AND user_id IN (?)", config.ID, userIDs).
				Pluck("user_id", &existedUserIDs)

			existedSet := make(map[int64]struct{})
			for _, uid := range existedUserIDs {
				existedSet[uid] = struct{}{}
			}

			var toInsert []models.SystemUserMessage
			var toUpdateIDs []int64

			for _, uid := range userIDs {
				if _, ok := existedSet[uid]; ok {
					toUpdateIDs = append(toUpdateIDs, uid)
				} else {
					toInsert = append(toInsert, models.SystemUserMessage{
						UserID:          uid,
						MessageConfigID: uint(config.ID),
						MessageType:     1,
						Title:           config.Title,
						Content:         config.ContentTemplate,
						IsRead:          false,
						IsVisible:       true,
					})
				}
			}

			if len(toInsert) > 0 {
				_ = orm.Eloquent.Create(&toInsert).Error
			}
			if len(toUpdateIDs) > 0 {
				_ = orm.Eloquent.Model(&models.SystemUserMessage{}).
					Where("message_config_id = ? AND user_id IN (?)", config.ID, toUpdateIDs).
					Update("is_visible", true).Error
			}
		}
	} else if req.Status == models.MessageStop {
		// ✅ 禁用逻辑：隐藏用户已发送的公告消息
		_ = orm.Eloquent.Model(&models.SystemUserMessage{}).
			Where("message_config_id = ?", config.ID).
			Update("is_visible", false).Error
	}

	app.OK(c, nil, "状态更新成功")
}

// SysMessageDelete 公告消息-删除（草稿/禁用/过期状态可删）
// @Summary 公告消息-删除（草稿/禁用/过期状态可删）
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.SysMessageDeleteReq true "删除公告请求"
// @Success 200 {object} app.Response
// @Router /api/v1/sys_message/delete [post]
func SysMessageDelete(c *gin.Context) {
	var req models.SysMessageDeleteReq
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	var config models.SystemMessageConfig
	if err := orm.Eloquent.Where("id = ? AND message_type = ?", req.ID, models.AnnouncementMessageType).
		First(&config).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "公告不存在")
		return
	}

	if config.Status != models.MessageStatusOnDraft && config.Status != models.MessageStatusOnDisable &&
		config.Status != models.MessageStatusOnExpire {
		app.Error(c, http.StatusBadRequest, nil, "仅草稿、禁用、已过期状态可删除")
		return
	}

	begin := orm.Eloquent.Begin()
	// 删除主配置（软删除）
	if err := begin.Delete(&config).Error; err != nil {
		begin.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
		return
	}

	// 删除接收对象配置
	if err := begin.Where("message_config_id = ?", config.ID).
		Delete(&models.SystemMessageTarget{}).Error; err != nil {
		begin.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
		return
	}

	// ✅ 更新用户消息为不可见（但保留）
	if err := begin.Model(&models.SystemUserMessage{}).
		Where("message_config_id = ?", config.ID).
		Update("is_visible", false).Error; err != nil {
		begin.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
		return
	}

	err := begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("SysMessageDelete commit err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
		return
	}

	app.OK(c, nil, "删除成功")
}

// SysMessageList 公告消息-列表
// @Summary 公告消息-列表
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.SysMessageListReq true "查询条件"
// @Success 200 {object} models.SysMessageListResp
// @Router /api/v1/sys_message/list [post]
func SysMessageList(c *gin.Context) {
	var req models.SysMessageListReq
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	// 分页默认处理
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	db := orm.Eloquent.Table("system_message_config").
		Where("message_type = ?", 1)

	if req.Title != "" {
		db = db.Where("title LIKE ?", "%"+req.Title+"%")
	}
	if req.Level != 0 {
		db = db.Where("level = ?", req.Level)
	}
	if req.DisplayMode != 0 {
		db = db.Where("display_mode = ?", req.DisplayMode)
	}
	if req.Status != 0 {
		db = db.Where("status = ?", req.Status)
	}
	if req.TargetType != 0 {
		subQuery := orm.Eloquent.Table("system_message_target").
			Select("message_config_id").
			Where("target_type = ?", req.TargetType)
		db = db.Where("id IN (?)", subQuery)
	}

	var total int64
	if err := db.Count(&total).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "统计失败: "+err.Error())
		return
	}

	var list []models.SystemMessageConfig
	if err := db.
		Order("created_at DESC").
		Offset((req.Page - 1) * req.PageSize).
		Limit(req.PageSize).
		Find(&list).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询失败: "+err.Error())
		return
	}

	// 转换为展示数据
	var items []models.SysAnnouncementItem
	for _, cfg := range list {
		item := models.SysAnnouncementItem{
			ID:              cfg.ID,
			Title:           cfg.Title,
			ContentTemplate: cfg.ContentTemplate,
			Level:           cfg.Level,
			DisplayMode:     cfg.DisplayMode,
			StartTime:       cfg.StartTime,
			EndTime:         cfg.EndTime,
			Status:          cfg.Status,
			CreatedAt:       cfg.CreatedAt,
			UpdatedAt:       cfg.UpdatedAt,
		}

		// 查询该消息的所有接收对象记录
		var targets []models.SystemMessageTarget
		if err := orm.Eloquent.
			Where("message_config_id = ?", cfg.ID).
			Find(&targets).Error; err == nil && len(targets) > 0 {
			// 假设所有 target_type 都一致（如不是，可按需修改）
			item.TargetType = targets[0].TargetType
			for _, t := range targets {
				item.TargetID = append(item.TargetID, t.TargetID)
			}
		}

		items = append(items, item)
	}

	resp := models.SysMessageListResp{
		List:     items,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}

	app.OK(c, resp, "查询成功")
}

// SysMessageDetail 公告消息-详情
// @Summary 公告消息-详情
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.SysMessageDetailReq true "公告消息ID"
// @Success 200 {object} models.SysMessageDetailResp
// @Router /api/v1/sys_message/detail [post]
func SysMessageDetail(c *gin.Context) {
	var req models.SysMessageDetailReq
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	var config models.SystemMessageConfig
	if err := orm.Eloquent.Where("id = ? AND message_type = 1", req.ID).First(&config).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "公告不存在")
		return
	}

	var targets []models.SystemMessageTarget
	_ = orm.Eloquent.Where("message_config_id = ?", config.ID).First(&targets)

	resp := models.SysMessageDetailResp{
		ID:          uint(config.ID),
		Title:       config.Title,
		Content:     config.ContentTemplate,
		Level:       config.Level,
		DisplayMode: config.DisplayMode,
		Status:      config.Status,
		CreatedAt:   config.CreatedAt,
		UpdatedAt:   config.UpdatedAt,
		StartTime:   config.StartTime,
		EndTime:     config.EndTime,
	}

	if len(targets) != 0 {
		// 假设所有 target_type 都一致（如不是，可按需修改）
		resp.TargetType = targets[0].TargetType
		for _, t := range targets {
			resp.TargetID = append(resp.TargetID, t.TargetID)
		}
	}

	app.OK(c, resp, "查询成功")
}
