package admin

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

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

type dailyLivestreamStats struct {
	Date         string  `json:"date"`          // 日期
	TotalRevenue int64   `json:"total_revenue"` // 营收
	TotalRefund  int64   `json:"total_refund"`  // 退款
	TotalCost    int64   `json:"total_cost"`    // 成本
	NetProfit    int64   `json:"net_profit"`    // 净利润
	ProfitMargin float64 `json:"profit_margin"` // 利润率
	OrderCount   int64   `json:"order_count"`   // 订单数
	RefundCount  int64   `json:"refund_count"`  // 退款单数
}

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"` // 利润率 %
	Daily        []dailyLivestreamStats `json:"daily"`         // 每日明细
}

// 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) {
		id, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
		if err != nil || id <= 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的活动ID"))
			return
		}

		req := new(struct {
			StartTime string `form:"start_time"`
			EndTime   string `form:"end_time"`
		})
		_ = ctx.ShouldBindQuery(req)

		var startTime, endTime *time.Time
		if req.StartTime != "" {
			if t, err := time.ParseInLocation("2006-01-02", req.StartTime, time.Local); err == nil {
				startTime = &t
			}
		}
		if req.EndTime != "" {
			if t, err := time.ParseInLocation("2006-01-02", req.EndTime, time.Local); err == nil {
				end := t.Add(24*time.Hour - time.Nanosecond)
				endTime = &end
			}
		}

		// 1. 获取活动信息（门票价格）
		var activity model.LivestreamActivities
		if err := h.repo.GetDbR().Where("id = ?", id).First(&activity).Error; err != nil {
			ctx.AbortWithError(core.Error(http.StatusNotFound, code.ServerError, "活动不存在"))
			return
		}
		// ticketPrice 暂未使用，但在统计中可能作为参考，这里移除未使用的报错

		// 2. 核心统计逻辑重构：从关联的订单表获取真实金额
		// 使用子查询或 Join 来获取不重复的订单金额，确保即便一次订单对应多次抽奖，金额也不重计
		var totalRevenue, orderCount int64
		// 统计营收：来自已参与过抽奖（产生过日志）且未退款的订单 (order_status != 4)
		// 使用 actual_pay_amount (实付金额)
		queryRevenue := `
			SELECT 
				CAST(IFNULL(SUM(distinct_orders.actual_pay_amount), 0) AS SIGNED) as rev,
				COUNT(*) as cnt
			FROM (
				SELECT DISTINCT o.id, o.actual_pay_amount
				FROM douyin_orders o
				JOIN livestream_draw_logs l ON o.id = l.douyin_order_id
				WHERE l.activity_id = ?
		`
		if startTime != nil {
			queryRevenue += " AND l.created_at >= '" + startTime.Format("2006-01-02 15:04:05") + "'"
		}
		if endTime != nil {
			queryRevenue += " AND l.created_at <= '" + endTime.Format("2006-01-02 15:04:05") + "'"
		}
		queryRevenue += ") as distinct_orders"

		_ = h.repo.GetDbR().Raw(queryRevenue, id).Row().Scan(&totalRevenue, &orderCount)

		// 统计退款：来自已参与过抽奖且标记为退款的订单 (order_status = 4)
		var totalRefund, refundCount int64
		queryRefund := `
			SELECT 
				CAST(IFNULL(SUM(distinct_orders.actual_pay_amount), 0) AS SIGNED) as ref_amt,
				COUNT(*) as ref_cnt
			FROM (
				SELECT DISTINCT o.id, o.actual_pay_amount
				FROM douyin_orders o
				JOIN livestream_draw_logs l ON o.id = l.douyin_order_id
				WHERE l.activity_id = ? AND o.order_status = 4
		`
		if startTime != nil {
			queryRefund += " AND l.created_at >= '" + startTime.Format("2006-01-02 15:04:05") + "'"
		}
		if endTime != nil {
			queryRefund += " AND l.created_at <= '" + endTime.Format("2006-01-02 15:04:05") + "'"
		}
		queryRefund += ") as distinct_orders"

		_ = h.repo.GetDbR().Raw(queryRefund, id).Row().Scan(&totalRefund, &refundCount)

		// 3. 获取所有抽奖记录用于成本计算
		var drawLogs []model.LivestreamDrawLogs
		db := h.repo.GetDbR().Where("activity_id = ?", id)
		if startTime != nil {
			db = db.Where("created_at >= ?", startTime)
		}
		if endTime != nil {
			db = db.Where("created_at <= ?", endTime)
		}
		db.Find(&drawLogs)

		// 3.1 获取该时间段内所有退款的 shop_order_id 集合，用于过滤成本
		refundedShopOrderIDs := make(map[string]bool)
		var refundedOrders []string
		qRefundIDs := `
			SELECT DISTINCT o.shop_order_id
			FROM douyin_orders o
			JOIN livestream_draw_logs l ON o.id = l.douyin_order_id
			WHERE l.activity_id = ? AND o.order_status = 4
		`
		if startTime != nil {
			qRefundIDs += " AND l.created_at >= '" + startTime.Format("2006-01-02 15:04:05") + "'"
		}
		if endTime != nil {
			qRefundIDs += " AND l.created_at <= '" + endTime.Format("2006-01-02 15:04:05") + "'"
		}
		h.repo.GetDbR().Raw(qRefundIDs, id).Scan(&refundedOrders)
		for _, oid := range refundedOrders {
			refundedShopOrderIDs[oid] = true
		}

		// 4. 计算成本（只统计未退款订单的奖品成本）
		prizeIDCountMap := make(map[int64]int64)
		for _, log := range drawLogs {
			// 排除已退款的订单 (检查 douyin_orders 状态)
			if refundedShopOrderIDs[log.ShopOrderID] {
				continue
			}
			prizeIDCountMap[log.PrizeID]++
		}

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

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

			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
				}
			}
		}

		// 5. 按天分组统计
		dailyMap := make(map[string]*dailyLivestreamStats)

		// 5.1 统计每日营收和退款（直接累加订单实付金额）
		type DailyAmount struct {
			DateKey    string
			Amount     int64
			Count      int64
			IsRefunded int32
		}
		var dailyAmounts []DailyAmount
		queryDailyCorrect := `
			SELECT 
				date_key,
				CAST(SUM(actual_pay_amount) AS SIGNED) as amount,
				COUNT(id) as cnt,
				refund_flag as is_refunded
			FROM (
				SELECT 
					o.id,
					DATE_FORMAT(MIN(l.created_at), '%Y-%m-%d') as date_key,
					o.actual_pay_amount,
					IF(o.order_status = 4, 1, 0) as refund_flag
				FROM douyin_orders o
				JOIN livestream_draw_logs l ON o.id = l.douyin_order_id
				WHERE l.activity_id = ?
		`
		if startTime != nil {
			queryDailyCorrect += " AND l.created_at >= '" + startTime.Format("2006-01-02 15:04:05") + "'"
		}
		if endTime != nil {
			queryDailyCorrect += " AND l.created_at <= '" + endTime.Format("2006-01-02 15:04:05") + "'"
		}
		queryDailyCorrect += `
				GROUP BY o.id
			) as t
			GROUP BY date_key, is_refunded
		`
		rows, _ := h.repo.GetDbR().Raw(queryDailyCorrect, id).Rows()
		defer rows.Close()
		for rows.Next() {
			var da DailyAmount
			_ = rows.Scan(&da.DateKey, &da.Amount, &da.Count, &da.IsRefunded)
			dailyAmounts = append(dailyAmounts, da)
		}

		for _, da := range dailyAmounts {
			if _, ok := dailyMap[da.DateKey]; !ok {
				dailyMap[da.DateKey] = &dailyLivestreamStats{Date: da.DateKey}
			}

			// 修正口径：营收(Revenue) = 总流水 (含退款与未退款)
			// 这样下面的 NetProfit = TotalRevenue - TotalRefund - TotalCost 才不会双重扣除
			dailyMap[da.DateKey].TotalRevenue += da.Amount
			dailyMap[da.DateKey].OrderCount += da.Count

			if da.IsRefunded == 1 {
				dailyMap[da.DateKey].TotalRefund += da.Amount
				dailyMap[da.DateKey].RefundCount += da.Count
			}
		}

		// 5.2 统计每日成本（基于 Logs）
		for _, log := range drawLogs {
			// 排除退款订单
			if refundedShopOrderIDs[log.ShopOrderID] {
				continue
			}
			dateKey := log.CreatedAt.Format("2006-01-02")
			ds := dailyMap[dateKey]
			if ds != nil {
				if cost, ok := prizeCostMap[log.PrizeID]; ok {
					ds.TotalCost += cost
				}
			}
		}

		// 6. 汇总每日数据并计算总体指标
		var calcTotalRevenue, calcTotalRefund, calcTotalCost int64
		dailyList := make([]dailyLivestreamStats, 0, len(dailyMap))
		for _, ds := range dailyMap {
			ds.NetProfit = (ds.TotalRevenue - ds.TotalRefund) - ds.TotalCost
			netRev := ds.TotalRevenue - ds.TotalRefund
			if netRev > 0 {
				ds.ProfitMargin = math.Trunc(float64(ds.NetProfit)/float64(netRev)*10000) / 100
			} else if netRev == 0 && ds.TotalCost > 0 {
				ds.ProfitMargin = -100
			}
			dailyList = append(dailyList, *ds)

			calcTotalRevenue += ds.TotalRevenue
			calcTotalRefund += ds.TotalRefund
			calcTotalCost += ds.TotalCost
		}

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

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