/// API-related constants for the Worker app
///
/// This file contains all API endpoints, timeouts, and network-related configurations.
/// Base URLs should be configured per environment (dev, staging, production).
class ApiConstants {
  // Private constructor to prevent instantiation
  ApiConstants._();

  // ============================================================================
  // Base URLs
  // ============================================================================

  /// Base URL for all APIs (Frappe/ERPNext)
  static const String baseUrl = 'https://land.dbiz.com';

  /// Full API base URL (no version prefix, using Frappe endpoints)
  static String get apiBaseUrl => baseUrl;

  // ============================================================================
  // Timeout Configurations
  // ============================================================================

  /// Connection timeout in milliseconds (30 seconds)
  static const Duration connectionTimeout = Duration(milliseconds: 30000);

  /// Receive timeout in milliseconds (30 seconds)
  static const Duration receiveTimeout = Duration(milliseconds: 30000);

  /// Send timeout in milliseconds (30 seconds)
  static const Duration sendTimeout = Duration(milliseconds: 30000);

  // ============================================================================
  // Retry Configurations
  // ============================================================================

  /// Maximum number of retry attempts for failed requests
  static const int maxRetryAttempts = 3;

  /// Initial retry delay in milliseconds
  static const Duration initialRetryDelay = Duration(milliseconds: 1000);

  /// Maximum retry delay in milliseconds
  static const Duration maxRetryDelay = Duration(milliseconds: 5000);

  /// Retry delay multiplier for exponential backoff
  static const double retryDelayMultiplier = 2.0;

  // ============================================================================
  // Cache Configurations
  // ============================================================================

  /// Default cache duration (1 hour)
  static const Duration defaultCacheDuration = Duration(hours: 1);

  /// Products cache duration (24 hours)
  static const Duration productsCacheDuration = Duration(hours: 24);

  /// Profile cache duration (1 hour)
  static const Duration profileCacheDuration = Duration(hours: 1);

  /// Categories cache duration (48 hours)
  static const Duration categoriesCacheDuration = Duration(hours: 48);

  /// Maximum cache size in bytes (50 MB)
  static const int maxCacheSize = 50 * 1024 * 1024;

  // ============================================================================
  // Request Headers
  // ============================================================================

  /// Content-Type header for JSON requests
  static const String contentTypeJson = 'application/json';

  /// Accept header for JSON responses
  static const String acceptJson = 'application/json';

  /// Accept-Language header for Vietnamese
  static const String acceptLanguageVi = 'vi';

  /// Accept-Language header for English
  static const String acceptLanguageEn = 'en';

  // ============================================================================
  // Authentication Endpoints
  // ============================================================================

  /// Request OTP for phone number login
  /// POST /auth/request-otp
  /// Body: { "phone": "+84912345678" }
  static const String requestOtp = '/auth/request-otp';

  /// Verify OTP code
  /// POST /auth/verify-otp
  /// Body: { "phone": "+84912345678", "otp": "123456" }
  static const String verifyOtp = '/auth/verify-otp';

  /// Register new user
  /// POST /auth/register
  /// Body: { "name": "...", "phone": "...", "email": "...", "userType": "..." }
  static const String register = '/auth/register';

  /// Refresh access token
  /// POST /auth/refresh-token
  /// Headers: { "Authorization": "Bearer {refreshToken}" }
  static const String refreshToken = '/auth/refresh-token';

  /// Logout user
  /// POST /auth/logout
  static const String logout = '/auth/logout';

  /// Get current user profile
  /// GET /auth/me
  static const String getCurrentUser = '/auth/me';

  // ============================================================================
  // Loyalty Program Endpoints
  // ============================================================================

  /// Get loyalty points and tier information
  /// GET /loyalty/points
  static const String getLoyaltyPoints = '/loyalty/points';

  /// Get loyalty points transaction history
  /// GET /loyalty/transactions?page={page}&limit={limit}
  static const String getPointsHistory = '/loyalty/transactions';

  /// Get available rewards for redemption
  /// GET /loyalty/rewards?category={category}
  static const String getRewards = '/loyalty/rewards';

  /// Redeem a reward
  /// POST /loyalty/rewards/{rewardId}/redeem
  static const String redeemReward = '/loyalty/rewards';

  /// Get user's redeemed gifts
  /// GET /loyalty/gifts?status={active|used|expired}
  static const String getGifts = '/loyalty/gifts';

  /// Get referral information
  /// GET /loyalty/referral
  static const String getReferralInfo = '/loyalty/referral';

  /// Share referral link
  /// POST /loyalty/referral/share
  /// Body: { "method": "whatsapp|telegram|sms" }
  static const String shareReferral = '/loyalty/referral/share';

  // ============================================================================
  // Favorites/Wishlist Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Get favorite/wishlist items for current user
  /// POST /api/method/building_material.building_material.api.item_wishlist.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  static const String getFavorites = '/building_material.building_material.api.item_wishlist.get_list';

  /// Add item to wishlist
  /// POST /api/method/building_material.building_material.api.item_wishlist.add_to_wishlist
  /// Body: { "item_id": "GIB20 G04" }
  static const String addToFavorites = '/building_material.building_material.api.item_wishlist.add_to_wishlist';

  /// Remove item from wishlist
  /// POST /api/method/building_material.building_material.api.item_wishlist.remove_from_wishlist
  /// Body: { "item_id": "GIB20 G04" }
  static const String removeFromFavorites = '/building_material.building_material.api.item_wishlist.remove_from_wishlist';

  // ============================================================================
  // Product Endpoints
  // ============================================================================

  /// Get all products with pagination
  /// GET /products?page={page}&limit={limit}&category={categoryId}
  static const String getProducts = '/products';

  /// Get product details by ID
  /// GET /products/{productId}
  static const String getProductDetails = '/products';

  /// Search products
  /// GET /products/search?q={query}&page={page}&limit={limit}
  static const String searchProducts = '/products/search';

  /// Get product categories
  /// GET /categories
  static const String getCategories = '/categories';

  /// Get products by category
  /// GET /categories/{categoryId}/products
  static const String getProductsByCategory = '/categories';

  // ============================================================================
  // Cart Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Add items to cart
  /// POST /api/method/building_material.building_material.api.user_cart.add_to_cart
  /// Body: { "items": [{ "item_id": "...", "amount": 0, "quantity": 0 }] }
  static const String addToCart = '/building_material.building_material.api.user_cart.add_to_cart';

  /// Remove items from cart
  /// POST /api/method/building_material.building_material.api.user_cart.remove_from_cart
  /// Body: { "item_ids": ["item_id1", "item_id2"] }
  static const String removeFromCart = '/building_material.building_material.api.user_cart.remove_from_cart';

  /// Get user's cart items
  /// POST /api/method/building_material.building_material.api.user_cart.get_user_cart
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  static const String getUserCart = '/building_material.building_material.api.user_cart.get_user_cart';

  // ============================================================================
  // Order Endpoints
  // ============================================================================

  /// Get order status list (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sales_order.get_order_status_list
  /// Returns: { "message": [{ "status": "...", "label": "...", "color": "...", "index": 0 }] }
  static const String getOrderStatusList = '/building_material.building_material.api.sales_order.get_order_status_list';

  /// Create new order (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sales_order.save
  /// Body: { "transaction_date": "...", "delivery_date": "...", "items": [...], ... }
  static const String createOrder = '/building_material.building_material.api.sales_order.save';

  /// Generate QR code for payment (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.v1.qrcode.generate
  /// Body: { "order_id": "SAL-ORD-2025-00048" }
  /// Returns: { "message": { "qr_code": "...", "amount": null, "transaction_id": "...", "bank_info": {...} } }
  static const String generateQrCode = '/building_material.building_material.api.v1.qrcode.generate';

  /// Upload file (bill/invoice/attachment) (requires sid and csrf_token)
  /// POST /api/method/upload_file
  /// Form-data: { "file": File, "is_private": "1", "folder": "Home/Attachments", "doctype": "Sales Order", "docname": "SAL-ORD-2025-00058-1", "optimize": "true" }
  /// Returns: { "message": { "file_url": "...", "file_name": "...", ... } }
  static const String uploadFile = '/upload_file';

  /// Get list of orders (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sales_order.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  /// Returns: { "message": [...] }
  static const String getOrdersList = '/building_material.building_material.api.sales_order.get_list';

  /// Get order details (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sales_order.get_detail
  /// Body: { "name": "SAL-ORD-2025-00058-1" }
  /// Returns: { "message": {...} }
  static const String getOrderDetail = '/building_material.building_material.api.sales_order.get_detail';

  /// Update order address (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sales_order.update
  /// Body: { "name": "SAL-ORD-2025-00053", "shipping_address_name": "...", "customer_address": "..." }
  static const String updateOrder = '/building_material.building_material.api.sales_order.update';

  /// Cancel order (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sales_order.cancel
  /// Body: { "name": "SAL-ORD-2025-00054" }
  static const String cancelOrder = '/building_material.building_material.api.sales_order.cancel';

  /// Get user's orders (legacy endpoint - may be deprecated)
  /// GET /orders?status={status}&page={page}&limit={limit}
  static const String getOrders = '/orders';

  /// Get order details by ID
  /// GET /orders/{orderId}
  static const String getOrderDetails = '/orders';

  /// Get payment transactions
  /// GET /payments?page={page}&limit={limit}
  static const String getPayments = '/payments';

  /// Get payment details
  /// GET /payments/{paymentId}
  static const String getPaymentDetails = '/payments';

  /// Get payment list (Frappe API)
  /// POST /api/method/building_material.building_material.api.payment.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  static const String getPaymentList =
      '/building_material.building_material.api.payment.get_list';

  /// Get payment detail (Frappe API)
  /// POST /api/method/building_material.building_material.api.payment.get_detail
  /// Body: { "name": "ACC-PAY-2025-00020" }
  static const String getPaymentDetail =
      '/building_material.building_material.api.payment.get_detail';

  /// Get invoice list (Frappe API)
  /// POST /api/method/building_material.building_material.api.invoice.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  static const String getInvoiceList =
      '/building_material.building_material.api.invoice.get_list';

  /// Get invoice detail (Frappe API)
  /// POST /api/method/building_material.building_material.api.invoice.get_detail
  /// Body: { "name": "ACC-SINV-2025-00041" }
  static const String getInvoiceDetail =
      '/building_material.building_material.api.invoice.get_detail';

  // ============================================================================
  // Project Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Get project status list (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.project.get_project_status_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  /// Returns: { "message": [{ "status": "...", "label": "...", "color": "...", "index": 0 }] }
  static const String getProjectStatusList =
      '/building_material.building_material.api.project.get_project_status_list';

  /// Get list of project submissions (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.project.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  /// Returns: { "message": [{ "name": "...", "designed_area": "...", "design_area": 0, ... }] }
  static const String getProjectList =
      '/building_material.building_material.api.project.get_list';

  /// Save (create/update) project submission
  /// POST /api/method/building_material.building_material.api.project.save
  /// Body: {
  ///   "name": "...",  // optional for new, required for update
  ///   "designed_area": "Project Name",
  ///   "address_of_project": "...",
  ///   "project_owner": "...",
  ///   "design_firm": "...",
  ///   "contruction_contractor": "...",
  ///   "design_area": 350.5,
  ///   "products_included_in_the_design": "...",
  ///   "project_progress": "progress_id",  // from ProjectProgress.id
  ///   "expected_commencement_date": "2026-01-15",
  ///   "description": "...",
  ///   "request_date": "2025-11-26 09:30:00"
  /// }
  static const String saveProject =
      '/building_material.building_material.api.project.save';

  /// Get project detail (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.project.get_detail
  /// Body: { "name": "#DA00011" }
  /// Returns: Full project detail with all fields
  static const String getProjectDetail =
      '/building_material.building_material.api.project.get_detail';

  /// Delete project file/attachment (requires sid and csrf_token)
  /// POST /api/method/frappe.desk.form.utils.remove_attach
  /// Form-data: { "fid": "file_id", "dt": "Architectural Project", "dn": "project_name" }
  static const String removeProjectFile = '/frappe.desk.form.utils.remove_attach';

  // ============================================================================
  // Sample Project / Model House Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Get list of sample/model house projects (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sample_project.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  /// Returns: { "message": [{ "name": "...", "project_name": "...", "notes": "...", "link": "...", "thumbnail": "..." }] }
  static const String getSampleProjectList =
      '/building_material.building_material.api.sample_project.get_list';

  /// Get detail of a sample/model house project (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.sample_project.get_detail
  /// Body: { "name": "PROJ-0001" }
  /// Returns: { "message": { "name": "...", "project_name": "...", "notes": "...", "link": "...", "thumbnail": "...", "files_list": [...] } }
  static const String getSampleProjectDetail =
      '/building_material.building_material.api.sample_project.get_detail';

  // ============================================================================
  // Design Request Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Get list of design requests (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.design_request.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  /// Returns: { "message": [{ "name": "...", "subject": "...", "description": "...", "dateline": "...", "status": "...", "status_color": "..." }] }
  static const String getDesignRequestList =
      '/building_material.building_material.api.design_request.get_list';

  /// Get detail of a design request (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.design_request.get_detail
  /// Body: { "name": "ISS-2025-00005" }
  /// Returns: { "message": { "name": "...", "subject": "...", "description": "...", "dateline": "...", "status": "...", "status_color": "...", "files_list": [...] } }
  static const String getDesignRequestDetail =
      '/building_material.building_material.api.design_request.get_detail';

  /// Create a new design request (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.design_request.create
  /// Body: { "subject": "...", "area": "...", "region": "...", "desired_style": "...", "estimated_budget": "...", "detailed_requirements": "...", "dateline": "..." }
  /// Returns: { "message": { "success": true, "data": { "name": "ISS-2025-00006" } } }
  static const String createDesignRequest =
      '/building_material.building_material.api.design_request.create';

  /// Create new project (legacy endpoint - may be deprecated)
  /// POST /projects
  static const String createProject = '/projects';

  /// Get user's projects (legacy endpoint - may be deprecated)
  /// GET /projects?status={status}&page={page}&limit={limit}
  static const String getProjects = '/projects';

  /// Get project details by ID (legacy endpoint - may be deprecated)
  /// GET /projects/{projectId}
  static const String getProjectDetails = '/projects';

  /// Update project (legacy endpoint - may be deprecated)
  /// PUT /projects/{projectId}
  static const String updateProject = '/projects';

  /// Update project progress (legacy endpoint - may be deprecated)
  /// PATCH /projects/{projectId}/progress
  /// Body: { "progress": 75 }
  static const String updateProjectProgress = '/projects';

  /// Delete project (legacy endpoint - may be deprecated)
  /// DELETE /projects/{projectId}
  static const String deleteProject = '/projects';

  // ============================================================================
  // Quote Endpoints
  // ============================================================================

  /// Create new quote
  /// POST /quotes
  static const String createQuote = '/quotes';

  /// Get user's quotes
  /// GET /quotes?status={status}&page={page}&limit={limit}
  static const String getQuotes = '/quotes';

  /// Get quote details by ID
  /// GET /quotes/{quoteId}
  static const String getQuoteDetails = '/quotes';

  /// Update quote
  /// PUT /quotes/{quoteId}
  static const String updateQuote = '/quotes';

  /// Send quote to client
  /// POST /quotes/{quoteId}/send
  /// Body: { "email": "client@example.com" }
  static const String sendQuote = '/quotes';

  /// Convert quote to order
  /// POST /quotes/{quoteId}/convert
  static const String convertQuoteToOrder = '/quotes';

  // ============================================================================
  // Chat Endpoints
  // ============================================================================

  /// WebSocket endpoint for real-time chat
  static const String chatWebSocket = '/ws/chat';

  /// Get chat messages
  /// GET /chat/messages?roomId={roomId}&before={messageId}&limit={limit}
  static const String getChatMessages = '/chat/messages';

  /// Send chat message
  /// POST /chat/messages
  /// Body: { "roomId": "...", "text": "...", "attachments": [...] }
  static const String sendChatMessage = '/chat/messages';

  /// Mark messages as read
  /// POST /chat/messages/read
  /// Body: { "messageIds": [...] }
  static const String markMessagesAsRead = '/chat/messages/read';

  // ============================================================================
  // Account & Profile Endpoints
  // ============================================================================

  /// Get user profile
  /// GET /profile
  static const String getProfile = '/profile';

  /// Update user profile
  /// PUT /profile
  static const String updateProfile = '/profile';

  /// Upload avatar
  /// POST /profile/avatar
  /// Form-data: { "avatar": File }
  static const String uploadAvatar = '/profile/avatar';

  /// Change password
  /// POST /profile/change-password
  /// Body: { "currentPassword": "...", "newPassword": "..." }
  static const String changePassword = '/profile/change-password';

  /// Get user addresses
  /// GET /addresses
  static const String getAddresses = '/addresses';

  /// Add new address
  /// POST /addresses
  static const String addAddress = '/addresses';

  /// Update address
  /// PUT /addresses/{addressId}
  static const String updateAddress = '/addresses';

  /// Delete address
  /// DELETE /addresses/{addressId}
  static const String deleteAddress = '/addresses';

  /// Set default address
  /// POST /addresses/{addressId}/set-default
  static const String setDefaultAddress = '/addresses';

  // ============================================================================
  // Promotion Endpoints
  // ============================================================================

  /// Get active promotions
  /// GET /promotions?category={category}
  static const String getPromotions = '/promotions';

  /// Get promotion details
  /// GET /promotions/{promotionId}
  static const String getPromotionDetails = '/promotions';

  /// Claim promotion
  /// POST /promotions/{promotionId}/claim
  static const String claimPromotion = '/promotions';

  // ============================================================================
  // Frappe/ERPNext API Endpoints
  // ============================================================================

  /// Frappe API method prefix
  static const String frappeApiMethod = '/api/method';

  /// Get Frappe session (public API, no auth required)
  /// POST /api/method/dbiz_common.dbiz_common.api.auth.get_session
  /// Returns: { "message": { "data": { "sid": "...", "csrf_token": "..." } }, "full_name": "..." }
  static const String frappeGetSession = '/dbiz_common.dbiz_common.api.auth.get_session';

  /// Login with phone (requires session sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.auth.login
  /// Body: { "username": "phone", "googleid": null, "facebookid": null, "zaloid": null }
  /// Returns: { "message": { "data": { "sid": "...", "csrf_token": "..." } }, "full_name": "..." }
  static const String frappeLogin = '/building_material.building_material.api.auth.login';

  /// Frappe client get_list (requires sid and csrf_token)
  /// POST /api/method/frappe.client.get_list
  static const String frappeGetList = '/frappe.client.get_list';

  /// Frappe client get (requires sid and csrf_token)
  /// POST /api/method/frappe.client.get
  static const String frappeGet = '/frappe.client.get';

  /// Register user (requires session sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.user.register
  static const String frappeRegister = '/building_material.building_material.api.user.register';

  /// Frappe public API user ID
  static const String frappePublicUserId = 'public_api@dbiz.com';

  // ============================================================================
  // Product/Item Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Get product/item list (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.item.get_list
  /// Body: { "limit_start": 0, "limit_page_length": 0 }
  static const String frappeGetItems = '/building_material.building_material.api.item.get_list';

  /// Get product/item detail (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.item.get_detail
  /// Body: { "name": "item_code" }
  static const String frappeGetItemDetail = '/building_material.building_material.api.item.get_detail';

  /// Get item attributes list (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.item_attribute.get_list
  /// Body: { "filters": {"is_group": 0}, "limit_page_length": 0 }
  static const String frappeGetItemAttributes = '/building_material.building_material.api.item_attribute.get_list';

  // ============================================================================
  // Review/Feedback Endpoints (Frappe ERPNext)
  // ============================================================================

  /// Get list of reviews for a product (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.item_feedback.get_list
  /// Body: { "limit_page_length": 10, "limit_start": 0, "item_id": "GIB20 G04" }
  static const String frappeGetReviews = '/building_material.building_material.api.item_feedback.get_list';

  /// Create or update a review (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.item_feedback.update
  /// Body: { "item_id": "...", "rating": 0.5, "comment": "...", "name": "..." }
  /// Note: rating is 0-1 scale (0.5 = 50% or 2.5 stars out of 5)
  /// Note: name is optional - if provided, updates existing review
  static const String frappeUpdateReview = '/building_material.building_material.api.item_feedback.update';

  /// Delete a review (requires sid and csrf_token)
  /// POST /api/method/building_material.building_material.api.item_feedback.delete
  /// Body: { "name": "ITEM-{item_id}-{user_email}" }
  static const String frappeDeleteReview = '/building_material.building_material.api.item_feedback.delete';

  // ============================================================================
  // Notification Endpoints
  // ============================================================================

  /// Get notifications
  /// GET /notifications?type={type}&page={page}&limit={limit}
  static const String getNotifications = '/notifications';

  /// Mark notification as read
  /// POST /notifications/{notificationId}/read
  static const String markNotificationAsRead = '/notifications';

  /// Mark all notifications as read
  /// POST /notifications/read-all
  static const String markAllNotificationsAsRead = '/notifications/read-all';

  /// Clear all notifications
  /// DELETE /notifications
  static const String clearAllNotifications = '/notifications';

  /// Register FCM token for push notifications
  /// POST /notifications/fcm-token
  /// Body: { "token": "..." }
  static const String registerFcmToken = '/notifications/fcm-token';

  // ============================================================================
  // Helper Methods
  // ============================================================================

  /// Build full URL for endpoint
  ///
  /// Example:
  /// ```dart
  /// final url = ApiConstants.buildUrl('/api/method/frappe.client.get_list', {'doctype': 'Item'});
  /// // Returns: https://land.dbiz.com/api/method/frappe.client.get_list?doctype=Item
  /// ```
  static String buildUrl(String endpoint, [Map<String, String>? queryParams]) {
    final uri = Uri.parse('$apiBaseUrl$endpoint');
    if (queryParams != null && queryParams.isNotEmpty) {
      return uri.replace(queryParameters: queryParams).toString();
    }
    return uri.toString();
  }

  /// Build URL with path parameters
  ///
  /// Example:
  /// ```dart
  /// final url = ApiConstants.buildUrlWithParams('/api/resource/Item/{id}', {'id': '123'});
  /// // Returns: https://land.dbiz.com/api/resource/Item/123
  /// ```
  static String buildUrlWithParams(
    String endpoint,
    Map<String, String> params,
  ) {
    String url = endpoint;
    params.forEach((key, value) {
      url = url.replaceAll('{$key}', value);
    });
    return '$apiBaseUrl$url';
  }
}
