import apiClient from './client'; export interface TrafficPurchaseInfo { id: number; traffic_gb: number; expires_at: string; created_at: string; days_remaining: number; is_expired: boolean; } 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; purchased_traffic_gb: number; traffic_purchases: TrafficPurchaseInfo[]; } export interface UserPromoGroupInfo { id: number; name: string; is_default: boolean; } export interface UserListItemSubscription { id: number; tariff_id: number | null; tariff_name: string | null; status: string; is_trial: boolean; end_date: string | null; days_remaining: number; traffic_used_gb: number; traffic_limit_gb: number; device_limit: number; } 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; tariff_id: number | null; tariff_name: string | null; traffic_used_gb: number; traffic_limit_gb: number; device_limit: number; days_remaining: number; 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; subscriptions?: UserListItemSubscription[]; } 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; subscriptions: UserSubscriptionInfo[]; 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; campaign_name: string | null; campaign_id: number | null; 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 UserPanelInfo { found: boolean; trojan_password: string | null; vless_uuid: string | null; ss_password: string | null; subscription_url: string | null; happ_link: string | null; used_traffic_bytes: number; lifetime_used_traffic_bytes: number; traffic_limit_bytes: number; first_connected_at: string | null; online_at: string | null; last_connected_node_uuid: string | null; last_connected_node_name: string | null; } export interface SubscriptionRequestRecord { id: number; userUuid: string; requestAt: string; requestIp: string | null; userAgent: string | null; } export interface SubscriptionRequestHistory { total: number; records: SubscriptionRequestRecord[]; } export interface UserNodeUsageItem { node_uuid: string; node_name: string; country_code: string; total_bytes: number; daily_bytes: number[]; } export interface UserNodeUsageResponse { items: UserNodeUsageItem[]; categories: string[]; period_days: number; } 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; device_price_kopeks: number | null; max_device_limit: number | null; traffic_topup_enabled: boolean; traffic_topup_packages: Record; max_topup_traffic_gb: 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; subscription_id: number | null; subscription_tariff_name: 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' | 'add_traffic' | 'remove_traffic' | 'set_device_limit' | 'shorten'; subscription_id?: number; 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; traffic_gb?: number; traffic_purchase_id?: 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; } export interface AdminUserGiftItem { id: number; token: string; status: string; tariff_name: string | null; period_days: number; device_limit: number; amount_kopeks: number; payment_method: string | null; gift_recipient_type: string | null; gift_recipient_value: string | null; gift_message: string | null; buyer_user_id: number | null; buyer_username: string | null; buyer_full_name: string | null; receiver_user_id: number | null; receiver_username: string | null; receiver_full_name: string | null; created_at: string | null; paid_at: string | null; delivered_at: string | null; } export interface AdminUserGiftsResponse { sent: AdminUserGiftItem[]; received: AdminUserGiftItem[]; sent_total: number; received_total: number; } export const adminUsersApi = { // List users getUsers: async ( params: { offset?: number; limit?: number; search?: string; email?: string; status?: 'active' | 'blocked' | 'deleted'; subscription_status?: string; tariff_id?: string; promo_group_id?: number; campaign_id?: number; partner_id?: number; 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; }, // Update referral commission updateReferralCommission: async ( userId: number, commissionPercent: number | null, ): Promise<{ success: boolean; message: string }> => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/referral-commission`, { commission_percent: commissionPercent, }); return response.data; }, // Delete user (soft delete, does NOT remove from Remnawave) 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; }, // Full delete user (removes from bot DB + Remnawave panel) fullDeleteUser: async ( userId: number, ): Promise<{ success: boolean; message: string; deleted_from_bot: boolean; deleted_from_panel: boolean; panel_error: string | null; }> => { const response = await apiClient.delete(`/cabinet/admin/users/${userId}/full`); return response.data; }, // Assign a referrer to this user assignReferrer: async ( userId: number, referrerId: number, ): Promise<{ success: boolean; message: string }> => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/assign-referrer`, { referrer_id: referrerId, }); return response.data; }, // Remove this user's referrer removeReferrer: async (userId: number): Promise<{ success: boolean; message: string }> => { const response = await apiClient.delete(`/cabinet/admin/users/${userId}/referrer`); return response.data; }, // Remove a specific referral from this user's list removeReferral: async ( userId: number, referralUserId: number, ): Promise<{ success: boolean; message: string }> => { const response = await apiClient.delete( `/cabinet/admin/users/${userId}/referrals/${referralUserId}`, ); 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, subscriptionId?: number, ): Promise => { const params = subscriptionId != null ? { subscription_id: subscriptionId } : undefined; const response = await apiClient.get(`/cabinet/admin/users/${userId}/sync/status`, { params }); return response.data; }, // Sync from panel syncFromPanel: async ( userId: number, data: SyncFromPanelRequest = {}, subscriptionId?: number, ): Promise => { const params = subscriptionId != null ? { subscription_id: subscriptionId } : undefined; const response = await apiClient.post(`/cabinet/admin/users/${userId}/sync/from-panel`, data, { params, }); return response.data; }, // Sync to panel syncToPanel: async ( userId: number, data: SyncToPanelRequest = {}, subscriptionId?: number, ): Promise => { const params = subscriptionId != null ? { subscription_id: subscriptionId } : undefined; const response = await apiClient.post(`/cabinet/admin/users/${userId}/sync/to-panel`, data, { params, }); return response.data; }, // Reset trial resetTrial: async (userId: number): Promise<{ success: boolean; message: string }> => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/reset-trial`); return response.data; }, // Reset subscription resetSubscription: async (userId: number): Promise<{ success: boolean; message: string }> => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/reset-subscription`); return response.data; }, // Disable user disableUser: async (userId: number): Promise<{ success: boolean; message: string }> => { const response = await apiClient.post(`/cabinet/admin/users/${userId}/disable`); return response.data; }, // Get panel info getPanelInfo: async (userId: number, subscriptionId?: number): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/panel-info`, { params: subscriptionId != null ? { subscription_id: subscriptionId } : undefined, }); return response.data; }, // Get node usage (always 30 days with daily breakdown) getNodeUsage: async (userId: number, subscriptionId?: number): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/node-usage`, { params: subscriptionId != null ? { subscription_id: subscriptionId } : undefined, }); return response.data; }, // Get subscription request history from RemnaWave panel getSubscriptionRequestHistory: async ( userId: number, subscriptionId?: number, offset = 0, limit = 20, ): Promise => { const params: Record = { offset, limit }; if (subscriptionId != null) params.subscription_id = subscriptionId; const response = await apiClient.get( `/cabinet/admin/users/${userId}/subscription-request-history`, { params }, ); return response.data; }, // Get user devices getUserDevices: async ( userId: number, subscriptionId?: number, ): Promise<{ devices: { hwid: string; platform: string; device_model: string; created_at: string | null }[]; total: number; device_limit: number; }> => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/devices`, { params: subscriptionId != null ? { subscription_id: subscriptionId } : undefined, }); return response.data; }, // Delete single device deleteUserDevice: async ( userId: number, hwid: string, subscriptionId?: number, ): Promise<{ success: boolean; message: string; deleted_hwid: string | null }> => { const response = await apiClient.delete(`/cabinet/admin/users/${userId}/devices/${hwid}`, { params: subscriptionId != null ? { subscription_id: subscriptionId } : undefined, }); return response.data; }, // Reset all devices resetUserDevices: async ( userId: number, subscriptionId?: number, ): Promise<{ success: boolean; message: string; deleted_count: number }> => { const response = await apiClient.delete(`/cabinet/admin/users/${userId}/devices`, { params: subscriptionId != null ? { subscription_id: subscriptionId } : undefined, }); return response.data; }, // Get user gifts getUserGifts: async (userId: number): Promise => { const response = await apiClient.get(`/cabinet/admin/users/${userId}/gifts`); return response.data; }, };