package service

import (
	"context"

	roomv1 "hyapp.local/api/proto/room/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
)

// AdminGetRoomRocketConfig 暴露 room-service owner 内部配置读模型，避免后台跨库读取 room_rocket_configs。
func (s *Service) AdminGetRoomRocketConfig(ctx context.Context, _ *roomv1.AdminGetRoomRocketConfigRequest) (*roomv1.AdminGetRoomRocketConfigResponse, error) {
	config, err := s.roomRocketConfig(ctx)
	if err != nil {
		return nil, err
	}
	return &roomv1.AdminGetRoomRocketConfigResponse{
		Config:       roomRocketConfigToAdminProto(config),
		ServerTimeMs: s.clock.Now().UnixMilli(),
	}, nil
}

// AdminUpdateRoomRocketConfig 保存后台火箭配置；版本号在 room-service 内递增，admin 不能直写 owner 表。
func (s *Service) AdminUpdateRoomRocketConfig(ctx context.Context, req *roomv1.AdminUpdateRoomRocketConfigRequest) (*roomv1.AdminUpdateRoomRocketConfigResponse, error) {
	if req == nil || req.GetConfig() == nil {
		return nil, xerr.New(xerr.InvalidArgument, "room rocket config is required")
	}
	current, exists, err := s.repository.GetRoomRocketConfig(ctx)
	if err != nil {
		return nil, err
	}
	nowMS := s.clock.Now().UTC().UnixMilli()
	createdAtMS := current.CreatedAtMS
	if !exists || createdAtMS <= 0 {
		createdAtMS = nowMS
	}
	input := req.GetConfig()
	config, err := normalizeRoomRocketConfig(RoomRocketConfig{
		AppCode:           appcode.FromContext(ctx),
		Enabled:           input.GetEnabled(),
		ConfigVersion:     current.ConfigVersion + 1,
		FuelSource:        input.GetFuelSource(),
		LaunchDelayMS:     input.GetLaunchDelayMs(),
		BroadcastEnabled:  input.GetBroadcastEnabled(),
		BroadcastScope:    input.GetBroadcastScope(),
		BroadcastDelayMS:  input.GetBroadcastDelayMs(),
		RewardStackPolicy: input.GetRewardStackPolicy(),
		Levels:            roomRocketLevelsFromProto(input.GetLevels()),
		GiftFuelRules:     roomRocketFuelRulesFromProto(input.GetGiftFuelRules()),
		UpdatedByAdminID:  req.GetAdminId(),
		CreatedAtMS:       createdAtMS,
		UpdatedAtMS:       nowMS,
	})
	if err != nil {
		return nil, err
	}
	if err := s.repository.UpsertRoomRocketConfig(ctx, config); err != nil {
		return nil, err
	}
	return &roomv1.AdminUpdateRoomRocketConfigResponse{
		Config:       roomRocketConfigToAdminProto(config),
		ServerTimeMs: nowMS,
	}, nil
}

func roomRocketConfigToAdminProto(config RoomRocketConfig) *roomv1.AdminRoomRocketConfig {
	return &roomv1.AdminRoomRocketConfig{
		AppCode:           config.AppCode,
		Enabled:           config.Enabled,
		ConfigVersion:     config.ConfigVersion,
		FuelSource:        config.FuelSource,
		LaunchDelayMs:     config.LaunchDelayMS,
		BroadcastEnabled:  config.BroadcastEnabled,
		BroadcastScope:    config.BroadcastScope,
		BroadcastDelayMs:  config.BroadcastDelayMS,
		RewardStackPolicy: config.RewardStackPolicy,
		Levels:            roomRocketLevelsToProto(config.Levels),
		GiftFuelRules:     roomRocketFuelRulesToProto(config.GiftFuelRules),
		UpdatedByAdminId:  config.UpdatedByAdminID,
		CreatedAtMs:       config.CreatedAtMS,
		UpdatedAtMs:       config.UpdatedAtMS,
	}
}

func roomRocketLevelsFromProto(input []*roomv1.RoomRocketLevel) []RoomRocketLevelConfig {
	out := make([]RoomRocketLevelConfig, 0, len(input))
	for _, level := range input {
		if level == nil {
			continue
		}
		out = append(out, RoomRocketLevelConfig{
			Level:              level.GetLevel(),
			FuelThreshold:      level.GetFuelThreshold(),
			CoverURL:           level.GetCoverUrl(),
			AnimationURL:       level.GetAnimationUrl(),
			LaunchAnimationURL: level.GetLaunchAnimationUrl(),
			LaunchedImageURL:   level.GetLaunchedImageUrl(),
			InRoomRewards:      roomRocketRewardsFromProto(level.GetInRoomRewards()),
			Top1Rewards:        roomRocketRewardsFromProto(level.GetTop1Rewards()),
			IgniterRewards:     roomRocketRewardsFromProto(level.GetIgniterRewards()),
		})
	}
	return out
}

func roomRocketRewardsFromProto(input []*roomv1.RoomRocketRewardItem) []RoomRocketRewardItem {
	out := make([]RoomRocketRewardItem, 0, len(input))
	for _, reward := range input {
		if reward == nil {
			continue
		}
		out = append(out, RoomRocketRewardItem{
			RewardItemID:    reward.GetRewardItemId(),
			ResourceGroupID: reward.GetResourceGroupId(),
			Weight:          reward.GetWeight(),
			Quantity:        reward.GetQuantity(),
			DisplayName:     reward.GetDisplayName(),
			IconURL:         reward.GetIconUrl(),
		})
	}
	return out
}

func roomRocketFuelRulesToProto(input []GiftFuelRuleConfig) []*roomv1.RoomRocketGiftFuelRule {
	out := make([]*roomv1.RoomRocketGiftFuelRule, 0, len(input))
	for _, rule := range input {
		out = append(out, &roomv1.RoomRocketGiftFuelRule{
			RuleId:        rule.RuleID,
			GiftId:        rule.GiftID,
			GiftTypeCode:  rule.GiftTypeCode,
			MultiplierPpm: rule.MultiplierPPM,
			FixedFuel:     rule.FixedFuel,
			Excluded:      rule.Excluded,
		})
	}
	return out
}

func roomRocketFuelRulesFromProto(input []*roomv1.RoomRocketGiftFuelRule) []GiftFuelRuleConfig {
	out := make([]GiftFuelRuleConfig, 0, len(input))
	for _, rule := range input {
		if rule == nil {
			continue
		}
		out = append(out, GiftFuelRuleConfig{
			RuleID:        rule.GetRuleId(),
			GiftID:        rule.GetGiftId(),
			GiftTypeCode:  rule.GetGiftTypeCode(),
			MultiplierPPM: rule.GetMultiplierPpm(),
			FixedFuel:     rule.GetFixedFuel(),
			Excluded:      rule.GetExcluded(),
		})
	}
	return out
}
