package agent

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"sort"
	"strconv"
	"strings"
	"time"
	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/internal/router/admin"
	"verification-platform-backend/internal/service"
	"verification-platform-backend/pkg/response"
	"verification-platform-backend/pkg/utils"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

func SetupAgentRoutes(r *gin.RouterGroup) {
	r.GET("/stats", handleGetStats)
	r.GET("/apps", handleGetApps)
	r.GET("/apps/:id", handleGetAppDetail)
	r.GET("/cards", handleGetCards)
	r.POST("/cards/generate", handleGenerateCards)
	r.GET("/users", handleGetUsers)
	r.POST("/users", handleCreateUser)
	r.PUT("/users/:id", handleUpdateUser)
	r.GET("/users/:id", handleGetUser)
	r.PUT("/users/:id/status", handleUpdateUserStatus)
	r.GET("/finance", handleGetFinance)
	r.GET("/profile", handleGetProfile)
	r.PUT("/profile", handleUpdateProfile)
	r.GET("/cards/export", handleExportCards)
	r.GET("/cloud-variables", handleGetCloudVariables)
	r.GET("/cloud-variables/:id/records", handleGetCloudVariableRecords)

	r.GET("/devices", handleGetDevices)
	r.PUT("/devices/:id/status", admin.HandleUpdateDeviceStatus)
	r.DELETE("/devices/:id", admin.HandleUnbindDevice)
	r.POST("/devices/:id/force-offline", admin.HandleForceOfflineDevice)

	r.GET("/sessions", handleGetSessions)
	r.DELETE("/sessions/:id", admin.HandleDeleteSession)
}

func handleGetStats(c *gin.Context) {
	userID := c.GetUint("user_id")

	var totalApps int64
	database.DB.Model(&model.AgentApplication{}).Where("agent_id = ?", userID).Count(&totalApps)

	// 统计卡密数：包括 agent_id 或 creator_id 等于当前用户的卡密
	var totalCards int64
	database.DB.Model(&model.Card{}).Where("agent_id = ? OR (agent_id IS NULL AND creator_id = ?)", userID, userID).Count(&totalCards)

	var totalUsers int64
	var agentApps []model.AgentApplication
	database.DB.Where("agent_id = ?", userID).Find(&agentApps)
	appIDs := make([]uint, 0)
	for _, app := range agentApps {
		appIDs = append(appIDs, app.ApplicationID)
	}
	if len(appIDs) > 0 {
		database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Count(&totalUsers)
	}

	var totalRevenue float64
	database.DB.Model(&model.Card{}).Where("agent_id = ? OR (agent_id IS NULL AND creator_id = ?)", userID, userID).Select("COALESCE(SUM(price), 0)").Scan(&totalRevenue)

	today := time.Now().Format("2006-01-02")
	var todayCards int64
	database.DB.Model(&model.Card{}).Where("(agent_id = ? OR (agent_id IS NULL AND creator_id = ?)) AND DATE(created_at) = ?", userID, userID, today).Count(&todayCards)

	var todayRevenue float64
	database.DB.Model(&model.Card{}).Where("(agent_id = ? OR (agent_id IS NULL AND creator_id = ?)) AND DATE(created_at) = ?", userID, userID, today).Select("COALESCE(SUM(price), 0)").Scan(&todayRevenue)

	var agent model.User
	database.DB.First(&agent, userID)

	response.Success(c, gin.H{
		"totalApps":     totalApps,
		"totalCards":   totalCards,
		"totalUsers":   totalUsers,
		"totalRevenue": totalRevenue,
		"todayCards":   todayCards,
		"todayRevenue": todayRevenue,
		"balance":      agent.Balance,
	})
}

func handleGetApps(c *gin.Context) {
	userID := c.GetUint("user_id")

	var agentApps []model.AgentApplication
	if err := database.DB.Where("agent_id = ?", userID).Preload("Application").Find(&agentApps).Error; err != nil {
		response.Error(c, 500, "获取应用列表失败")
		return
	}

	apps := make([]gin.H, 0)
	for _, aa := range agentApps {
		if aa.Application.ID > 0 {
			apps = append(apps, gin.H{
				"id":            aa.Application.ID,
				"name":          aa.Application.Name,
				"description":   aa.Application.Description,
				"status":        aa.Application.Status,
				"authorized_at": aa.CreatedAt,
			})
		}
	}

	response.Success(c, gin.H{
		"apps": apps,
	})
}

func handleGetAppDetail(c *gin.Context) {
	userID := c.GetUint("user_id")
	appID := c.Param("id")

	// 检查代理是否有该应用的授权
	var agentApp model.AgentApplication
	if err := database.DB.Where("agent_id = ? AND application_id = ?", userID, appID).Preload("Application").First(&agentApp).Error; err != nil {
		response.Error(c, 404, "应用不存在或无权访问")
		return
	}

	// 获取该应用可用的卡类
	var cardTypes []model.CardType
	if err := database.DB.Where("application_id = ?", appID).Find(&cardTypes).Error; err != nil {
		response.Error(c, 500, "获取卡类列表失败")
		return
	}

	// 获取代理对该应用的卡类权限和价格
	var agentCardTypes []model.AgentApplicationCardType
	database.DB.Where("agent_application_id = ?", agentApp.ID).Find(&agentCardTypes)

	// 构建卡类列表，包含代理权限信息
	cardTypesList := make([]gin.H, 0)
	for _, ct := range cardTypes {
		// 查找代理是否有该卡类的权限
		var agentPrice float64
		var canGenerate bool
		for _, act := range agentCardTypes {
			if act.CardTypeID == ct.ID {
				agentPrice = act.Price
				canGenerate = act.CanGenerate
				break
			}
		}

		// 只返回代理有权限的卡类
		if canGenerate {
			cardTypesList = append(cardTypesList, gin.H{
				"id":            ct.ID,
				"name":          ct.Name,
				"billing_type":  ct.RechargeType,
				"price":         agentPrice,
				"value":         ct.Value,
				"duration_days": ct.Value,
			})
		}
	}

	response.Success(c, gin.H{
		"app": gin.H{
			"id":          agentApp.Application.ID,
			"name":        agentApp.Application.Name,
			"description": agentApp.Application.Description,
			"status":      agentApp.Application.Status,
		},
		"cardTypes": cardTypesList,
	})
}

func handleGetCards(c *gin.Context) {
	userID := c.GetUint("user_id")

	page := c.DefaultQuery("page", "1")
	pageSize := c.DefaultQuery("page_size", "20")
	applicationID := c.Query("application_id")
	cardTypeID := c.Query("card_type_id")
	status := c.Query("status")
	search := c.Query("search")
	startDate := c.Query("start_date")
	endDate := c.Query("end_date")

	baseCondition := "agent_id = ? OR (agent_id IS NULL AND creator_id = ?)"

	var total int64
	database.DB.Model(&model.Card{}).Where(baseCondition, userID, userID).Count(&total)

	var unusedCount int64
	database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "unused").Count(&unusedCount)

	var usedCount int64
	database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "used").Count(&usedCount)

	var expiredCount int64
	database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "expired").Count(&expiredCount)

	var bannedCount int64
	database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "banned").Count(&bannedCount)

	query := database.DB.Model(&model.Card{}).Where(baseCondition, userID, userID)

	if applicationID != "" {
		appID, err := strconv.ParseUint(applicationID, 10, 32)
		if err == nil {
			query = query.Where("application_id = ?", uint(appID))
		}
	}

	if cardTypeID != "" {
		ctID, err := strconv.ParseUint(cardTypeID, 10, 32)
		if err == nil {
			query = query.Where("card_type_id = ?", uint(ctID))
		}
	}

	if status != "" {
		query = query.Where("status = ?", status)
	}

	if search != "" {
		searchPattern := "%" + search + "%"
		query = query.Where("card_key LIKE ?", searchPattern)
	}

	if startDate != "" {
		query = query.Where("created_at >= ?", startDate+" 00:00:00")
	}

	if endDate != "" {
		query = query.Where("created_at <= ?", endDate+" 23:59:59")
	}

	var filteredTotal int64
	query.Count(&filteredTotal)

	var cards []model.Card
	offset := 0
	if pageInt, err := strconv.Atoi(page); err == nil && pageInt > 1 {
		offset = (pageInt - 1) * 20
	}

	limit := 20
	if pageSizeInt, err := strconv.Atoi(pageSize); err == nil && pageSizeInt > 0 {
		limit = pageSizeInt
	}

	query.Order("created_at DESC").Limit(limit).Offset(offset).Find(&cards)

	// 获取关联数据
	cardTypeIDs := make([]uint, 0)
	appIDs := make([]uint, 0)
	for _, card := range cards {
		cardTypeIDs = append(cardTypeIDs, card.CardTypeID)
		appIDs = append(appIDs, card.ApplicationID)
	}

	cardTypeMap := make(map[uint]model.CardType)
	if len(cardTypeIDs) > 0 {
		var cardTypes []model.CardType
		database.DB.Where("id IN ?", cardTypeIDs).Find(&cardTypes)
		for _, ct := range cardTypes {
			cardTypeMap[ct.ID] = ct
		}
	}

	appMap := make(map[uint]model.Application)
	if len(appIDs) > 0 {
		var apps []model.Application
		database.DB.Where("id IN ?", appIDs).Find(&apps)
		for _, app := range apps {
			appMap[app.ID] = app
		}
	}

	// 构建返回数据
	cardList := make([]gin.H, 0)
	for _, card := range cards {
		ct := cardTypeMap[card.CardTypeID]
		app := appMap[card.ApplicationID]

		cardList = append(cardList, gin.H{
			"id":             card.ID,
			"code":           card.CardKey,
			"app_name":       app.Name,
			"card_type_name": ct.Name,
			"status":         card.Status,
			"created_at":     card.CreatedAt,
			"used_at":        card.UsedAt,
		})
	}

	response.Success(c, gin.H{
		"cards":          cardList,
		"total":          total,
		"filtered_total": filteredTotal,
		"unused_count":   unusedCount,
		"used_count":     usedCount,
		"expired_count":  expiredCount,
		"banned_count":    bannedCount,
	})
}

func handleGenerateCards(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		ApplicationID uint `json:"application_id"`
		AppID         uint `json:"app_id"` // 兼容前端传的app_id
		CardTypeID    uint `json:"card_type_id"`
		Quantity      int  `json:"quantity"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	// 限制最大生成数量
	if req.Quantity <= 0 || req.Quantity > 100 {
		response.Error(c, 400, "生成数量必须在1-100之间")
		return
	}

	// 兼容 app_id 和 application_id
	appID := req.ApplicationID
	if appID == 0 {
		appID = req.AppID
	}

	var agentApp model.AgentApplication
	if err := database.DB.Where("agent_id = ? AND application_id = ?", userID, appID).First(&agentApp).Error; err != nil {
		response.Error(c, 403, "无权操作该应用")
		return
	}

	// 检查代理是否有该卡类的生成权限
	var agentCardType model.AgentApplicationCardType
	if err := database.DB.Where("agent_application_id = ? AND card_type_id = ? AND can_generate = ?", agentApp.ID, req.CardTypeID, true).First(&agentCardType).Error; err != nil {
		response.Error(c, 403, "无权生成该卡类")
		return
	}

	// 计算总价格
	totalPrice := agentCardType.Price * float64(req.Quantity)

	// 获取代理余额并检查是否足够
	var user model.User
	if err := database.DB.First(&user, userID).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	if user.Balance < totalPrice {
		response.Error(c, 400, fmt.Sprintf("余额不足，当前余额: %.2f，需要: %.2f", user.Balance, totalPrice))
		return
	}

	// 使用事务确保数据一致性
	tx := database.DB.Begin()

	cards := make([]model.Card, req.Quantity)
	for i := 0; i < req.Quantity; i++ {
		cards[i] = model.Card{
			ApplicationID: appID,
			CardTypeID:    req.CardTypeID,
			CardKey:       generateCardCode(),
			CreatorID:     userID,
			AgentID:       &userID,
			Status:        "unused",
		}
	}

	if err := tx.Create(&cards).Error; err != nil {
		tx.Rollback()
		response.Error(c, 500, "生成卡密失败")
		return
	}

	// 扣除余额
	if err := tx.Model(&user).Update("balance", user.Balance-totalPrice).Error; err != nil {
		tx.Rollback()
		response.Error(c, 500, "扣除余额失败")
		return
	}

	// 记录消费记录
	consumeRecord := model.RechargeRecord{
		UserID:      userID,
		OrderNo:     fmt.Sprintf("CARD%d%d", userID, time.Now().UnixNano()),
		Amount:      -totalPrice,
		Status:      "success",
		PaymentType: "balance",
		Remark:      fmt.Sprintf("生成卡密 %d 张", req.Quantity),
	}
	if err := tx.Create(&consumeRecord).Error; err != nil {
		tx.Rollback()
		response.Error(c, 500, "记录消费失败")
		return
	}

	tx.Commit()

	// 返回生成的卡号
	codes := make([]string, req.Quantity)
	for i, card := range cards {
		codes[i] = card.CardKey
	}

	response.Success(c, gin.H{
		"count":      req.Quantity,
		"codes":      codes,
		"totalPrice": totalPrice,
		"balance":    user.Balance - totalPrice,
	})
}

func generateCardCode() string {
	const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, 16)
	for i := range b {
		b[i] = charset[rand.Intn(len(charset))]
	}
	return string(b)
}

func handleGetUsers(c *gin.Context) {
	userID := c.GetUint("user_id")

	appUserIDs := getAgentUserIDs(userID)

	if len(appUserIDs) == 0 {
		response.Success(c, gin.H{
			"users":          []interface{}{},
			"total":          0,
			"active_count":   0,
			"disabled_count": 0,
			"banned_count":   0,
		})
		return
	}

	if len(appUserIDs) == 0 {
		response.Success(c, gin.H{
			"users":          []interface{}{},
			"total":          0,
			"active_count":   0,
			"disabled_count": 0,
			"banned_count":   0,
		})
		return
	}

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

	var total int64
	database.DB.Model(&model.AppUser{}).Where("id IN ?", appUserIDs).Count(&total)

	var activeCount, disabledCount, bannedCount int64
	database.DB.Model(&model.AppUser{}).Where("id IN ? AND status = ?", appUserIDs, "active").Count(&activeCount)
	database.DB.Model(&model.AppUser{}).Where("id IN ? AND status = ?", appUserIDs, "disabled").Count(&disabledCount)
	database.DB.Model(&model.AppUser{}).Where("id IN ? AND status = ?", appUserIDs, "banned").Count(&bannedCount)

	var users []model.AppUser
	offset := 0
	if pageInt, err := strconv.Atoi(page); err == nil && pageInt > 1 {
		offset = (pageInt - 1) * 20
	}

	limit := 20
	if pageSizeInt, err := strconv.Atoi(pageSize); err == nil && pageSizeInt > 0 {
		limit = pageSizeInt
	}

	database.DB.Preload("Application").Where("id IN ?", appUserIDs).Order("created_at DESC").Limit(limit).Offset(offset).Find(&users)

	result := make([]gin.H, 0, len(users))
	for _, u := range users {
		var deviceCount int64
		database.DB.Model(&model.UserDevice{}).Where("user_id = ?", u.ID).Count(&deviceCount)

		onlineStatus := "offline"
		if u.Status == "banned" {
			onlineStatus = "banned"
		} else if u.LastHeartbeatAt != nil {
			lastHeartbeat := *u.LastHeartbeatAt
			if time.Since(lastHeartbeat) < 5*time.Minute {
				onlineStatus = "online"
			}
		}

		item := gin.H{
			"id":               u.ID,
			"username":         u.Username,
			"email":            u.Email,
			"status":           u.Status,
			"balance":          u.Balance,
			"expiry_at":        u.ExpiryAt,
			"last_login_at":    u.LastLoginAt,
			"last_heartbeat_at": u.LastHeartbeatAt,
			"device_count":     deviceCount,
			"online_status":    onlineStatus,
			"application_id":   u.ApplicationID,
			"is_trial_user":    u.IsTrialUser,
			"created_at":       u.CreatedAt,
		}
		if u.Application.ID > 0 {
			item["application"] = gin.H{
				"id":           u.Application.ID,
				"name":         u.Application.Name,
				"billing_type": u.Application.BillingType,
			}
		}
		result = append(result, item)
	}

	response.Success(c, gin.H{
		"users":          result,
		"total":          total,
		"active_count":   activeCount,
		"disabled_count": disabledCount,
		"banned_count":   bannedCount,
	})
}

func handleGetFinance(c *gin.Context) {
	userID := c.GetUint("user_id")

	var user model.User
	if err := database.DB.First(&user, userID).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

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

	type TransactionItem struct {
		ID          uint    `json:"id"`
		Type        string  `json:"type"`
		Amount      float64 `json:"amount"`
		Description string  `json:"description"`
		Balance     float64 `json:"balance"`
		CreatedAt   string  `json:"created_at"`
	}

	var allTransactions []TransactionItem

	var rechargeRecords []model.RechargeRecord
	database.DB.Where("user_id = ? AND status = ?", userID, "success").Order("created_at DESC").Find(&rechargeRecords)
	for _, r := range rechargeRecords {
		txType := "recharge"
		if r.PaymentType == "refund" || r.Remark != "" && strings.Contains(strings.ToLower(r.Remark), "refund") {
			txType = "refund"
		}
		desc := r.Remark
		if desc == "" {
			desc = "充值"
		}
		allTransactions = append(allTransactions, TransactionItem{
			ID:          r.ID,
			Type:        txType,
			Amount:      r.Amount,
			Description: desc,
			Balance:     user.Balance,
			CreatedAt:   r.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
		})
	}

	var consumptionRecords []model.ConsumptionRecord
	database.DB.Where("user_id = ?", userID).Order("created_at DESC").Find(&consumptionRecords)
	for _, r := range consumptionRecords {
		desc := r.Description
		if desc == "" {
			desc = r.Content
		}
		if desc == "" {
			desc = "消费"
		}
		allTransactions = append(allTransactions, TransactionItem{
			ID:          r.ID,
			Type:        "consume",
			Amount:      r.Amount,
			Description: desc,
			Balance:     r.BalanceAfter,
			CreatedAt:   r.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
		})
	}

	sort.Slice(allTransactions, func(i, j int) bool {
		return allTransactions[i].CreatedAt > allTransactions[j].CreatedAt
	})

	var filtered []TransactionItem
	if typeFilter != "" {
		for _, tx := range allTransactions {
			if tx.Type == typeFilter {
				filtered = append(filtered, tx)
			}
		}
	} else {
		filtered = allTransactions
	}

	total := len(filtered)

	rechargeCount := 0
	consumeCount := 0
	var totalRecharge, totalConsume float64
	for _, tx := range allTransactions {
		if tx.Type == "recharge" || tx.Type == "refund" {
			rechargeCount++
			totalRecharge += tx.Amount
		} else if tx.Type == "consume" {
			consumeCount++
			totalConsume += tx.Amount
		}
	}

	offset := (page - 1) * pageSize
	end := offset + pageSize
	if offset > total {
		offset = total
	}
	if end > total {
		end = total
	}

	paginated := filtered[offset:end]

	response.Success(c, gin.H{
		"balance":        user.Balance,
		"transactions":   paginated,
		"total":          total,
		"page":           page,
		"page_size":      pageSize,
		"recharge_count": rechargeCount,
		"consume_count":  consumeCount,
		"total_recharge": totalRecharge,
		"total_consume":  totalConsume,
	})
}

func handleGetProfile(c *gin.Context) {
	userID := c.GetUint("user_id")

	var user model.User
	if err := database.DB.First(&user, userID).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	response.Success(c, gin.H{
		"id":                  user.ID,
		"username":            user.Username,
		"email":               user.Email,
		"avatar":              user.Avatar,
		"balance":             user.Balance,
		"can_create_agent":    user.CanCreateAgent,
		"can_view_cloud_data": user.CanViewCloudData,
	})
}

func handleUpdateProfile(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		Email string `json:"email"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var user model.User
	if err := database.DB.First(&user, userID).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	if req.Email != "" {
		user.Email = &req.Email
	}
	database.DB.Save(&user)

	response.Success(c, nil)
}

func handleExportCards(c *gin.Context) {
	userID := c.GetUint("user_id")

	token := c.Query("token")
	if token == "" {
		response.Error(c, 401, "未授权")
		return
	}

	baseCondition := "agent_id = ? OR (agent_id IS NULL AND creator_id = ?)"
	query := database.DB.Model(&model.Card{}).Where(baseCondition, userID, userID)

	if applicationID := c.Query("application_id"); applicationID != "" {
		appID, err := strconv.ParseUint(applicationID, 10, 32)
		if err == nil {
			query = query.Where("application_id = ?", uint(appID))
		}
	}

	if cardTypeID := c.Query("card_type_id"); cardTypeID != "" {
		ctID, err := strconv.ParseUint(cardTypeID, 10, 32)
		if err == nil {
			query = query.Where("card_type_id = ?", uint(ctID))
		}
	}

	if status := c.Query("status"); status != "" {
		query = query.Where("status = ?", status)
	}

	if startDate := c.Query("start_date"); startDate != "" {
		query = query.Where("created_at >= ?", startDate+" 00:00:00")
	}

	if endDate := c.Query("end_date"); endDate != "" {
		query = query.Where("created_at <= ?", endDate+" 23:59:59")
	}

	if ids := c.Query("ids"); ids != "" {
		idList := []uint{}
		for _, idStr := range splitIDs(ids) {
			if id, err := strconv.ParseUint(idStr, 10, 32); err == nil {
				idList = append(idList, uint(id))
			}
		}
		if len(idList) > 0 {
			query = database.DB.Model(&model.Card{}).Where("id IN ? AND ("+baseCondition+")", idList, userID, userID)
		}
	}

	var cards []model.Card
	query.Order("created_at DESC").Find(&cards)

	cardTypeIDs := make([]uint, 0)
	appIDs := make([]uint, 0)
	for _, card := range cards {
		cardTypeIDs = append(cardTypeIDs, card.CardTypeID)
		appIDs = append(appIDs, card.ApplicationID)
	}

	cardTypeMap := make(map[uint]model.CardType)
	if len(cardTypeIDs) > 0 {
		var cardTypes []model.CardType
		database.DB.Where("id IN ?", cardTypeIDs).Find(&cardTypes)
		for _, ct := range cardTypes {
			cardTypeMap[ct.ID] = ct
		}
	}

	appMap := make(map[uint]model.Application)
	if len(appIDs) > 0 {
		var apps []model.Application
		database.DB.Where("id IN ?", appIDs).Find(&apps)
		for _, app := range apps {
			appMap[app.ID] = app
		}
	}

	c.Header("Content-Type", "text/csv; charset=utf-8")
	c.Header("Content-Disposition", "attachment; filename=cards_export.csv")

	c.Writer.Write([]byte("\xEF\xBB\xBF"))
	c.Writer.Write([]byte("卡号,应用,卡类,状态,创建时间,使用时间\n"))

	for _, card := range cards {
		ct := cardTypeMap[card.CardTypeID]
		app := appMap[card.ApplicationID]
		statusMap := map[string]string{"unused": "未使用", "used": "已使用", "expired": "已过期", "banned": "已禁用"}
		statusText := statusMap[card.Status]
		if statusText == "" {
			statusText = card.Status
		}
		usedAt := ""
		if card.UsedAt != nil {
			usedAt = card.UsedAt.Format("2006-01-02 15:04:05")
		}
		line := fmt.Sprintf("%s,%s,%s,%s,%s,%s\n",
			card.CardKey,
			app.Name,
			ct.Name,
			statusText,
			card.CreatedAt.Format("2006-01-02 15:04:05"),
			usedAt,
		)
		c.Writer.Write([]byte(line))
	}
}

func splitIDs(ids string) []string {
	result := []string{}
	for _, id := range strings.Split(ids, ",") {
		id = strings.TrimSpace(id)
		if id != "" {
			result = append(result, id)
		}
	}
	return result
}

func handleGetCloudVariables(c *gin.Context) {
	userID := c.GetUint("user_id")

	var agent model.User
	if err := database.DB.First(&agent, userID).Error; err != nil {
		response.Error(c, 404, "代理不存在")
		return
	}

	if !agent.CanViewCloudData {
		response.Error(c, 403, "无权查看云端变量")
		return
	}

	var agentApps []model.AgentApplication
	database.DB.Where("agent_id = ?", userID).Find(&agentApps)
	appIDs := make([]uint, 0)
	for _, app := range agentApps {
		appIDs = append(appIDs, app.ApplicationID)
	}

	if len(appIDs) == 0 {
		response.Success(c, gin.H{
			"variables": []interface{}{},
			"total":     0,
		})
		return
	}

	appIDFilter := c.Query("app_id")
	var variables []model.CloudVariable
	query := database.DB.Where("app_id IN ?", appIDs)
	if appIDFilter != "" {
		if aid, err := strconv.ParseUint(appIDFilter, 10, 32); err == nil {
			query = database.DB.Where("app_id = ?", uint(aid))
		}
	}
	query.Find(&variables)

	appMap := make(map[uint]string)
	var apps []model.Application
	database.DB.Where("id IN ?", appIDs).Find(&apps)
	for _, app := range apps {
		appMap[app.ID] = app.Name
	}

	result := make([]gin.H, 0)
	for _, v := range variables {
		appName := ""
		if v.AppID != nil {
			appName = appMap[*v.AppID]
		}
		result = append(result, gin.H{
			"id":                v.ID,
			"key":               v.Key,
			"app_id":            v.AppID,
			"application_name":  appName,
			"default_value":     v.DefaultValue,
			"var_type":          v.VarType,
			"max_records":       v.MaxRecords,
			"scope":             v.Scope,
			"write_permission":  v.WritePermission,
			"status":            v.Status,
			"description":       v.Description,
			"created_at":        v.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
		})
	}

	response.Success(c, gin.H{
		"variables": result,
		"total":     len(result),
	})
}

func handleGetCloudVariableRecords(c *gin.Context) {
	userID := c.GetUint("user_id")

	var agent model.User
	if err := database.DB.First(&agent, userID).Error; err != nil {
		response.Error(c, 404, "代理不存在")
		return
	}

	if !agent.CanViewCloudData {
		response.Error(c, 403, "无权查看云端变量")
		return
	}

	variableID := c.Param("id")
	var variable model.CloudVariable
	if err := database.DB.First(&variable, variableID).Error; err != nil {
		response.Error(c, 404, "云端变量不存在")
		return
	}

	var agentApps []model.AgentApplication
	database.DB.Where("agent_id = ?", userID).Find(&agentApps)
	appIDs := make(map[uint]bool)
	for _, app := range agentApps {
		appIDs[app.ApplicationID] = true
	}

	if variable.AppID == nil || !appIDs[*variable.AppID] {
		response.Error(c, 403, "无权查看该变量的记录")
		return
	}

	if variable.VarType != "stream" {
		response.Error(c, 400, "该变量不是记录类型")
		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
	}

	startDate := c.Query("start_date")
	endDate := c.Query("end_date")

	var total int64
	query := database.DB.Model(&model.CloudVariableRecord{}).Where("cloud_variable_id = ?", variable.ID)
	if startDate != "" {
		query = query.Where("created_at >= ?", startDate+" 00:00:00")
	}
	if endDate != "" {
		query = query.Where("created_at <= ?", endDate+" 23:59:59")
	}
	query.Count(&total)

	var records []model.CloudVariableRecord
	offset := (page - 1) * pageSize
	if err := query.Order("created_at DESC").Limit(pageSize).Offset(offset).Find(&records).Error; err != nil {
		response.Error(c, 500, "获取记录失败")
		return
	}

	result := make([]gin.H, len(records))
	for i, r := range records {
		var parsedData interface{}
		if r.Data != "" {
			json.Unmarshal([]byte(r.Data), &parsedData)
		}
		if parsedData == nil && r.Data != "" {
			parsedData = r.Data
		}
		record := gin.H{
			"id":         r.ID,
			"data":       parsedData,
			"created_at": r.CreatedAt,
		}
		if r.AppUserID != nil {
			record["user_id"] = r.AppUserID
			var appUser model.AppUser
			if err := database.DB.Select("id, username").First(&appUser, *r.AppUserID).Error; err == nil {
				record["user"] = gin.H{
					"id":       appUser.ID,
					"username": appUser.Username,
				}
			}
		}
		result[i] = record
	}

	response.Success(c, gin.H{
		"records":     result,
		"total":       total,
		"page":        page,
		"page_size":   pageSize,
		"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
	})
}

func handleCreateUser(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		Username      string `json:"username"`
		Email         string `json:"email"`
		Password      string `json:"password"`
		ApplicationID uint   `json:"application_id"`
		CardTypeID    *uint  `json:"card_type_id"`
		CardQuantity  int    `json:"card_quantity"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	if req.Username == "" {
		response.Error(c, 400, "用户名不能为空")
		return
	}
	if req.Password == "" {
		response.Error(c, 400, "密码不能为空")
		return
	}
	if req.ApplicationID == 0 {
		response.Error(c, 400, "所属应用不能为空")
		return
	}
	if req.CardQuantity < 1 {
		req.CardQuantity = 1
	}
	if req.CardQuantity > 100 {
		response.Error(c, 400, "卡密数量不能超过100")
		return
	}

	var agentApp model.AgentApplication
	if err := database.DB.Where("application_id = ? AND agent_id = ? AND is_received = ?", req.ApplicationID, userID, true).First(&agentApp).Error; err != nil {
		response.Error(c, 403, "无权限在该应用下创建用户")
		return
	}

	var app model.Application
	if err := database.DB.First(&app, req.ApplicationID).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	var existingUser model.AppUser
	if err := database.DB.Where("username = ? AND application_id = ?", req.Username, app.ID).First(&existingUser).Error; err == nil {
		response.Error(c, 400, "用户已存在")
		return
	}

	var cardType *model.CardType
	var agentCardType *model.AgentApplicationCardType
	if req.CardTypeID != nil && *req.CardTypeID > 0 {
		var ct model.CardType
		if err := database.DB.Where("id = ? AND application_id = ?", *req.CardTypeID, req.ApplicationID).First(&ct).Error; err != nil {
			response.Error(c, 400, "卡密类型不存在或不属于该应用")
			return
		}

		var act model.AgentApplicationCardType
		if err := database.DB.Where("agent_application_id = ? AND card_type_id = ? AND can_generate = ?", agentApp.ID, *req.CardTypeID, true).First(&act).Error; err != nil {
			response.Error(c, 403, "无权使用该卡类充值")
			return
		}

		totalPrice := act.Price * float64(req.CardQuantity)
		var agent model.User
		if err := database.DB.First(&agent, userID).Error; err != nil {
			response.Error(c, 404, "代理不存在")
			return
		}
		if agent.Balance < totalPrice {
			response.Error(c, 400, fmt.Sprintf("余额不足，当前余额: %.2f，需要: %.2f", agent.Balance, totalPrice))
			return
		}

		cardType = &ct
		agentCardType = &act
	}

	tx := database.DB.Begin()

	user := model.AppUser{
		Username:      req.Username,
		Email:         req.Email,
		Password:      req.Password,
		Avatar:        "",
		Status:        "active",
		ApplicationID: app.ID,
		CreatedBy:     &userID,
	}

	if err := tx.Create(&user).Error; err != nil {
		tx.Rollback()
		response.Error(c, 500, "创建用户失败")
		return
	}

	var cards []model.Card
	if cardType != nil {
		now := time.Now()
		for i := 0; i < req.CardQuantity; i++ {
			cardKey := "CK" + utils.GenerateRandomString(16)
			card := model.Card{
				ApplicationID: req.ApplicationID,
				CardTypeID:    cardType.ID,
				CardKey:       cardKey,
				CreatorID:     userID,
				AgentID:       &userID,
				AppUserID:     &user.ID,
				Status:        "used",
			}
			card.UsedAt = &now

			if err := tx.Create(&card).Error; err != nil {
				tx.Rollback()
				response.Error(c, 500, "生成卡密失败")
				return
			}

			user.IsTrialUser = false

			if cardType.Value == -1 {
				if cardType.RechargeType == "subscription" {
					permanentExpiry := time.Date(9999, 12, 31, 23, 59, 59, 0, time.UTC)
					user.ExpiryAt = &permanentExpiry
					user.Balance = -1
				} else {
					user.Balance = -1
					user.ExpiryAt = nil
				}
			} else {
				switch cardType.RechargeType {
				case "subscription":
					var baseTime time.Time
					if user.ExpiryAt != nil && user.ExpiryAt.After(now) {
						baseTime = *user.ExpiryAt
					} else {
						baseTime = now
					}
					var duration time.Duration
					switch cardType.ValueUnit {
					case "minute":
						duration = time.Duration(cardType.Value) * time.Minute
					case "hour":
						duration = time.Duration(cardType.Value) * time.Hour
					case "day":
						duration = time.Duration(cardType.Value) * 24 * time.Hour
					case "month":
						duration = time.Duration(cardType.Value) * 30 * 24 * time.Hour
					case "year":
						duration = time.Duration(cardType.Value) * 365 * 24 * time.Hour
					default:
						duration = time.Duration(cardType.Value) * time.Second
					}
					newExpiry := baseTime.Add(duration)
					user.ExpiryAt = &newExpiry
				case "balance":
					fallthrough
				default:
					user.Balance += cardType.Value
				}
			}

			rechargeRecord := model.RechargeRecord{
				UserID:      user.ID,
				OrderNo:     generateAgentOrderNo("R"),
				CardID:      &card.ID,
				CardCode:    card.CardKey,
				Amount:      cardType.Price,
				Status:      "success",
				PaymentType: "card",
				Remark:      "代理创建用户充值 - " + cardType.Name,
			}
			if err := tx.Create(&rechargeRecord).Error; err != nil {
				tx.Rollback()
				response.Error(c, 500, "创建充值记录失败")
				return
			}

			cards = append(cards, card)
		}

		if err := tx.Save(&user).Error; err != nil {
			tx.Rollback()
			response.Error(c, 500, "充值失败")
			return
		}

		totalPrice := agentCardType.Price * float64(req.CardQuantity)
		if err := tx.Model(&model.User{}).Where("id = ?", userID).Update("balance", gorm.Expr("balance - ?", totalPrice)).Error; err != nil {
			tx.Rollback()
			response.Error(c, 500, "扣除余额失败")
			return
		}

		consumeRecord := model.RechargeRecord{
			UserID:      userID,
			OrderNo:     generateAgentOrderNo("C"),
			Amount:      -totalPrice,
			Status:      "success",
			PaymentType: "balance",
			Remark:      fmt.Sprintf("创建用户充值卡密: %s x%d", cardType.Name, req.CardQuantity),
		}
		if err := tx.Create(&consumeRecord).Error; err != nil {
			tx.Rollback()
			response.Error(c, 500, "记录消费失败")
			return
		}
	}

	if err := tx.Commit().Error; err != nil {
		response.Error(c, 500, "创建用户失败")
		return
	}

	logDesc := fmt.Sprintf("代理创建用户: %s (应用: %s)", user.Username, app.Name)
	if cardType != nil {
		logDesc += fmt.Sprintf("，充值卡密: %s x%d", cardType.Name, req.CardQuantity)
	}
	service.LogOperation(c, "create", "app_user", &user.ID, logDesc, nil)

	result := gin.H{
		"user": user,
	}
	if len(cards) > 0 {
		result["cards"] = cards
	}

	response.Success(c, result)
}

func generateAgentOrderNo(prefix string) string {
	return prefix + time.Now().Format("20060102150405") + utils.GenerateRandomString(6)
}

func handleUpdateUserStatus(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var req struct {
		Status string `json:"status"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	if req.Status != "active" && req.Status != "banned" {
		response.Error(c, 400, "状态值无效，仅支持 active 或 banned")
		return
	}

	var user model.AppUser
	if err := database.DB.First(&user, id).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	if !checkAgentUserPermission(userID, user.ID) {
		response.Error(c, 403, "无权限操作该用户")
		return
	}

	user.Status = req.Status
	if err := database.DB.Save(&user).Error; err != nil {
		response.Error(c, 500, "更新用户状态失败")
		return
	}

	logDesc := fmt.Sprintf("代理更新用户状态: %s -> %s", user.Username, req.Status)
	service.LogOperation(c, "update", "app_user", &user.ID, logDesc, nil)

	response.Success(c, user)
}

func getAgentUserIDs(userID uint) []uint {
	agentIDs := []uint{userID}
	var childAgents []model.User
	database.DB.Where("parent_agent_id = ? AND role = ?", userID, "agent").Find(&childAgents)
	for _, child := range childAgents {
		agentIDs = append(agentIDs, child.ID)
	}

	var cardIDs []uint
	database.DB.Model(&model.Card{}).Where("agent_id IN ?", agentIDs).Pluck("id", &cardIDs)

	userIDSet := make(map[uint]bool)

	if len(cardIDs) > 0 {
		var rechargedUserIDs []uint
		database.DB.Model(&model.RechargeRecord{}).
			Where("card_id IN ? AND status = ?", cardIDs, "success").
			Distinct("user_id").
			Pluck("user_id", &rechargedUserIDs)
		for _, id := range rechargedUserIDs {
			userIDSet[id] = true
		}
	}

	var createdUserIDs []uint
	database.DB.Model(&model.AppUser{}).
		Where("created_by IN ?", agentIDs).
		Pluck("id", &createdUserIDs)
	for _, id := range createdUserIDs {
		userIDSet[id] = true
	}

	result := make([]uint, 0, len(userIDSet))
	for id := range userIDSet {
		result = append(result, id)
	}
	return result
}

func getAgentAppIDs(userID uint) []uint {
	var agentApps []model.AgentApplication
	database.DB.Where("agent_id = ? AND is_received = ?", userID, true).Find(&agentApps)

	appIDs := make([]uint, 0, len(agentApps))
	for _, agentApp := range agentApps {
		appIDs = append(appIDs, agentApp.ApplicationID)
	}
	return appIDs
}

func checkAgentUserPermission(userID uint, appUserID uint) bool {
	agentUserIDs := getAgentUserIDs(userID)
	for _, id := range agentUserIDs {
		if id == appUserID {
			return true
		}
	}
	return false
}

func handleGetUser(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var user model.AppUser
	if err := database.DB.Preload("Application").First(&user, id).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	if !checkAgentUserPermission(userID, user.ID) {
		response.Error(c, 403, "无权限查看该用户")
		return
	}

	response.Success(c, gin.H{
		"user": user,
	})
}

func handleUpdateUser(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var req struct {
		Username string `json:"username"`
		Email    string `json:"email"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	var user model.AppUser
	if err := database.DB.First(&user, id).Error; err != nil {
		response.Error(c, 404, "用户不存在")
		return
	}

	if !checkAgentUserPermission(userID, user.ID) {
		response.Error(c, 403, "无权限修改该用户")
		return
	}

	if req.Username != "" {
		user.Username = req.Username
	}
	if req.Email != "" {
		user.Email = req.Email
	}
	if req.Password != "" {
		user.Password = req.Password
	}

	if err := database.DB.Save(&user).Error; err != nil {
		response.Error(c, 500, "更新用户失败")
		return
	}

	logDesc := fmt.Sprintf("代理更新用户: %s", user.Username)
	service.LogOperation(c, "update", "app_user", &user.ID, logDesc, nil)

	response.Success(c, user)
}

func handleGetDevices(c *gin.Context) {
	userID := c.GetUint("user_id")

	appUserIDs := getAgentUserIDs(userID)
	if len(appUserIDs) == 0 {
		response.Success(c, gin.H{
			"devices":      []interface{}{},
			"total":        0,
			"banned_count": 0,
		})
		return
	}

	appIDs := getAgentAppIDs(userID)
	if len(appIDs) == 0 {
		response.Success(c, gin.H{
			"devices":      []interface{}{},
			"total":        0,
			"banned_count": 0,
		})
		return
	}

	statusFilter := c.Query("status")
	applicationIDFilter := c.Query("application_id")

	query := database.DB.Model(&model.UserDevice{}).
		Where("user_id IN ? AND application_id IN ?", appUserIDs, appIDs)

	if statusFilter != "" {
		query = query.Where("status = ?", statusFilter)
	}
	if applicationIDFilter != "" {
		appID, _ := strconv.Atoi(applicationIDFilter)
		if appID > 0 {
			query = query.Where("application_id = ?", appID)
		}
	}

	var total int64
	query.Count(&total)

	var bannedCount int64
	database.DB.Model(&model.UserDevice{}).
		Where("user_id IN ? AND application_id IN ? AND status = ?", appUserIDs, appIDs, "banned").
		Count(&bannedCount)

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

	var devices []model.UserDevice
	findQuery := database.DB.Preload("User").Preload("Application").
		Where("user_id IN ? AND application_id IN ?", appUserIDs, appIDs)

	if statusFilter != "" {
		findQuery = findQuery.Where("status = ?", statusFilter)
	}
	if applicationIDFilter != "" {
		appID, _ := strconv.Atoi(applicationIDFilter)
		if appID > 0 {
			findQuery = findQuery.Where("application_id = ?", appID)
		}
	}

	if err := findQuery.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&devices).Error; err != nil {
		response.Error(c, 500, "获取设备列表失败")
		return
	}

	deviceIDs := make([]uint, len(devices))
	for i, d := range devices {
		deviceIDs[i] = d.ID
	}

	onlineSessionMap := make(map[uint]int)
	if len(deviceIDs) > 0 {
		type SessionCountResult struct {
			DeviceID uint
			Count    int
		}
		var sessionCounts []SessionCountResult
		database.DB.Model(&model.DeviceSession{}).
			Select("device_id, COUNT(*) as count").
			Where("device_id IN ? AND last_heartbeat > ?", deviceIDs, time.Now().Add(-5*time.Minute)).
			Group("device_id").
			Find(&sessionCounts)
		for _, sc := range sessionCounts {
			onlineSessionMap[sc.DeviceID] = sc.Count
		}
	}

	type DeviceWithDetails struct {
		model.UserDevice
		OnlineSessions int `json:"online_sessions"`
	}

	result := make([]DeviceWithDetails, 0, len(devices))
	for _, device := range devices {
		result = append(result, DeviceWithDetails{
			UserDevice:     device,
			OnlineSessions: onlineSessionMap[device.ID],
		})
	}

	response.Success(c, gin.H{
		"devices":      result,
		"total":        total,
		"page":         page,
		"page_size":    pageSize,
		"total_page":   (total + int64(pageSize) - 1) / int64(pageSize),
		"banned_count": bannedCount,
	})
}

func handleGetSessions(c *gin.Context) {
	userID := c.GetUint("user_id")

	appUserIDs := getAgentUserIDs(userID)
	if len(appUserIDs) == 0 {
		response.Success(c, gin.H{
			"sessions": []interface{}{},
			"total":    0,
		})
		return
	}

	appIDs := getAgentAppIDs(userID)
	if len(appIDs) == 0 {
		response.Success(c, gin.H{
			"sessions": []interface{}{},
			"total":    0,
		})
		return
	}

	appIDFilter := c.Query("app_id")
	searchFilter := c.Query("search")

	query := database.DB.Model(&model.DeviceSession{}).
		Where("user_id IN ? AND application_id IN ?", appUserIDs, appIDs)

	if appIDFilter != "" {
		appID, _ := strconv.Atoi(appIDFilter)
		if appID > 0 {
			query = query.Where("application_id = ?", appID)
		}
	}

	var total int64
	query.Count(&total)

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

	var sessions []model.DeviceSession
	findQuery := database.DB.Where("user_id IN ? AND application_id IN ?", appUserIDs, appIDs)

	if appIDFilter != "" {
		appID, _ := strconv.Atoi(appIDFilter)
		if appID > 0 {
			findQuery = findQuery.Where("application_id = ?", appID)
		}
	}

	if err := findQuery.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&sessions).Error; err != nil {
		response.Error(c, 500, "获取会话列表失败")
		return
	}

	type SessionWithDetails struct {
		model.DeviceSession
		DeviceID   string `json:"device_identifier"`
		DeviceName string `json:"device_name"`
		Username   string `json:"username"`
		AppName    string `json:"app_name"`
		IsOnline   bool   `json:"is_online"`
	}

	result := make([]SessionWithDetails, 0, len(sessions))
	for _, session := range sessions {
		var device model.UserDevice
		if err := database.DB.First(&device, session.DeviceID).Error; err != nil {
			continue
		}

		var user model.AppUser
		if err := database.DB.First(&user, session.UserID).Error; err != nil {
			continue
		}

		var app model.Application
		if err := database.DB.First(&app, session.ApplicationID).Error; err != nil {
			continue
		}

		heartbeatTimeout := app.HeartbeatTimeout
		if heartbeatTimeout == 0 {
			heartbeatTimeout = 300
		}
		timeoutThreshold := time.Now().Add(-time.Duration(heartbeatTimeout) * time.Second)
		isOnline := session.LastHeartbeat != nil && session.LastHeartbeat.After(timeoutThreshold)

		if searchFilter != "" {
			searchLower := strings.ToLower(searchFilter)
			instanceIDMatch := strings.Contains(strings.ToLower(session.InstanceID), searchLower)
			deviceIDMatch := strings.Contains(strings.ToLower(device.DeviceID), searchLower)
			usernameMatch := strings.Contains(strings.ToLower(user.Username), searchLower)
			deviceNameMatch := strings.Contains(strings.ToLower(device.DeviceName), searchLower)

			if !instanceIDMatch && !deviceIDMatch && !usernameMatch && !deviceNameMatch {
				continue
			}
		}

		result = append(result, SessionWithDetails{
			DeviceSession: session,
			DeviceID:      device.DeviceID,
			DeviceName:    device.DeviceName,
			Username:      user.Username,
			AppName:       app.Name,
			IsOnline:      isOnline,
		})
	}

	response.Success(c, gin.H{
		"sessions":  result,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	})
}
