package wallet

import (
	"context"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
	"strings"
)

// ListVipPackages 返回可购买 VIP 包和当前会员状态。
func (s *Service) ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) {
	if userID <= 0 {
		return ledger.UserVip{}, nil, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return ledger.UserVip{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.ListVipPackages(ctx, userID)
}

// GetMyVip 返回当前用户会员状态；过期会员会按 active=false 投影。
func (s *Service) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip, error) {
	if userID <= 0 {
		return ledger.UserVip{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return ledger.UserVip{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.GetMyVip(ctx, userID)
}

// PurchaseVip 执行 VIP 购买、升级或续期；降级由 repository 在锁内按当前会员状态拒绝。
func (s *Service) PurchaseVip(ctx context.Context, command ledger.PurchaseVipCommand) (ledger.PurchaseVipReceipt, error) {
	if command.CommandID == "" || command.UserID <= 0 || command.Level <= 0 {
		return ledger.PurchaseVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip purchase command is incomplete")
	}
	if s.repository == nil {
		return ledger.PurchaseVipReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	command.AppCode = appcode.Normalize(command.AppCode)
	ctx = appcode.WithContext(ctx, command.AppCode)
	return s.repository.PurchaseVip(ctx, command)
}

// GrantVip 是活动和后台赠送 VIP 的统一入口；购买仍走 PurchaseVip 完成扣费。
func (s *Service) GrantVip(ctx context.Context, command ledger.GrantVipCommand) (ledger.GrantVipReceipt, error) {
	if command.CommandID == "" || command.TargetUserID <= 0 || command.Level <= 0 {
		return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip grant command is incomplete")
	}
	if len(command.CommandID) > 128 {
		return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "command_id is too long")
	}
	command.GrantSource = ledger.NormalizeVipGrantSource(command.GrantSource)
	switch command.GrantSource {
	case ledger.VipGrantSourceAdmin, ledger.VipGrantSourceManagerCenter:
		if command.OperatorUserID <= 0 {
			return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "operator_user_id is required")
		}
	case ledger.VipGrantSourceActivity:
		if command.OperatorUserID < 0 {
			return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "operator_user_id is invalid")
		}
	default:
		return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip grant_source is invalid")
	}
	command.Reason = strings.TrimSpace(command.Reason)
	if command.Reason == "" {
		command.Reason = command.GrantSource
	}
	if len(command.Reason) > 512 {
		return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "reason is too long")
	}
	if s.repository == nil {
		return ledger.GrantVipReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	command.AppCode = appcode.Normalize(command.AppCode)
	ctx = appcode.WithContext(ctx, command.AppCode)
	return s.repository.GrantVip(ctx, command)
}

// ListAdminVipLevels 返回后台 VIP 配置页的 10 级配置快照。
func (s *Service) ListAdminVipLevels(ctx context.Context) ([]ledger.VipLevel, error) {
	if s.repository == nil {
		return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.ListAdminVipLevels(ctx)
}

// UpdateAdminVipLevels 保存后台 VIP 等级配置；完整校验下沉到 repository，保证和购买事务一致。
func (s *Service) UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) ([]ledger.VipLevel, error) {
	if operatorUserID <= 0 {
		return nil, xerr.New(xerr.InvalidArgument, "operator_user_id is required")
	}
	if s.repository == nil {
		return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	normalized := make([]ledger.AdminVipLevelCommand, 0, len(levels))
	for _, level := range levels {
		level.Name = strings.TrimSpace(level.Name)
		level.Status = strings.ToLower(strings.TrimSpace(level.Status))
		normalized = append(normalized, level)
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.UpdateAdminVipLevels(ctx, normalized, operatorUserID)
}
