package admin

import (
	"math"
	"net/http"
	"strconv"

	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/repository/mysql/model"
)

type livestreamStatsResponse struct {
	TotalRevenue int64   `json:"total_revenue"` // 总营收(分)
	TotalRefund  int64   `json:"total_refund"`  // 总退款(分)
	TotalCost    int64   `json:"total_cost"`    // 总成本(分)
	NetProfit    int64   `json:"net_profit"`    // 净利润(分)
	OrderCount   int64   `json:"order_count"`   // 订单数
	RefundCount  int64   `json:"refund_count"`  // 退款数
	ProfitMargin float64 `json:"profit_margin"` // 利润率 %
}

// GetLivestreamStats 获取直播间盈亏统计
// @Summary 获取直播间盈亏统计
// @Description 计算逻辑：净利润 = (营收 - 退款) - 奖品成本。营收 = 抽奖次数 * 门票价格。成本 = 中奖奖品成本总和。
// @Tags 管理端.直播间
// @Accept json
// @Produce json
// @Param id path integer true "活动ID"
// @Success 200 {object} livestreamStatsResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/livestream/activities/{id}/stats [get]
// @Security LoginVerifyToken
func (h *handler) GetLivestreamStats() core.HandlerFunc {
	return func(ctx core.Context) {
		activityID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
		if err != nil || activityID <= 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的活动ID"))
			return
		}

		// 1. 获取活动信息（门票价格）
		var activity model.LivestreamActivities
		if err := h.repo.GetDbR().Where("id = ?", activityID).First(&activity).Error; err != nil {
			ctx.AbortWithError(core.Error(http.StatusNotFound, code.ServerError, "活动不存在"))
			return
		}
		ticketPrice := activity.TicketPrice

		// 2. 从 livestream_draw_logs 统计抽奖次数
		var drawLogs []model.LivestreamDrawLogs
		if err := h.repo.GetDbR().Where("activity_id = ?", activityID).Find(&drawLogs).Error; err != nil {
			ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
			return
		}

		orderCount := int64(len(drawLogs))
		totalRevenue := orderCount * ticketPrice

		// 3. 统计退款数量
		var refundCount int64
		h.repo.GetDbR().Model(&model.LivestreamDrawLogs{}).Where("activity_id = ? AND is_refunded = 1", activityID).Count(&refundCount)
		totalRefund := refundCount * ticketPrice

		// 4. 计算成本
		prizeIDCountMap := make(map[int64]int64)
		for _, log := range drawLogs {
			prizeIDCountMap[log.PrizeID]++
		}

		prizeIDs := make([]int64, 0, len(prizeIDCountMap))
		for pid := range prizeIDCountMap {
			prizeIDs = append(prizeIDs, pid)
		}

		var totalCost int64
		if len(prizeIDs) > 0 {
			var prizes []model.LivestreamPrizes
			h.repo.GetDbR().Where("id IN ?", prizeIDs).Find(&prizes)

			prizeCostMap := make(map[int64]int64)
			productIDsNeedingFallback := make([]int64, 0)
			prizeProductMap := make(map[int64]int64)

			for _, p := range prizes {
				if p.CostPrice > 0 {
					prizeCostMap[p.ID] = p.CostPrice
				} else if p.ProductID > 0 {
					productIDsNeedingFallback = append(productIDsNeedingFallback, p.ProductID)
					prizeProductMap[p.ID] = p.ProductID
				}
			}

			if len(productIDsNeedingFallback) > 0 {
				var products []model.Products
				h.repo.GetDbR().Where("id IN ?", productIDsNeedingFallback).Find(&products)
				productPriceMap := make(map[int64]int64)
				for _, prod := range products {
					productPriceMap[prod.ID] = prod.Price
				}
				for prizeID, productID := range prizeProductMap {
					if _, ok := prizeCostMap[prizeID]; !ok {
						if price, found := productPriceMap[productID]; found {
							prizeCostMap[prizeID] = price
						}
					}
				}
			}

			for prizeID, count := range prizeIDCountMap {
				if cost, ok := prizeCostMap[prizeID]; ok {
					totalCost += cost * count
				}
			}
		}

		netProfit := (totalRevenue - totalRefund) - totalCost

		var margin float64
		netRevenue := totalRevenue - totalRefund
		if netRevenue > 0 {
			margin = float64(netProfit) / float64(netRevenue) * 100
		} else {
			margin = -100
		}

		ctx.Payload(&livestreamStatsResponse{
			TotalRevenue: totalRevenue,
			TotalRefund:  totalRefund,
			TotalCost:    totalCost,
			NetProfit:    netProfit,
			OrderCount:   orderCount,
			RefundCount:  refundCount,
			ProfitMargin: math.Trunc(margin*100) / 100,
		})
	}
}
