package message

import (
	"encoding/json"
	"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"
)

// BusMessageCreate 业务消息-新增
// @Summary 业务消息-新增
// @Tags 消息中心
// @Produce json
// @Accept json
// @Param request body models.BusMessageCreateReq true "新增业务消息模型"
// @Success 200 {object} models.BusMessageCreateResp
// @Router /api/v1/bus_message/create [post]
func BusMessageCreate(c *gin.Context) {
	var req models.BusMessageCreateReq
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, err, "参数绑定失败")
		return
	}

	// 校验业务类型、事件类型、模板变量
	if err := models.ValidateBizEventAndTemplate(req.BizType, req.Event, req.ContentTemplate); err != nil {
		app.Error(c, http.StatusBadRequest, err, "模板校验失败")
		return
	}

	// 创建业务消息配置
	msg := models.SystemMessageConfig{
		MessageType:     models.BusinessMessageType, // 业务消息
		Title:           req.Title,
		ContentTemplate: req.ContentTemplate,
		BizType:         req.BizType,
		Event:           req.Event,
		Status:          req.Status,
	}
	if err := orm.Eloquent.Create(&msg).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, err, "创建业务消息失败")
		return
	}

	// 创建接收对象配置（target_type = 2）
	for _, roleID := range req.RoleID {
		target := models.SystemMessageTarget{
			MessageConfigID: uint(msg.ID),
			TargetType:      models.TargetTypeByRole, // 角色
			TargetID:        roleID,
		}
		if err := orm.Eloquent.Create(&target).Error; err != nil {
			app.Error(c, http.StatusInternalServerError, err, "接收对象配置失败")
			return
		}
	}

	app.OK(c, models.BusMessageCreateResp{ID: uint(msg.ID)}, "创建成功")
}

// BusMessageList 业务消息-列表
// @Summary 业务消息-列表
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.BusMessageListReq true "查询条件"
// @Success 200 {object} models.BusMessageListResp
// @Router /api/v1/bus_message/list [post]
func BusMessageList(c *gin.Context) {
	var req models.BusMessageListReq
	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 = ?", models.BusinessMessageType)

	if req.BizType != "" {
		db = db.Where("biz_type = ?", req.BizType)
	}
	if req.Event != "" {
		db = db.Where("event = ?", req.Event)
	}
	if req.Status != 0 {
		db = db.Where("status = ?", req.Status)
	}

	// 角色过滤（JOIN subquery）
	if len(req.RoleID) > 0 {
		subQuery := orm.Eloquent.Table("system_message_target").
			Select("message_config_id").
			Where("target_type = ?", models.TargetTypeByRole).
			Where("target_id IN (?)", req.RoleID)
		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 eventRegistryList []models.SystemEventRegistry
	eventRegistryMap := make(map[string]models.SystemEventRegistry)

	if err := orm.Eloquent.
		Where("is_enabled = ?", true).
		Find(&eventRegistryList).Error; err == nil {
		for _, ev := range eventRegistryList {
			key := ev.BizType + "#" + ev.Event
			eventRegistryMap[key] = ev
		}
	}

	var items []models.BusMessageItem
	for _, cfg := range list {
		key := cfg.BizType + "#" + cfg.Event
		reg := eventRegistryMap[key]

		item := models.BusMessageItem{
			ID:              cfg.ID,
			CreatedAt:       cfg.CreatedAt,
			UpdatedAt:       cfg.UpdatedAt,
			Title:           cfg.Title,
			ContentTemplate: cfg.ContentTemplate,
			BizType:         cfg.BizType,
			BizName:         reg.BizName,
			Event:           cfg.Event,
			EventName:       reg.EventName,
			Status:          cfg.Status,
		}

		// 查询该消息绑定的所有角色
		var targets []models.SystemMessageTarget
		if err := orm.Eloquent.Where("message_config_id = ? AND target_type = ?", cfg.ID,
			models.TargetTypeByRole).Find(&targets).Error; err == nil {
			for _, t := range targets {
				item.RoleID = append(item.RoleID, t.TargetID)
			}
		}

		items = append(items, item)
	}

	resp := models.BusMessageListResp{
		List:     items,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}
	app.OK(c, resp, "查询成功")
}

// BusMessageSetStatus 业务消息-设置状态（启用/禁用）
// @Summary 业务消息-设置状态（启用/禁用）
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.BusMessageSetStatusReq true "状态更新请求"
// @Success 200 {object} app.Response
// @Router /api/v1/bus_message/set_status [post]
func BusMessageSetStatus(c *gin.Context) {
	var req models.BusMessageSetStatusReq
	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.BusinessMessageType).
		First(&config).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "业务消息不存在")
		return
	}

	// 校验状态切换合法性
	switch req.Status {
	case 1: // 启用
		if 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
	}

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

// BusMessageDelete 业务消息-删除（禁用状态可删）
// @Summary 业务消息-删除（禁用状态可删）
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.BusMessageDeleteReq true "删除业务消息"
// @Success 200 {object} app.Response
// @Router /api/v1/bus_message/delete [post]
func BusMessageDelete(c *gin.Context) {
	var req models.BusMessageDeleteReq
	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.BusinessMessageType).
		First(&config).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "业务消息不存在")
		return
	}

	if config.Status != models.MessageStatusOnDisable {
		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
	}

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

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

// BusMessageEdit 业务消息-编辑
// @Summary 业务消息-编辑
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.BusMessageEditReq true "编辑业务消息"
// @Success 200 {object} app.Response
// @Router /api/v1/bus_message/edit [post]
func BusMessageEdit(c *gin.Context) {
	var req models.BusMessageEditReq
	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
	}

	// 校验事件与模板字段是否合法
	if err := models.ValidateBizEventAndTemplate(req.BizType, req.Event, req.ContentTemplate); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "模板校验失败: "+err.Error())
		return
	}

	// 更新主记录
	update := map[string]interface{}{
		"title":            req.Title,
		"biz_type":         req.BizType,
		"event":            req.Event,
		"content_template": req.ContentTemplate,
		"status":           req.Status,
		"updated_at":       time.Now(),
	}
	if err := orm.Eloquent.Model(&models.SystemMessageConfig{}).
		Where("id = ? AND message_type = ?", req.ID, models.BusinessMessageType).
		Updates(update).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "更新失败: "+err.Error())
		return
	}

	// 删除旧的接收对象记录
	_ = orm.Eloquent.Where("message_config_id = ?", req.ID).
		Delete(&models.SystemMessageTarget{})

	// 重建角色接收对象（target_type = 2）
	for _, roleID := range req.RoleID {
		target := models.SystemMessageTarget{
			MessageConfigID: uint(req.ID),
			TargetType:      models.TargetTypeByRole, // 角色
			TargetID:        roleID,
		}
		_ = orm.Eloquent.Create(&target).Error
	}

	app.OK(c, nil, "编辑成功")
}

// BusMessageDetail 业务消息-详情
// @Summary 业务消息-详情
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.BusMessageDetailReq true "业务消息ID"
// @Success 200 {object} models.BusMessageItem
// @Router /api/v1/bus_message/detail [post]
func BusMessageDetail(c *gin.Context) {
	var req models.BusMessageDetailReq
	if err := c.ShouldBindJSON(&req); err != nil || req.ID == 0 {
		app.Error(c, http.StatusBadRequest, nil, "参数错误：缺少或非法ID")
		return
	}

	// 查询主表
	var cfg models.SystemMessageConfig
	if err := orm.Eloquent.
		Where("id = ? AND message_type = ?", req.ID, models.BusinessMessageType).
		First(&cfg).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "未找到业务消息")
		return
	}

	// 查询事件注册表，补充 BizName、EventName
	var reg models.SystemEventRegistry
	if err := orm.Eloquent.
		Where("biz_type = ? AND event = ? AND is_enabled = ?", cfg.BizType, cfg.Event, true).
		First(&reg).Error; err != nil {
		// 可选：未找到事件名称也允许正常返回，只是字段为空
	}

	// 构建响应
	item := models.BusMessageItem{
		ID:              cfg.ID,
		CreatedAt:       cfg.CreatedAt,
		UpdatedAt:       cfg.UpdatedAt,
		Title:           cfg.Title,
		ContentTemplate: cfg.ContentTemplate,
		BizType:         cfg.BizType,
		BizName:         reg.BizName,
		Event:           cfg.Event,
		EventName:       reg.EventName,
		Status:          cfg.Status,
	}

	// 查询角色绑定
	var targets []models.SystemMessageTarget
	if err := orm.Eloquent.
		Where("message_config_id = ? AND target_type = ?", cfg.ID, models.TargetTypeByRole).
		Find(&targets).Error; err == nil {
		for _, t := range targets {
			item.RoleID = append(item.RoleID, t.TargetID)
		}
	}

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

// GetBizTypes 业务消息-查询业务类型
// @Summary 业务消息-查询业务类型
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.BizTypeListReq true "分页请求"
// @Success 200 {object} models.BizTypeListResp
// @Router /api/v1/bus_message/biz_types [post]
func GetBizTypes(c *gin.Context) {
	var req models.BizTypeListReq
	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_event_registry").
		Select("biz_type, biz_name, MIN(created_at) as created_at, MAX(updated_at) as updated_at, MAX(is_enabled) as is_enabled").
		Where("is_enabled = ?", true).
		Group("biz_type, biz_name")

	var total int64
	err := orm.Eloquent.
		Table("(?) as t", db).
		Count(&total).Error
	if err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "统计总数失败")
		return
	}

	var list []models.BizTypeItem
	err = orm.Eloquent.
		Table("(?) as t", db).
		Limit(req.PageSize).
		Offset((req.Page - 1) * req.PageSize).
		Scan(&list).Error
	if err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询失败")
		return
	}

	resp := models.BizTypeListResp{
		List:     list,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}

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

// GetEventsByBizType 业务消息-查询事件类型
// @Summary 业务消息-查询事件类型
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.EventListReq true "分页请求"
// @Success 200 {object} models.EventListResp
// @Router /api/v1/bus_message/events [post]
func GetEventsByBizType(c *gin.Context) {
	var req models.EventListReq
	if err := c.ShouldBindJSON(&req); err != nil || req.BizType == "" {
		app.Error(c, http.StatusBadRequest, nil, "参数错误")
		return
	}

	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	db := orm.Eloquent.Model(&models.SystemEventRegistry{}).
		Where("biz_type = ? AND is_enabled = ?", req.BizType, true)

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

	var list []models.EventItem
	if err := db.Select("event, event_name, description, created_at, updated_at, is_enabled").
		Order("created_at DESC").
		Limit(req.PageSize).
		Offset((req.Page - 1) * req.PageSize).
		Scan(&list).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询失败")
		return
	}

	resp := models.EventListResp{
		List:     list,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}

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

// GetTemplateVariables 业务消息-查询模板变量
// @Summary 业务消息-查询模板变量
// @Tags 消息中心
// @Accept json
// @Produce json
// @Param request body models.TemplateVarReq true "模板变量请求参数"
// @Success 200 {object} models.TemplateVarListResp
// @Router /api/v1/bus_message/template_variables [post]
func GetTemplateVariables(c *gin.Context) {
	var req models.TemplateVarReq
	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
	}

	// 查询事件配置
	var record models.SystemEventRegistry
	err := orm.Eloquent.
		Where("biz_type = ? AND event = ? AND is_enabled = ?", req.BizType, req.Event, true).
		First(&record).Error
	if err != nil {
		app.Error(c, http.StatusNotFound, nil, "未找到对应模板配置")
		return
	}

	// 解析模板变量
	var allVars []models.TemplateVariable
	if err := json.Unmarshal([]byte(record.TemplateVariables), &allVars); err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "模板变量解析失败")
		return
	}

	// 分页切片
	start := (req.Page - 1) * req.PageSize
	end := start + req.PageSize
	if start > len(allVars) {
		start = len(allVars)
	}
	if end > len(allVars) {
		end = len(allVars)
	}

	resp := models.TemplateVarListResp{
		List:     allVars[start:end],
		Total:    int64(len(allVars)),
		Page:     req.Page,
		PageSize: req.PageSize,
	}

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