import apiClient from './client' // ============ Types ============ export interface UserSubscriptionInfo { id: number status: string is_trial: boolean start_date: string | null end_date: string | null traffic_limit_gb: number traffic_used_gb: number device_limit: number tariff_id: number | null tariff_name: string | null autopay_enabled: boolean is_active: boolean days_remaining: number } export interface UserPromoGroupInfo { id: number name: string is_default: boolean } export interface UserListItem { id: number telegram_id: number username: string | null first_name: string | null last_name: string | null full_name: string status: string balance_kopeks: number balance_rubles: number created_at: string last_activity: string | null has_subscription: boolean subscription_status: string | null subscription_is_trial: boolean subscription_end_date: string | null promo_group_id: number | null promo_group_name: string | null total_spent_kopeks: number purchase_count: number has_restrictions: boolean restriction_topup: boolean restriction_subscription: boolean } export interface UsersListResponse { users: UserListItem[] total: number offset: number limit: number } export interface UserTransactionItem { id: number type: string amount_kopeks: number amount_rubles: number description: string | null payment_method: string | null is_completed: boolean created_at: string } export interface UserReferralInfo { referral_code: string referrals_count: number total_earnings_kopeks: number commission_percent: number | null referred_by_id: number | null referred_by_username: string | null } export interface UserDetailResponse { id: number telegram_id: number username: string | null first_name: string | null last_name: string | null full_name: string status: string language: string balance_kopeks: number balance_rubles: number email: string | null email_verified: boolean created_at: string updated_at: string | null last_activity: string | null cabinet_last_login: string | null subscription: UserSubscriptionInfo | null promo_group: UserPromoGroupInfo | null referral: UserReferralInfo total_spent_kopeks: number purchase_count: number used_promocodes: number has_had_paid_subscription: boolean lifetime_used_traffic_bytes: number restriction_topup: boolean restriction_subscription: boolean restriction_reason: string | null promo_offer_discount_percent: number promo_offer_discount_source: string | null promo_offer_discount_expires_at: string | null recent_transactions: UserTransactionItem[] remnawave_uuid: string | null } export interface UsersStatsResponse { total_users: number active_users: number blocked_users: number deleted_users: number new_today: number new_week: number new_month: number users_with_subscription: number users_with_active_subscription: number users_with_trial: number users_with_expired_subscription: number total_balance_kopeks: number total_balance_rubles: number avg_balance_kopeks: number active_today: number active_week: number active_month: number } // Available tariffs export interface PeriodPriceInfo { days: number price_kopeks: number price_rubles: number } export interface UserAvailableTariff { id: number name: string description: string | null is_active: boolean is_trial_available: boolean traffic_limit_gb: number device_limit: number tier_level: number display_order: number period_prices: PeriodPriceInfo[] is_daily: boolean daily_price_kopeks: number custom_days_enabled: boolean price_per_day_kopeks: number min_days: number max_days: number is_available: boolean requires_promo_group: boolean } export interface UserAvailableTariffsResponse { user_id: number promo_group_id: number | null promo_group_name: string | null tariffs: UserAvailableTariff[] total: number current_tariff_id: number | null current_tariff_name: string | null } // Sync types export interface PanelUserInfo { uuid: string | null short_uuid: string | null username: string | null status: string | null expire_at: string | null traffic_limit_gb: number traffic_used_gb: number device_limit: number subscription_url: string | null active_squads: string[] } export interface SyncFromPanelResponse { success: boolean message: string panel_user: PanelUserInfo | null changes: Record errors: string[] } export interface SyncToPanelResponse { success: boolean message: string action: string panel_uuid: string | null changes: Record errors: string[] } export interface PanelSyncStatusResponse { user_id: number telegram_id: number remnawave_uuid: string | null last_sync: string | null bot_subscription_status: string | null bot_subscription_end_date: string | null bot_traffic_limit_gb: number bot_traffic_used_gb: number bot_device_limit: number bot_squads: string[] panel_found: boolean panel_status: string | null panel_expire_at: string | null panel_traffic_limit_gb: number panel_traffic_used_gb: number panel_device_limit: number panel_squads: string[] has_differences: boolean differences: string[] } // Update types export interface UpdateBalanceRequest { amount_kopeks: number description?: string create_transaction?: boolean } export interface UpdateBalanceResponse { success: boolean old_balance_kopeks: number new_balance_kopeks: number message: string } export interface UpdateSubscriptionRequest { action: 'extend' | 'set_end_date' | 'change_tariff' | 'set_traffic' | 'toggle_autopay' | 'cancel' | 'activate' | 'create' days?: number end_date?: string tariff_id?: number traffic_limit_gb?: number traffic_used_gb?: number autopay_enabled?: boolean is_trial?: boolean device_limit?: number } export interface UpdateSubscriptionResponse { success: boolean message: string subscription: UserSubscriptionInfo | null } export interface UpdateUserStatusResponse { success: boolean old_status: string new_status: string message: string } export interface UpdateRestrictionsRequest { restriction_topup?: boolean restriction_subscription?: boolean restriction_reason?: string } export interface UpdateRestrictionsResponse { success: boolean restriction_topup: boolean restriction_subscription: boolean restriction_reason: string | null message: string } export interface SyncFromPanelRequest { update_subscription?: boolean update_traffic?: boolean create_if_missing?: boolean } export interface SyncToPanelRequest { create_if_missing?: boolean update_status?: boolean update_traffic_limit?: boolean update_expire_date?: boolean update_squads?: boolean } // ============ API ============ export const adminUsersApi = { // List users getUsers: async (params: { offset?: number limit?: number search?: string status?: 'active' | 'blocked' | 'deleted' sort_by?: 'created_at' | 'balance' | 'traffic' | 'last_activity' | 'total_spent' | 'purchase_count' } = {}): Promise => { const response = await apiClient.get('/cabinet/admin/users', { params }) return response.data }, // Get users stats getStats: async (): Promise => { const response = await apiClient.get('/cabinet/admin/users/stats') return response.data }, // Get user detail getUser: async (userId: number): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}`) return response.data }, // Get user by telegram ID getUserByTelegram: async (telegramId: number): Promise => { const response = await apiClient.get(`/cabinet/admin/users/by-telegram/${telegramId}`) return response.data }, // Get available tariffs for user getAvailableTariffs: async (userId: number, includeInactive = false): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/available-tariffs`, { params: { include_inactive: includeInactive } }) return response.data }, // Update balance updateBalance: async (userId: number, data: UpdateBalanceRequest): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/balance`, data) return response.data }, // Update subscription updateSubscription: async (userId: number, data: UpdateSubscriptionRequest): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/subscription`, data) return response.data }, // Update status updateStatus: async (userId: number, status: 'active' | 'blocked' | 'deleted', reason?: string): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/status`, { status, reason }) return response.data }, // Block user blockUser: async (userId: number, reason?: string): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/block`, null, { params: { reason } }) return response.data }, // Unblock user unblockUser: async (userId: number): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/unblock`) return response.data }, // Update restrictions updateRestrictions: async (userId: number, data: UpdateRestrictionsRequest): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/restrictions`, data) return response.data }, // Update promo group updatePromoGroup: async (userId: number, promoGroupId: number | null): Promise<{ success: boolean; message: string }> => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/promo-group`, { promo_group_id: promoGroupId }) return response.data }, // Delete user deleteUser: async (userId: number, softDelete = true, reason?: string): Promise<{ success: boolean; message: string }> => { const response = await apiClient.delete(`/cabinet/admin/users/${userId}`, { data: { soft_delete: softDelete, reason } }) return response.data }, // Get referrals getReferrals: async (userId: number, offset = 0, limit = 50): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/referrals`, { params: { offset, limit } }) return response.data }, // Get transactions getTransactions: async (userId: number, params: { offset?: number limit?: number transaction_type?: string } = {}): Promise<{ transactions: UserTransactionItem[]; total: number; offset: number; limit: number }> => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/transactions`, { params }) return response.data }, // Sync status getSyncStatus: async (userId: number): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/sync/status`) return response.data }, // Sync from panel syncFromPanel: async (userId: number, data: SyncFromPanelRequest = {}): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/sync/from-panel`, data) return response.data }, // Sync to panel syncToPanel: async (userId: number, data: SyncToPanelRequest = {}): Promise => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/sync/to-panel`, data) return response.data }, }