# API Client Quick Reference

## Import

```dart
import 'package:minhthu/core/core.dart';
```

## Initialization

```dart
final secureStorage = SecureStorage();
final apiClient = ApiClient(
  secureStorage,
  onUnauthorized: () => context.go('/login'),
);
```

## HTTP Methods

### GET Request

```dart
final response = await apiClient.get(
  '/warehouses',
  queryParameters: {'limit': 10},
);
```

### POST Request

```dart
final response = await apiClient.post(
  '/auth/login',
  data: {'username': 'user', 'password': 'pass'},
);
```

### PUT Request

```dart
final response = await apiClient.put(
  '/products/123',
  data: {'name': 'Updated'},
);
```

### DELETE Request

```dart
final response = await apiClient.delete('/products/123');
```

## Parse API Response

```dart
final apiResponse = ApiResponse.fromJson(
  response.data,
  (json) => User.fromJson(json), // or your model
);

if (apiResponse.isSuccess && apiResponse.value != null) {
  final data = apiResponse.value;
  // Use data
} else {
  final error = apiResponse.getErrorMessage();
  // Handle error
}
```

## Error Handling

```dart
try {
  final response = await apiClient.get('/products');
} on NetworkException catch (e) {
  // Timeout, no internet
  print('Network error: ${e.message}');
} on ServerException catch (e) {
  // HTTP errors (401, 404, 500, etc.)
  print('Server error: ${e.message}');
  print('Error code: ${e.code}');
}
```

## Token Management

### Save Token

```dart
await secureStorage.saveAccessToken('your_token');
await secureStorage.saveRefreshToken('refresh_token');
```

### Get Token

```dart
final token = await secureStorage.getAccessToken();
```

### Check Authentication

```dart
final isAuthenticated = await apiClient.isAuthenticated();
```

### Clear Tokens (Logout)

```dart
await apiClient.clearAuth();
```

## API Endpoints

Use constants from `ApiEndpoints`:

```dart
// Authentication
ApiEndpoints.login           // /auth/login
ApiEndpoints.logout          // /auth/logout

// Warehouses
ApiEndpoints.warehouses      // /warehouses
ApiEndpoints.warehouseById(1) // /warehouses/1

// Products
ApiEndpoints.products        // /products
ApiEndpoints.productById(123) // /products/123

// Query parameters helper
ApiEndpoints.productQueryParams(
  warehouseId: 1,
  type: 'import',
) // {warehouseId: 1, type: 'import'}
```

## Utilities

### Test Connection

```dart
final isConnected = await apiClient.testConnection();
```

### Update Base URL

```dart
apiClient.updateBaseUrl('https://dev-api.example.com');
```

### Get Current Token

```dart
final token = await apiClient.getAccessToken();
```

## Common Patterns

### Login Flow

```dart
// 1. Login
final response = await apiClient.post(
  ApiEndpoints.login,
  data: {'username': username, 'password': password},
);

// 2. Parse
final apiResponse = ApiResponse.fromJson(
  response.data,
  (json) => User.fromJson(json),
);

// 3. Save tokens
if (apiResponse.isSuccess && apiResponse.value != null) {
  final user = apiResponse.value!;
  await secureStorage.saveAccessToken(user.accessToken);
  await secureStorage.saveUserId(user.userId);
}
```

### Repository Pattern

```dart
class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
  final ApiClient apiClient;

  WarehouseRemoteDataSourceImpl(this.apiClient);

  @override
  Future<List<Warehouse>> getWarehouses() async {
    final response = await apiClient.get(ApiEndpoints.warehouses);

    final apiResponse = ApiResponse.fromJson(
      response.data,
      (json) => (json as List).map((e) => Warehouse.fromJson(e)).toList(),
    );

    if (apiResponse.isSuccess && apiResponse.value != null) {
      return apiResponse.value!;
    } else {
      throw ServerException(apiResponse.getErrorMessage());
    }
  }
}
```

## Configuration

### Set Base URL

In `lib/core/constants/app_constants.dart`:

```dart
static const String apiBaseUrl = 'https://api.example.com';
```

### Set Timeouts

In `lib/core/constants/app_constants.dart`:

```dart
static const int connectionTimeout = 30000; // 30 seconds
static const int receiveTimeout = 30000;
static const int sendTimeout = 30000;
```

## Files Location

- API Client: `/lib/core/network/api_client.dart`
- API Response: `/lib/core/network/api_response.dart`
- Secure Storage: `/lib/core/storage/secure_storage.dart`
- API Endpoints: `/lib/core/constants/api_endpoints.dart`
- Examples: `/lib/core/network/api_client_example.dart`
- Documentation: `/lib/core/network/README.md`

## Important Notes

1. **Automatic Token Injection**: Bearer token is automatically added to all requests
2. **401 Handling**: 401 errors automatically clear tokens and trigger `onUnauthorized` callback
3. **Logging**: All requests/responses are logged with sensitive data redacted
4. **Singleton Storage**: SecureStorage is a singleton - use `SecureStorage()` everywhere
5. **Error Codes**: ServerException includes error codes (e.g., '401', '404', '500')

## Common Issues

### Token not injected?
Check if token exists: `await secureStorage.getAccessToken()`

### 401 not clearing tokens?
Verify `onUnauthorized` callback is set in ApiClient constructor

### Connection timeout?
Check network, verify base URL, increase timeout in constants

### Logs not showing?
Check Flutter DevTools console or developer.log output
