import { apiRequest } from "@/shared/api/request"; import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints"; export interface LuckyGiftTierDto { pool: string; tierId: string; rewardCoins: number; multiplierPPM: number; weight: number; highWaterOnly: boolean; enabled: boolean; } export interface LuckyGiftConfigDto { appCode?: string; poolId: string; enabled: boolean; ruleVersion: number; giftPrice: number; targetRTPPPM: number; poolRatePPM: number; globalWindowDraws: number; giftWindowDraws: number; noviceDrawLimit: number; intermediateDrawLimit: number; highMultiplier: number; highWaterPoolMultiple: number; platformPoolWeightPPM: number; roomPoolWeightPPM: number; giftPoolWeightPPM: number; initialPlatformPool: number; initialGiftPool: number; initialRoomPool: number; platformReserve: number; giftReserve: number; roomReserve: number; maxSinglePayout: number; userHourlyPayoutCap: number; userDailyPayoutCap: number; deviceDailyPayoutCap: number; roomHourlyPayoutCap: number; anchorDailyPayoutCap: number; roomAtmosphereRatePPM: number; roomAtmosphereInitial: number; roomAtmosphereReserve: number; activityBudget: number; activityDailyLimit: number; largeTierEnabled: boolean; multiplierPPMs: number[]; tiers: LuckyGiftTierDto[]; updatedByAdminId?: number; createdAtMs?: number; updatedAtMs?: number; } export interface LuckyGiftConfigPayload { pool_id: string; enabled: boolean; gift_price: number; target_rtp_ppm: number; pool_rate_ppm: number; global_window_draws: number; gift_window_draws: number; novice_draw_limit: number; intermediate_draw_limit: number; high_multiplier: number; high_water_pool_multiple: number; platform_pool_weight_ppm: number; room_pool_weight_ppm: number; gift_pool_weight_ppm: number; initial_platform_pool: number; initial_gift_pool: number; initial_room_pool: number; platform_reserve: number; gift_reserve: number; room_reserve: number; max_single_payout: number; user_hourly_payout_cap: number; user_daily_payout_cap: number; device_daily_payout_cap: number; room_hourly_payout_cap: number; anchor_daily_payout_cap: number; room_atmosphere_rate_ppm: number; room_atmosphere_initial: number; room_atmosphere_reserve: number; activity_budget: number; activity_daily_limit: number; large_tier_enabled: boolean; multiplier_ppms: number[]; tiers: Array<{ pool: string; tier_id: string; reward_coins: number; multiplier_ppm: number; weight: number; high_water_only: boolean; enabled: boolean; }>; } export interface LuckyGiftDrawSummaryDto { poolId: string; totalDraws: number; uniqueUsers: number; uniqueRooms: number; totalSpentCoins: number; totalRewardCoins: number; baseRewardCoins: number; roomAtmosphereRewardCoins: number; activitySubsidyCoins: number; actualRTPPPM: number; pendingDraws: number; grantedDraws: number; failedDraws: number; } type RawConfig = LuckyGiftConfigDto & Record; type RawTier = LuckyGiftTierDto & Record; type RawSummary = LuckyGiftDrawSummaryDto & Record; type LuckyGiftDrawSummaryQuery = Record; export function getLuckyGiftConfig(poolId: string): Promise { const endpoint = API_ENDPOINTS.getLuckyGiftConfig; return apiRequest(apiEndpointPath(API_OPERATIONS.getLuckyGiftConfig), { method: endpoint.method, query: { pool_id: poolId }, }).then(normalizeConfig); } export function listLuckyGiftConfigs(): Promise { const endpoint = API_ENDPOINTS.listLuckyGiftConfigs; return apiRequest(apiEndpointPath(API_OPERATIONS.listLuckyGiftConfigs), { method: endpoint.method, }).then((items) => (items || []).map(normalizeConfig)); } export function updateLuckyGiftConfig(payload: LuckyGiftConfigPayload): Promise { const endpoint = API_ENDPOINTS.upsertLuckyGiftConfig; return apiRequest(apiEndpointPath(API_OPERATIONS.upsertLuckyGiftConfig), { body: payload, method: endpoint.method, query: { pool_id: payload.pool_id }, }).then(normalizeConfig); } export function getLuckyGiftDrawSummary(query: LuckyGiftDrawSummaryQuery = {}): Promise { const endpoint = API_ENDPOINTS.getLuckyGiftDrawSummary; return apiRequest(apiEndpointPath(API_OPERATIONS.getLuckyGiftDrawSummary), { method: endpoint.method, query, }).then(normalizeSummary); } function normalizeConfig(item: RawConfig): LuckyGiftConfigDto { return { appCode: stringValue(item.appCode ?? item.app_code), poolId: stringValue(item.poolId ?? item.pool_id ?? item.gift_id), enabled: booleanValue(item.enabled), ruleVersion: numberValue(item.ruleVersion ?? item.rule_version), giftPrice: numberValue(item.giftPrice ?? item.gift_price), targetRTPPPM: numberValue(item.targetRTPPPM ?? item.target_rtp_ppm), poolRatePPM: numberValue(item.poolRatePPM ?? item.pool_rate_ppm), globalWindowDraws: numberValue(item.globalWindowDraws ?? item.global_window_draws), giftWindowDraws: numberValue(item.giftWindowDraws ?? item.gift_window_draws), noviceDrawLimit: numberValue(item.noviceDrawLimit ?? item.novice_draw_limit), intermediateDrawLimit: numberValue(item.intermediateDrawLimit ?? item.intermediate_draw_limit), highMultiplier: numberValue(item.highMultiplier ?? item.high_multiplier), highWaterPoolMultiple: numberValue(item.highWaterPoolMultiple ?? item.high_water_pool_multiple), platformPoolWeightPPM: numberValue(item.platformPoolWeightPPM ?? item.platform_pool_weight_ppm), roomPoolWeightPPM: numberValue(item.roomPoolWeightPPM ?? item.room_pool_weight_ppm), giftPoolWeightPPM: numberValue(item.giftPoolWeightPPM ?? item.gift_pool_weight_ppm), initialPlatformPool: numberValue(item.initialPlatformPool ?? item.initial_platform_pool), initialGiftPool: numberValue(item.initialGiftPool ?? item.initial_gift_pool), initialRoomPool: numberValue(item.initialRoomPool ?? item.initial_room_pool), platformReserve: numberValue(item.platformReserve ?? item.platform_reserve), giftReserve: numberValue(item.giftReserve ?? item.gift_reserve), roomReserve: numberValue(item.roomReserve ?? item.room_reserve), maxSinglePayout: numberValue(item.maxSinglePayout ?? item.max_single_payout), userHourlyPayoutCap: numberValue(item.userHourlyPayoutCap ?? item.user_hourly_payout_cap), userDailyPayoutCap: numberValue(item.userDailyPayoutCap ?? item.user_daily_payout_cap), deviceDailyPayoutCap: numberValue(item.deviceDailyPayoutCap ?? item.device_daily_payout_cap), roomHourlyPayoutCap: numberValue(item.roomHourlyPayoutCap ?? item.room_hourly_payout_cap), anchorDailyPayoutCap: numberValue(item.anchorDailyPayoutCap ?? item.anchor_daily_payout_cap), roomAtmosphereRatePPM: numberValue(item.roomAtmosphereRatePPM ?? item.room_atmosphere_rate_ppm), roomAtmosphereInitial: numberValue(item.roomAtmosphereInitial ?? item.room_atmosphere_initial), roomAtmosphereReserve: numberValue(item.roomAtmosphereReserve ?? item.room_atmosphere_reserve), activityBudget: numberValue(item.activityBudget ?? item.activity_budget), activityDailyLimit: numberValue(item.activityDailyLimit ?? item.activity_daily_limit), largeTierEnabled: booleanValue(item.largeTierEnabled ?? item.large_tier_enabled), multiplierPPMs: arrayValue(item.multiplierPPMs ?? item.multiplier_ppms).map(numberValue), tiers: arrayValue(item.tiers).map(normalizeTier), updatedByAdminId: numberValue(item.updatedByAdminId ?? item.updated_by_admin_id), createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms), updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms), }; } function normalizeTier(raw: unknown): LuckyGiftTierDto { const item = asRecord(raw) as RawTier; return { pool: stringValue(item.pool), tierId: stringValue(item.tierId ?? item.tier_id), rewardCoins: numberValue(item.rewardCoins ?? item.reward_coins), multiplierPPM: numberValue(item.multiplierPPM ?? item.multiplier_ppm), weight: numberValue(item.weight), highWaterOnly: booleanValue(item.highWaterOnly ?? item.high_water_only), enabled: booleanValue(item.enabled), }; } function normalizeSummary(item: RawSummary): LuckyGiftDrawSummaryDto { return { poolId: stringValue(item.poolId ?? item.pool_id), totalDraws: numberValue(item.totalDraws ?? item.total_draws), uniqueUsers: numberValue(item.uniqueUsers ?? item.unique_users), uniqueRooms: numberValue(item.uniqueRooms ?? item.unique_rooms), totalSpentCoins: numberValue(item.totalSpentCoins ?? item.total_spent_coins), totalRewardCoins: numberValue(item.totalRewardCoins ?? item.total_reward_coins), baseRewardCoins: numberValue(item.baseRewardCoins ?? item.base_reward_coins), roomAtmosphereRewardCoins: numberValue(item.roomAtmosphereRewardCoins ?? item.room_atmosphere_reward_coins), activitySubsidyCoins: numberValue(item.activitySubsidyCoins ?? item.activity_subsidy_coins), actualRTPPPM: numberValue(item.actualRTPPPM ?? item.actual_rtp_ppm), pendingDraws: numberValue(item.pendingDraws ?? item.pending_draws), grantedDraws: numberValue(item.grantedDraws ?? item.granted_draws), failedDraws: numberValue(item.failedDraws ?? item.failed_draws), }; } function asRecord(value: unknown): Record { return value && typeof value === "object" && !Array.isArray(value) ? (value as Record) : {}; } function arrayValue(value: unknown): unknown[] { return Array.isArray(value) ? value : []; } function booleanValue(value: unknown) { return value === true || value === "true" || value === 1 || value === "1"; } function stringValue(value: unknown) { return typeof value === "string" ? value : value === undefined || value === null ? "" : String(value); } function numberValue(value: unknown) { const number = Number(value || 0); return Number.isFinite(number) ? number : 0; }