class AuthApiPaths {
  static const login = '/auth/login';
}

class ProductApiPaths {
  static const list = '/products';
  static const mine = '/products/mine';
  static const createPrivate = '/products/private';
  static const privateList = '/products/private';
  static String promotePrivate(int id) => '/products/private/$id/promote';
  static const pending = '/products/pending';
  static const aiCategorizeBulk = '/products/ai-categorize-bulk';
  static const deleted = '/products/deleted';
  static const merge = '/products/merge';
  static const mergePrivate = '/products/private/merge';
  static String updateMineCategory(int id) => '/products/mine/$id/category';
  static const backfillMineCategories = '/products/mine/backfill-categories';
  static String mergePreview(int sourceProductId, int targetProductId) =>
      '/products/merge-preview?sourceProductId=$sourceProductId&targetProductId=$targetProductId';
  static String setStatus(int id) => '/products/$id/status';
  static String update(int id) => '/products/$id';
  static String canonicalName(int id) => '/products/$id/canonical-name';
  static String canonicalNamePrivate(int id) =>
      '/products/private/$id/canonical-name';
  static String remove(int id) => '/products/$id';
  static String restore(int id) => '/products/$id/restore';
  static const bulkUpdate = '/products/bulk-update';
}

class AiApiPaths {
  static const models = '/ai/models';
  static String traces({
    required String source,
    int? limit,
    String? cursor,
    String? period,
    bool onlyErrors = false,
  }) {
    final params = <String, String>{'source': source};
    if (limit != null) params['limit'] = '$limit';
    if (cursor != null && cursor.isNotEmpty) params['cursor'] = cursor;
    if (period != null && period.isNotEmpty) params['period'] = period;
    if (onlyErrors) params['onlyErrors'] = 'true';
    final query = params.entries
        .map((e) =>
            '${Uri.encodeQueryComponent(e.key)}=${Uri.encodeQueryComponent(e.value)}')
        .join('&');
    return '/ai/traces?$query';
  }

  static String traceById(String traceId) =>
      '/ai/traces/${Uri.encodeComponent(traceId)}';
}

class CategoryApiPaths {
  static const tree = '/categories/tree';
}

class ReceiptImportApiPaths {
  static const refreshCategories = '/receipt-import/refresh-categories';
  static const unitMappings = '/receipt-import/unit-mappings';
}

class FlyerImportApiPaths {
  static const parse = '/flyer-import/parse';
  static const latestSession = '/flyer-import/sessions/latest';
  static String bySession(int sessionId) => '/flyer-import/sessions/$sessionId';
  static String sourceBySession(int sessionId) =>
      '/flyer-import/sessions/$sessionId/source';
  static String patchItem(int sessionId, int itemId) =>
      '/flyer-import/sessions/$sessionId/items/$itemId';
}

class FlyerSelectionApiPaths {
  static String bySession(int sessionId) =>
      '/flyer-sessions/$sessionId/selections';
  static String bulkBySession(int sessionId) =>
      '/flyer-sessions/$sessionId/selections/bulk';
  static String planToShoppingListBySession(int sessionId) =>
      '/flyer-sessions/$sessionId/selections/plan-to-shopping-list';
  static const open = '/flyer-selections/open';
}

class ShoppingListApiPaths {
  static const items = '/shopping-list/items';
  static String updateStatus(int itemId) =>
      '/shopping-list/items/$itemId/status';
}

class HelpTextApiPaths {
  static String byKey(String key) => '/help-texts/${Uri.encodeComponent(key)}';
}

class ReceiptAliasApiPaths {
  static const list = '/receipt-aliases';
  static String update(int id) => '/receipt-aliases/$id';
  static String remove(int id) => '/receipt-aliases/$id';
}

class RecipeApiPaths {
  static const list = '/recipes';
  static String detail(int id) => '/recipes/$id';
  static String update(int id) => '/recipes/$id';
  static String remove(int id) => '/recipes/$id';
  static String setVisibility(int id) => '/recipes/$id/visibility';
  static String share(int id) => '/recipes/$id/share';
  static String unshare(int id, String username) =>
      '/recipes/$id/share/${Uri.encodeComponent(username)}';
  static String inventoryPreview(int id) => '/recipes/$id/inventory-preview';
  static String analysis(int id) => '/recipes/$id/analysis';
  static String rematch(int id) => '/recipes/$id/rematch';
  static const parseMarkdown = '/recipes/parse-markdown';
  static const aiSuggestions = '/recipes/ai-suggestions';
}

class InventoryApiPaths {
  static const list = '/inventory';
  static const mergeMany = '/inventory/merge-many';
  static const bulkDelete = '/inventory/bulk-delete';
  static String update(int id) => '/inventory/$id';
  static String remove(int id) => '/inventory/$id';
  static String moveToPantry(int id) => '/inventory/$id/move-to-pantry';
  static String moveToPantryAdmin(int id) =>
      '/inventory/admin/$id/move-to-pantry';
  static String consume(int id) => '/inventory/$id/consume';
  static String consumptionHistory(int id) =>
      '/inventory/$id/consumption-history';
}

class AdminInventoryApiPaths {
  static const list = '/inventory/admin';
  static String withFilters({int? userId, String? sort}) {
    final params = <String, String>{};
    if (userId != null) params['userId'] = '$userId';
    if (sort != null && sort.isNotEmpty) params['sort'] = sort;
    if (params.isEmpty) return list;
    final query = params.entries
        .map((e) =>
            '${Uri.encodeQueryComponent(e.key)}=${Uri.encodeQueryComponent(e.value)}')
        .join('&');
    return '$list?$query';
  }

  static String update(int id) => '/inventory/admin/$id';
  static String remove(int id) => '/inventory/admin/$id';
  static String moveToPantry(int id) => '/inventory/admin/$id/move-to-pantry';
  static const merge = '/inventory/admin/merge';
  static String mergePreview(int sourceInventoryId, int targetInventoryId) =>
      '/inventory/admin/merge-preview?sourceInventoryId=$sourceInventoryId&targetInventoryId=$targetInventoryId';
}

class PantryApiPaths {
  static const list = '/pantry';
  static String remove(int id) => '/pantry/$id';
  static String moveToInventory(int id) => '/pantry/$id/move-to-inventory';
  static String moveToInventoryAdmin(int id) =>
      '/pantry/admin/$id/move-to-inventory';
  static const adminList = '/pantry/admin';
  static const adminCreate = '/pantry/admin';
  static String adminUpdate(int id) => '/pantry/admin/$id';
  static String adminRemove(int id) => '/pantry/admin/$id';
}

class UserApiPaths {
  static const me = '/users/me';
  static const list = '/users';
  static String setRole(int id) => '/users/$id/role';
  static String setPremium(int id) => '/users/$id/premium';
  static String setRecipeSharing(int id) => '/users/$id/recipe-sharing';
  static String updateEmail(int id) => '/users/$id/email';
  static String delete(int id) => '/users/$id';
  static String resetPassword(int id) => '/users/$id/reset-password';
}

class MealPlanApiPaths {
  static const list = '/meal-plan';

  static String listByRange(String from, String to) =>
      '$list?from=${Uri.encodeQueryComponent(from)}&to=${Uri.encodeQueryComponent(to)}';

  static String shoppingList(String from, String to) =>
      '$list/shopping-list?from=${Uri.encodeQueryComponent(from)}&to=${Uri.encodeQueryComponent(to)}';

  static String inventoryCompare(String from, String to) =>
      '$list/inventory-compare?from=${Uri.encodeQueryComponent(from)}&to=${Uri.encodeQueryComponent(to)}';

  static String removeByDate(String date) =>
      '$list/${Uri.encodeComponent(date)}';
}
