package admin

import (
	"net/http"
	"strconv"
	"time"

	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
)

// UserProfileResponse 用户综合画像
type UserProfileResponse struct {
	// 基本信息
	ID              int64  `json:"id"`
	Nickname        string `json:"nickname"`
	Avatar          string `json:"avatar"`
	Mobile          string `json:"mobile"`
	InviteCode      string `json:"invite_code"`
	InviterID       int64  `json:"inviter_id"`
	ChannelID       int64  `json:"channel_id"`
	CreatedAt       string `json:"created_at"`
	DouyinID        string `json:"douyin_id"`
	InviterNickname string `json:"inviter_nickname"` // 邀请人昵称

	// 邀请统计
	InviteCount int64 `json:"invite_count"`

	// 生命周期财务指标
	LifetimeStats struct {
		TotalPaid     int64 `json:"total_paid"`      // 累计支付
		TotalRefunded int64 `json:"total_refunded"`  // 累计退款
		NetCashCost   int64 `json:"net_cash_cost"`   // 净现金支出
		OrderCount    int64 `json:"order_count"`     // 订单数
		TodayPaid     int64 `json:"today_paid"`      // 当日支付
		SevenDayPaid  int64 `json:"seven_day_paid"`  // 近7天支付
		ThirtyDayPaid int64 `json:"thirty_day_paid"` // 近30天支付
	} `json:"lifetime_stats"`

	// 当前资产快照
	CurrentAssets struct {
		PointsBalance   int64   `json:"points_balance"`    // 积分余额
		InventoryCount  int64   `json:"inventory_count"`   // 持有商品数
		InventoryValue  int64   `json:"inventory_value"`   // 持有商品价值
		CouponCount     int64   `json:"coupon_count"`      // 持有优惠券数
		CouponValue     int64   `json:"coupon_value"`      // 持有优惠券价值
		ItemCardCount   int64   `json:"item_card_count"`   // 持有道具卡数
		ItemCardValue   int64   `json:"item_card_value"`   // 持有道具卡价值
		GamePassCount   int64   `json:"game_pass_count"`   // 持有次数卡数
		GameTicketCount int64   `json:"game_ticket_count"` // 持有游戏资格数
		TotalAssetValue int64   `json:"total_asset_value"` // 总资产估值
		ProfitLossRatio float64 `json:"profit_loss_ratio"` // 累计盈亏比
	} `json:"current_assets"`
}

// GetUserProfile 获取用户综合画像
// @Summary 获取用户综合画像
// @Description 聚合用户基本信息、生命周期财务指标、当前资产快照
// @Tags 管理端.用户
// @Accept json
// @Produce json
// @Param user_id path integer true "用户ID"
// @Success 200 {object} UserProfileResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/users/{user_id}/profile [get]
// @Security LoginVerifyToken
func (h *handler) GetUserProfile() core.HandlerFunc {
	return func(ctx core.Context) {
		userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID"))
			return
		}

		rsp := new(UserProfileResponse)

		// 1. 基本信息
		user, err := h.readDB.Users.WithContext(ctx.RequestContext()).Where(h.readDB.Users.ID.Eq(userID)).First()
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusNotFound, 20201, "用户不存在"))
			return
		}
		rsp.ID = user.ID
		rsp.Nickname = user.Nickname
		rsp.Avatar = user.Avatar
		rsp.Mobile = user.Mobile
		rsp.InviteCode = user.InviteCode
		rsp.InviterID = user.InviterID
		rsp.ChannelID = user.ChannelID
		rsp.DouyinID = user.DouyinID
		rsp.CreatedAt = user.CreatedAt.Format(time.RFC3339)

		// 1.1 查询邀请人昵称
		if user.InviterID > 0 {
			inviter, _ := h.readDB.Users.WithContext(ctx.RequestContext()).Where(h.readDB.Users.ID.Eq(user.InviterID)).First()
			if inviter != nil {
				rsp.InviterNickname = inviter.Nickname
			}
		}

		// 2. 邀请统计
		rsp.InviteCount, _ = h.readDB.Users.WithContext(ctx.RequestContext()).Where(h.readDB.Users.InviterID.Eq(userID)).Count()

		// 3. 生命周期财务指标
		// 3.1 消费统计
		type orderStats struct {
			TotalPaid     int64
			OrderCount    int64
			TodayPaid     int64
			SevenDayPaid  int64
			ThirtyDayPaid int64
		}
		var os orderStats
		now := time.Now()
		todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
		sevenDayStart := todayStart.AddDate(0, 0, -6)
		thirtyDayStart := todayStart.AddDate(0, 0, -29)

		h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
			Select(
				h.readDB.Orders.ActualAmount.Sum().As("total_paid"),
				h.readDB.Orders.ID.Count().As("order_count"),
			).
			Where(h.readDB.Orders.UserID.Eq(userID)).
			Where(h.readDB.Orders.Status.Eq(2)).
			Scan(&os)

		// 分阶段统计
		h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
			Select(h.readDB.Orders.ActualAmount.Sum().As("today_paid")).
			Where(h.readDB.Orders.UserID.Eq(userID)).
			Where(h.readDB.Orders.Status.Eq(2)).
			Where(h.readDB.Orders.CreatedAt.Gte(todayStart)).
			Scan(&os.TodayPaid)

		h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
			Select(h.readDB.Orders.ActualAmount.Sum().As("seven_day_paid")).
			Where(h.readDB.Orders.UserID.Eq(userID)).
			Where(h.readDB.Orders.Status.Eq(2)).
			Where(h.readDB.Orders.CreatedAt.Gte(sevenDayStart)).
			Scan(&os.SevenDayPaid)

		h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
			Select(h.readDB.Orders.ActualAmount.Sum().As("thirty_day_paid")).
			Where(h.readDB.Orders.UserID.Eq(userID)).
			Where(h.readDB.Orders.Status.Eq(2)).
			Where(h.readDB.Orders.CreatedAt.Gte(thirtyDayStart)).
			Scan(&os.ThirtyDayPaid)

		rsp.LifetimeStats.TotalPaid = os.TotalPaid
		rsp.LifetimeStats.OrderCount = os.OrderCount
		rsp.LifetimeStats.TodayPaid = os.TodayPaid
		rsp.LifetimeStats.SevenDayPaid = os.SevenDayPaid
		rsp.LifetimeStats.ThirtyDayPaid = os.ThirtyDayPaid

		// 3.2 累计退款
		var totalRefunded int64
		_ = h.repo.GetDbR().Raw(`
			SELECT COALESCE(SUM(pr.amount_refund), 0) 
			FROM payment_refunds pr
			JOIN orders o ON o.order_no = pr.order_no COLLATE utf8mb4_unicode_ci
			WHERE o.user_id = ? AND pr.status = 'SUCCESS'
		`, userID).Scan(&totalRefunded).Error
		rsp.LifetimeStats.TotalRefunded = totalRefunded
		// 净现金投入 = 累计实付 - 累计退款
		rsp.LifetimeStats.NetCashCost = rsp.LifetimeStats.TotalPaid - totalRefunded
		if rsp.LifetimeStats.NetCashCost < 0 {
			rsp.LifetimeStats.NetCashCost = 0
		}

		// 4. 当前资产快照
		// 4.1 积分余额
		var pointsBalance int64
		_ = h.repo.GetDbR().Raw("SELECT COALESCE(SUM(points), 0) FROM user_points WHERE user_id = ?", userID).Scan(&pointsBalance).Error
		rsp.CurrentAssets.PointsBalance = pointsBalance

		// 4.2 持有商品
		type invStats struct {
			Count int64
			Value int64
		}
		var is invStats
		h.readDB.UserInventory.WithContext(ctx.RequestContext()).ReadDB().
			LeftJoin(h.readDB.Products, h.readDB.Products.ID.EqCol(h.readDB.UserInventory.ProductID)).
			Select(h.readDB.UserInventory.ID.Count().As("count"), h.readDB.Products.Price.Sum().As("value")).
			Where(h.readDB.UserInventory.UserID.Eq(userID)).
			Where(h.readDB.UserInventory.Status.Eq(1)).
			Scan(&is)
		rsp.CurrentAssets.InventoryCount = is.Count
		rsp.CurrentAssets.InventoryValue = is.Value

		// 4.3 持有优惠券
		type cpStats struct {
			Count int64
			Value int64
		}
		var cs cpStats
		_ = h.repo.GetDbR().Raw(`
			SELECT COUNT(*) AS count, COALESCE(SUM(balance_amount), 0) AS value
			FROM user_coupons
			WHERE user_id = ? AND status = 1
		`, userID).Scan(&cs).Error
		rsp.CurrentAssets.CouponCount = cs.Count
		rsp.CurrentAssets.CouponValue = cs.Value

		// 4.4 持有道具卡
		type cardStats struct {
			Count int64
			Value int64
		}
		var cds cardStats
		h.readDB.UserItemCards.WithContext(ctx.RequestContext()).ReadDB().
			LeftJoin(h.readDB.SystemItemCards, h.readDB.SystemItemCards.ID.EqCol(h.readDB.UserItemCards.CardID)).
			Select(h.readDB.UserItemCards.ID.Count().As("count"), h.readDB.SystemItemCards.Price.Sum().As("value")).
			Where(h.readDB.UserItemCards.UserID.Eq(userID)).
			Where(h.readDB.UserItemCards.Status.Eq(1)).
			Scan(&cds)
		rsp.CurrentAssets.ItemCardCount = cds.Count
		rsp.CurrentAssets.ItemCardValue = cds.Value

		// 4.5 持有次数卡
		_ = h.repo.GetDbR().Raw("SELECT COALESCE(SUM(remaining), 0) FROM user_game_passes WHERE user_id = ? AND remaining > 0 AND (expired_at IS NULL OR expired_at > NOW())", userID).Scan(&rsp.CurrentAssets.GamePassCount).Error

		// 4.6 持有游戏资格
		_ = h.repo.GetDbR().Raw("SELECT COALESCE(SUM(available), 0) FROM user_game_tickets WHERE user_id = ?", userID).Scan(&rsp.CurrentAssets.GameTicketCount).Error

		// 4.5 总资产估值
		// 估值逻辑：积分余额 + 商品价值 + 优惠券价值 + 道具卡价值 + 次数卡(2元/次) + 游戏资格(1元/场)
		gamePassValue := rsp.CurrentAssets.GamePassCount * 200     // 估值：2元/次
		gameTicketValue := rsp.CurrentAssets.GameTicketCount * 100 // 估值：1元/场

		rsp.CurrentAssets.TotalAssetValue = rsp.CurrentAssets.PointsBalance +
			rsp.CurrentAssets.InventoryValue +
			rsp.CurrentAssets.CouponValue +
			rsp.CurrentAssets.ItemCardValue +
			gamePassValue +
			gameTicketValue

		// 4.6 累计盈亏比
		if rsp.LifetimeStats.NetCashCost > 0 {
			rsp.CurrentAssets.ProfitLossRatio = float64(rsp.CurrentAssets.TotalAssetValue) / float64(rsp.LifetimeStats.NetCashCost)
		} else if rsp.CurrentAssets.TotalAssetValue > 0 {
			rsp.CurrentAssets.ProfitLossRatio = 99.9 // 无成本但有资产
		}

		ctx.Payload(rsp)
	}
}
