package walletapi

import (
	"net/http"
	"strings"

	walletv1 "hyapp.local/api/proto/wallet/v1"
	"hyapp/pkg/appcode"
	"hyapp/services/gateway-service/internal/auth"
	"hyapp/services/gateway-service/internal/transport/http/httpkit"
)

type vipCoinRebateStatusesRequestBody struct {
	RebateIDs []string `json:"rebate_ids"`
	Page      int32    `json:"page"`
	PageSize  int32    `json:"page_size"`
}

type vipCoinRebateClaimRequestBody struct {
	CommandID    string `json:"command_id"`
	CommandIDAlt string `json:"commandId"`
}

type vipDailyCoinRebateData struct {
	RebateID            string `json:"rebate_id"`
	UserID              string `json:"user_id"`
	TaskDay             string `json:"task_day"`
	VIPLevel            int32  `json:"vip_level"`
	VIPName             string `json:"vip_name"`
	CoinAmount          int64  `json:"coin_amount"`
	Status              string `json:"status"`
	AvailableAtMS       int64  `json:"available_at_ms"`
	ExpiresAtMS         int64  `json:"expires_at_ms"`
	ConfigVersion       int64  `json:"config_version"`
	ClaimedAtMS         int64  `json:"claimed_at_ms"`
	WalletTransactionID string `json:"wallet_transaction_id"`
	CreatedAtMS         int64  `json:"created_at_ms"`
	UpdatedAtMS         int64  `json:"updated_at_ms"`
}

// getCurrentVIPCoinRebate 返回当前 UTC 自然日的领取事实。found=false 是用户当日无资格或
// cron 尚未生成的正常状态，客户端不能据 VIP 等级自行补算金额。
func (h *Handler) getCurrentVIPCoinRebate(writer http.ResponseWriter, request *http.Request) {
	if h.walletClient == nil {
		httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
		return
	}
	resp, err := h.walletClient.GetMyCurrentVipDailyCoinRebate(request.Context(), &walletv1.GetMyCurrentVipDailyCoinRebateRequest{
		RequestId: httpkit.RequestIDFromContext(request.Context()),
		AppCode:   appcode.FromContext(request.Context()),
		UserId:    auth.UserIDFromContext(request.Context()),
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}
	var rebate *vipDailyCoinRebateData
	if resp.GetFound() && resp.GetRebate() != nil {
		item := vipDailyCoinRebateFromProto(resp.GetRebate())
		rebate = &item
	}
	httpkit.WriteOK(writer, request, map[string]any{
		"found":          resp.GetFound(),
		"rebate":         rebate,
		"server_time_ms": resp.GetServerTimeMs(),
	})
}

// listVIPCoinRebateStatuses 为系统通知恢复真实领取状态。rebate_ids 非空时 wallet 只返回
// 当前用户拥有的指定记录；为空时提供受限历史分页，不能接受客户端 user_id/app_code。
func (h *Handler) listVIPCoinRebateStatuses(writer http.ResponseWriter, request *http.Request) {
	if h.walletClient == nil {
		httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
		return
	}
	var body vipCoinRebateStatusesRequestBody
	if !httpkit.Decode(writer, request, &body) {
		return
	}
	if len(body.RebateIDs) > 100 || body.Page < 0 || body.PageSize < 0 || body.PageSize > 100 {
		httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument")
		return
	}
	resp, err := h.walletClient.ListMyVipDailyCoinRebateStatuses(request.Context(), &walletv1.ListMyVipDailyCoinRebateStatusesRequest{
		RequestId: httpkit.RequestIDFromContext(request.Context()),
		AppCode:   appcode.FromContext(request.Context()),
		UserId:    auth.UserIDFromContext(request.Context()),
		Page:      body.Page,
		PageSize:  body.PageSize,
		RebateIds: body.RebateIDs,
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}
	items := make([]vipDailyCoinRebateData, 0, len(resp.GetRebates()))
	for _, rebate := range resp.GetRebates() {
		items = append(items, vipDailyCoinRebateFromProto(rebate))
	}
	httpkit.WriteOK(writer, request, map[string]any{
		"rebates":        items,
		"total":          resp.GetTotal(),
		"server_time_ms": resp.GetServerTimeMs(),
	})
}

// claimVIPCoinRebate 只接收返现 ID 和业务幂等键；金额、等级、归属和 [UTC 0点,次日0点)
// 领取窗口全部由 wallet 锁内事实决定，避免客户端篡改金额或跨用户领取。
func (h *Handler) claimVIPCoinRebate(writer http.ResponseWriter, request *http.Request) {
	if h.walletClient == nil {
		httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
		return
	}
	rebateID := strings.TrimSpace(request.PathValue("rebate_id"))
	var body vipCoinRebateClaimRequestBody
	if !httpkit.Decode(writer, request, &body) {
		return
	}
	commandID := strings.TrimSpace(body.CommandID)
	if commandID == "" {
		commandID = strings.TrimSpace(body.CommandIDAlt)
	}
	if rebateID == "" || len(rebateID) > 96 || commandID == "" || len(commandID) > 128 {
		httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument")
		return
	}
	resp, err := h.walletClient.ClaimVipDailyCoinRebate(request.Context(), &walletv1.ClaimVipDailyCoinRebateRequest{
		CommandId: commandID,
		AppCode:   appcode.FromContext(request.Context()),
		UserId:    auth.UserIDFromContext(request.Context()),
		RebateId:  rebateID,
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}
	httpkit.WriteOK(writer, request, map[string]any{
		"rebate":         vipDailyCoinRebateFromProto(resp.GetRebate()),
		"transaction_id": resp.GetTransactionId(),
		"coin_balance":   balanceFromProto(resp.GetCoinBalance()),
		"server_time_ms": resp.GetServerTimeMs(),
	})
}

func vipDailyCoinRebateFromProto(rebate *walletv1.VipDailyCoinRebate) vipDailyCoinRebateData {
	if rebate == nil {
		return vipDailyCoinRebateData{}
	}
	return vipDailyCoinRebateData{
		RebateID:            rebate.GetRebateId(),
		UserID:              httpkit.UserIDString(rebate.GetUserId()),
		TaskDay:             rebate.GetTaskDay(),
		VIPLevel:            rebate.GetVipLevel(),
		VIPName:             rebate.GetVipName(),
		CoinAmount:          rebate.GetCoinAmount(),
		Status:              rebate.GetStatus(),
		AvailableAtMS:       rebate.GetAvailableAtMs(),
		ExpiresAtMS:         rebate.GetExpiresAtMs(),
		ConfigVersion:       rebate.GetConfigVersion(),
		ClaimedAtMS:         rebate.GetClaimedAtMs(),
		WalletTransactionID: rebate.GetWalletTransactionId(),
		CreatedAtMS:         rebate.GetCreatedAtMs(),
		UpdatedAtMS:         rebate.GetUpdatedAtMs(),
	}
}
