package controller

import (
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"be.ems/src/framework/i18n"
	"be.ems/src/framework/reqctx"
	"be.ems/src/framework/resp"
	neService "be.ems/src/modules/ne/service"
	"be.ems/src/modules/ne_data/model"
	neDataService "be.ems/src/modules/ne_data/service"
	"github.com/gin-gonic/gin"
)

const (
	neType = "CBC" // 网元类型
)

// 实例化控制层 CBCController 结构体
var NewCBC = &CBCController{
	neInfoService:       neService.NewNeInfo,
	neCBCMessageService: neDataService.NewCBCMessage,
}

// 网元CBC
type CBCController struct {
	neInfoService       *neService.NeInfo         // 网元信息服务
	neCBCMessageService *neDataService.CBCMessage // CBC消息服务
}

func (m *CBCController) List(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	neId := c.Query("neId")
	if neId == "" {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	var query model.CBCMessageQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	query.NeType = neType
	query.NeId = neId

	data, total, err := neDataService.NewCBCMessage.SelectByPage(query)
	if err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}

	// 转换数据格式，确保 MessageJson 正确序列化
	processedData := make([]map[string]interface{}, len(data))
	for i, msg := range data {
		var messageJson interface{}
		if len(msg.MessageJson) > 0 {
			// 尝试解析为 JSON 对象
			if err := json.Unmarshal(msg.MessageJson, &messageJson); err != nil {
				// 如果解析失败，就作为字符串
				messageJson = string(msg.MessageJson)
			}
		}

		processedData[i] = map[string]interface{}{
			"id":          msg.Id,
			"neType":      msg.NeType,
			"neId":        msg.NeId,
			"messageJson": messageJson, // 这里是解析后的 JSON 对象
			"status":      msg.Status.Enum(),
			"detail":      msg.Detail,
			"createdAt":   msg.CreatedAt,
			"updatedAt":   msg.UpdatedAt,
		}
	}
	c.JSON(200, resp.Ok(gin.H{
		"total": total,
		"data":  processedData,
	}))
}

// Update 更新CB消息
func (m *CBCController) Insert(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	// 绑定请求体
	var msg model.CBCMessage
	msg.NeType = neType
	msg.NeId = c.Query("neId")
	msg.Status = model.CBCEventStatusInactive // 默认状态为 INACTIVE
	if msg.NeId == "" {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	now := time.Now().UnixMilli()
	msg.CreatedAt = now
	msg.UpdatedAt = now

	// 使用 ShouldBindBodyWithJSON 读取请求体
	var jsonData interface{}
	if err := c.ShouldBindBodyWithJSON(&jsonData); err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 将绑定的数据转换为 JSON
	jsonBytes, err := json.Marshal(jsonData)
	if err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	msg.MessageJson = json.RawMessage(jsonBytes)

	if err := neDataService.NewCBCMessage.Insert(msg); err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}

	c.JSON(200, resp.Ok(nil))
}

// Update 更新CB消息
func (m *CBCController) Update(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)

	// 获取路径参数
	messageId := c.Param("id")
	if messageId == "" {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	id, err := strconv.ParseInt(messageId, 10, 64)
	if err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	// 直接读取body为json.RawMessage
	var jsonData interface{}
	if err := c.ShouldBindBodyWithJSON(&jsonData); err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	// 将绑定的数据转换为 JSON
	jsonBytes, err := json.Marshal(jsonData)
	if err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}
	messageJson := json.RawMessage(jsonBytes)

	if err := neDataService.NewCBCMessage.Update(id, messageJson); err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}

	c.JSON(200, resp.Ok(nil))
}

// UpdateStatus 更新CB消息状态
// 这里的 neId 参数是为了兼容性，实际更新状态时不需要使用它
// 但为了保持与原有接口一致，仍然保留该参数
// 如果需要根据 neId 进行特定的逻辑处理，可以在服务层实现
// 但在当前实现中，neId 仅用于验证请求的有效性
// 实际的状态更新逻辑不依赖于 neId
// 该接口用于更新 CB 消息的状态，状态值通过查询参数传递
// 例如：PUT /:neId/message/status?status=ACTIVE
func (m *CBCController) UpdateStatus(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)

	neId := c.Query("neId")
	status := c.Param("status")
	if neId == "" || status == "" {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	messageId := c.Param("id")
	if messageId != "" {
		id, err := strconv.ParseInt(messageId, 10, 64)
		if err != nil {
			c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
			return
		}
		// 如果提供了 messageId，则更新特定消息的状态
		if err := neDataService.NewCBCMessage.UpdateStatus(id, status); err != nil {
			c.JSON(500, resp.ErrMsg(err.Error()))
			return
		}
		c.JSON(200, resp.Ok(nil))
		return
	}
	// 如果没有提供 messageId，则更新所有消息的状态
	if err := neDataService.NewCBCMessage.UpdateStatusByNeId(neId, status); err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}
	c.JSON(200, resp.Ok(nil))
}

// Delete 删除CB消息
func (m *CBCController) Delete(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)

	// 获取路径参数
	messageId := c.Param("id")
	if messageId == "" {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	id, err := strconv.ParseInt(messageId, 10, 64)
	if err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	if err := neDataService.NewCBCMessage.Delete(id); err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}

	c.JSON(200, resp.Ok(nil))
}

// ListById 根据ID获取CB消息
func (m *CBCController) ListById(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)

	// 获取路径参数
	idStr := c.Param("id")
	if idStr == "" {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
		return
	}

	data, err := neDataService.NewCBCMessage.SelectById(id)
	if err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}

	if data == nil {
		c.JSON(404, resp.CodeMsg(404, i18n.TKey(language, "app.common.err404")))
		return
	}
	// 转换数据格式，确保 MessageJson 正确序列化
	var messageJson interface{}
	if len(data.MessageJson) > 0 {
		// 尝试解析为 JSON 对象
		if err := json.Unmarshal(data.MessageJson, &messageJson); err != nil {
			// 如果解析失败，就作为字符串
			messageJson = string(data.MessageJson)
		}
	}

	processedData := map[string]interface{}{
		"id":          data.Id,
		"neType":      data.NeType,
		"neId":        data.NeId,
		"messageJson": messageJson, // 这里是解析后的 JSON 对象
		"status":      data.Status.Enum(),
		"detail":      data.Detail,
		"createdAt":   data.CreatedAt,
		"updatedAt":   data.UpdatedAt,
	}

	c.JSON(200, resp.Ok(gin.H{
		"data": processedData,
	}))
}

func (m *CBCController) Export(c *gin.Context) {
	language := reqctx.AcceptLanguage(c)
	// 查询结果，根据查询条件结果，单页最大值限制
	var query model.CBCMessageQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
		c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
		return
	}
	// 限制导出数据集
	if query.PageSize > 10000 {
		query.PageSize = 10000
	}
	// 查询数据
	rows, total, err := m.neCBCMessageService.SelectByPage(query)
	if err != nil {
		c.JSON(500, resp.ErrMsg(err.Error()))
		return
	}
	if total == 0 {
		// 导出数据记录为空
		c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
		return
	}

	// 导出文件名称
	fileName := fmt.Sprintf("cbc_message_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
	// 导出数据表格
	saveFilePath, err := m.neCBCMessageService.ExportXlsx(rows, fileName, language)
	if err != nil {
		c.JSON(200, resp.ErrMsg(err.Error()))
		return
	}

	c.FileAttachment(saveFilePath, fileName)
}
