import type { BulkCreateDiscountCodesResponseDto, CreateDiscountCodesDto, DiscountCodeResponseDto, DiscountPreviewResponseDto, DiscountRedemptionResponseDto, DiscountReportSummaryDto, } from '@/api/generated/models' import { getDiscountCodes } from '@/api/generated/discount-codes/discount-codes' import { getFinancial } from '@/api/generated/financial/financial' import axiosInstance from '@/config/axios' import { parseRemittanceList, unwrapApiPayload } from '@/helpers/listResponse' import { texts } from '@/texts' import { createServiceError, errorResult, handleServiceError, type ServiceCallOptions, type ServiceResult, shouldBubbleErrorToParent, successResult, } from '@/services/errorHandler' export type DiscountCode = DiscountCodeResponseDto export type DiscountRedemption = DiscountRedemptionResponseDto export type DiscountReport = DiscountReportSummaryDto export type DiscountBulkResult = BulkCreateDiscountCodesResponseDto export type DiscountPreview = DiscountPreviewResponseDto export type DiscountType = CreateDiscountCodesDto['type'] export type DiscountBearer = NonNullable export interface DiscountCodesPage { items: DiscountCode[] totalItemsCount: number totalPages: number } export interface DiscountRedemptionsPage { items: DiscountRedemption[] totalItemsCount: number totalPages: number } export interface DiscountManagementBootstrap { codes: { items: DiscountCode[] } report: DiscountReport redemptions: { items: DiscountRedemption[] } } export interface BulkCreateDiscountInput { type: DiscountType value: number quantity: number maxUses?: number maxUsesPerUser?: number validFrom?: string validUntil?: string bearer?: DiscountBearer } const discountApi = getDiscountCodes() const financialApi = getFinancial() const wrap = async (run: () => Promise, options?: ServiceCallOptions): Promise> => { try { return successResult(await run()) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const GET_DISCOUNT_MANAGEMENT_BOOTSTRAP = ( eventId: string, options?: ServiceCallOptions ): Promise> => wrap(async () => { const response = await axiosInstance.get(`events/${eventId}/discount-codes/management-bootstrap`) return unwrapApiPayload(response.data) }, options) export const LIST_DISCOUNT_CODES = ( eventId: string, params: { page?: number; pageSize?: number } = {}, options?: ServiceCallOptions ): Promise> => wrap(async () => { const res = await discountApi.discountCodesControllerList(eventId, { page: params.page ?? 1, pageSize: params.pageSize ?? 50, sort: '-createdAt', }) const parsed = parseRemittanceList(res.data) return { items: parsed.items, totalItemsCount: parsed.pagination.totalItemsCount, totalPages: parsed.pagination.totalPages ?? 0, } }, options) export const LIST_DISCOUNT_REDEMPTIONS = ( eventId: string, params: { page?: number; pageSize?: number } = {}, options?: ServiceCallOptions ): Promise> => wrap(async () => { const res = await discountApi.discountCodesControllerRedemptions(eventId, { page: params.page ?? 1, pageSize: params.pageSize ?? 50, sort: '-createdAt', }) const parsed = parseRemittanceList(res.data) return { items: parsed.items, totalItemsCount: parsed.pagination.totalItemsCount, totalPages: parsed.pagination.totalPages ?? 0, } }, options) export const GET_DISCOUNT_REPORT = (eventId: string, options?: ServiceCallOptions): Promise> => wrap(async () => { const res = await discountApi.discountCodesControllerReport(eventId) return unwrapApiPayload(res.data) }, options) export const BULK_CREATE_DISCOUNT_CODES = ( eventId: string, input: BulkCreateDiscountInput, options?: ServiceCallOptions ): Promise> => wrap(async () => { const res = await discountApi.discountCodesControllerCreate(eventId, { type: input.type, value: input.value, quantity: input.quantity, maxUses: input.maxUses, maxUsesPerUser: input.maxUsesPerUser, validFrom: input.validFrom, validUntil: input.validUntil, bearer: input.bearer, }) const data = unwrapApiPayload(res.data) if (!data?.codes) throw createServiceError(texts.events.discountCreateFailed) return data }, options) export const SET_DISCOUNT_CODE_ACTIVE = ( codeId: string, isActive: boolean, options?: ServiceCallOptions ): Promise> => wrap(async () => { const res = await discountApi.discountCodesControllerUpdate(codeId, { isActive }) const data = unwrapApiPayload(res.data) if (!data?.id) throw createServiceError(texts.events.discountUpdateFailed) return data }, options) export const DELETE_DISCOUNT_CODE = (codeId: string, options?: ServiceCallOptions): Promise> => wrap(async () => { await discountApi.discountCodesControllerRemove(codeId) }, options) export const PREVIEW_DISCOUNT = (bookingId: string, code: string, options?: ServiceCallOptions): Promise> => wrap(async () => { const res = await financialApi.paymentsControllerPreviewDiscount(bookingId, { code: code.trim() }) const data = unwrapApiPayload(res.data) if (!data?.code) throw createServiceError(texts.events.discountCodeInvalid) return data }, options)