# TimeSafari Daily Notification Plugin API Reference

**Author**: Matthew Raymer  
**Version**: 2.3.0  
**Last Updated**: 2025-12-08

## Overview

This API reference provides comprehensive documentation for the TimeSafari Daily Notification Plugin, optimized for **native-first architecture** supporting Android, iOS, and Electron platforms.

### Platform Support
- ✅ **Android**: WorkManager + AlarmManager + SQLite
- ✅ **iOS**: BGTaskScheduler + UNUserNotificationCenter + Core Data  
- ✅ **Electron**: Desktop notifications + SQLite/LocalStorage
- ❌ **Web (PWA)**: Removed for native-first focus

## DailyNotificationPlugin Interface

### Configuration

#### `configure(options: ConfigureOptions): Promise<void>`

Configure the plugin with storage, TTL, and optimization settings.

**Parameters:**

- `options.storage`: `'shared'` | `'tiered'` - Storage mode
- `options.ttlSeconds`: `number` - TTL in seconds (default: 1800)
- `options.prefetchLeadMinutes`: `number` - Prefetch lead time (default: 15)
- `options.enableETagSupport`: `boolean` - Enable ETag conditional requests
- `options.enableErrorHandling`: `boolean` - Enable advanced error handling
- `options.enablePerformanceOptimization`: `boolean` - Enable performance optimization

### Core Methods

#### `scheduleDailyNotification(options: NotificationOptions): Promise<void>`

Schedule a daily notification with content fetching.

**Parameters:**

- `options.url`: `string` - Content endpoint URL
- `options.time`: `string` - Time in HH:MM format
- `options.title`: `string` - Notification title
- `options.body`: `string` - Notification body
- `options.sound`: `boolean` - Enable sound (optional)
- `options.retryConfig`: `RetryConfiguration` - Custom retry settings (optional)

#### `getLastNotification(): Promise<NotificationResponse | null>`

Get the last scheduled notification.

#### `cancelAllNotifications(): Promise<void>`

Cancel all scheduled notifications.

### Platform-Specific Methods

#### Android Only

##### `getExactAlarmStatus(): Promise<ExactAlarmStatus>`

Get exact alarm permission and capability status.

##### `requestExactAlarmPermission(): Promise<void>`

Request exact alarm permission from user.

##### `openExactAlarmSettings(): Promise<void>`

Open exact alarm settings in system preferences.

##### `getRebootRecoveryStatus(): Promise<RecoveryStatus>`

Get reboot recovery status and statistics.

##### `isAlarmScheduled(options: { triggerAtMillis: number }): Promise<{ scheduled: boolean; triggerAtMillis: number }>`

Check if an alarm is scheduled for a specific trigger time. Useful for debugging and verification.

**Parameters:**
- `options.triggerAtMillis`: `number` - The trigger time in milliseconds (Unix timestamp)

**Returns:**
- `scheduled`: `boolean` - Whether the alarm is currently scheduled
- `triggerAtMillis`: `number` - The trigger time that was checked

**Example:**
```typescript
const result = await DailyNotification.isAlarmScheduled({
  triggerAtMillis: 1762421400000
});
console.log(`Alarm scheduled: ${result.scheduled}`);
```

##### `getNextAlarmTime(): Promise<{ scheduled: boolean; triggerAtMillis?: number }>`

Get the next scheduled alarm time from AlarmManager. Requires Android 5.0+ (API 21+).

**Returns:**
- `scheduled`: `boolean` - Whether any alarm is scheduled
- `triggerAtMillis`: `number | undefined` - The next alarm trigger time (if scheduled)

**Example:**
```typescript
const result = await DailyNotification.getNextAlarmTime();
if (result.scheduled) {
  const nextAlarm = new Date(result.triggerAtMillis);
  console.log(`Next alarm: ${nextAlarm.toLocaleString()}`);
}
```

##### `testAlarm(options?: { secondsFromNow?: number }): Promise<{ scheduled: boolean; secondsFromNow: number; triggerAtMillis: number }>`

Schedule a test alarm that fires in a few seconds. Useful for verifying alarm delivery works correctly.

**Parameters:**
- `options.secondsFromNow`: `number` (optional) - Seconds from now to fire the alarm (default: 5)

**Returns:**
- `scheduled`: `boolean` - Whether the alarm was scheduled successfully
- `secondsFromNow`: `number` - The delay used
- `triggerAtMillis`: `number` - The trigger time in milliseconds

**Example:**
```typescript
const result = await DailyNotification.testAlarm({ secondsFromNow: 10 });
console.log(`Test alarm scheduled for ${result.secondsFromNow} seconds`);
```

#### iOS Only

##### `getNotificationPermissionStatus(): Promise<NotificationPermissionStatus>`

Get notification permission status on iOS. Required before scheduling notifications.

**Returns:**
- `authorized`: `boolean` - Whether notifications are authorized
- `denied`: `boolean` - Whether notifications are denied
- `notDetermined`: `boolean` - Whether permission hasn't been requested yet
- `provisional`: `boolean` - Whether provisional authorization is granted (iOS 12+)

**Example:**
```typescript
const status = await DailyNotification.getNotificationPermissionStatus();
if (!status.authorized) {
  await DailyNotification.requestNotificationPermission();
}
```

##### `requestNotificationPermission(): Promise<{ granted: boolean }>`

Request notification permission from user. Must be called before scheduling notifications.

**Returns:**
- `granted`: `boolean` - Whether permission was granted

**Example:**
```typescript
const result = await DailyNotification.requestNotificationPermission();
if (result.granted) {
  await DailyNotification.scheduleDailyNotification({ ... });
}
```

##### `getPendingNotifications(): Promise<{ count: number; notifications: PendingNotification[] }>`

Get all pending notifications from UNUserNotificationCenter. Useful for debugging and verification.

**Returns:**
- `count`: `number` - Number of pending notifications
- `notifications`: `PendingNotification[]` - Array of pending notification details

**Example:**
```typescript
const result = await DailyNotification.getPendingNotifications();
console.log(`Pending notifications: ${result.count}`);
result.notifications.forEach(notif => {
  console.log(`Notification: ${notif.identifier} at ${notif.triggerDate}`);
});
```

##### `getBackgroundTaskStatus(): Promise<BackgroundTaskStatus>`

Get background task registration and execution status. Useful for debugging background prefetch.

**Returns:**
- `fetchTaskRegistered`: `boolean` - Whether fetch background task is registered
- `notifyTaskRegistered`: `boolean` - Whether notify background task is registered
- `lastFetchExecution`: `number | null` - Last fetch execution time (epoch ms)
- `lastNotifyExecution`: `number | null` - Last notify execution time (epoch ms)
- `backgroundRefreshEnabled`: `boolean` - Whether Background App Refresh is enabled

**Example:**
```typescript
const status = await DailyNotification.getBackgroundTaskStatus();
if (!status.backgroundRefreshEnabled) {
  console.warn('Background App Refresh is disabled. Enable in Settings.');
}
```

##### `openNotificationSettings(): Promise<void>`

Open notification settings in iOS Settings app. Useful for guiding users to enable notifications.

**Example:**
```typescript
await DailyNotification.openNotificationSettings();
```

##### `openBackgroundAppRefreshSettings(): Promise<void>`

Open Background App Refresh settings in iOS Settings app. Useful for guiding users to enable background execution.

**Example:**
```typescript
await DailyNotification.openBackgroundAppRefreshSettings();
```

### Management Methods

#### `maintainRollingWindow(): Promise<void>`

Manually trigger rolling window maintenance.

#### `getRollingWindowStats(): Promise<RollingWindowStats>`

Get rolling window statistics and status.

### Optimization Methods

#### `optimizeDatabase(): Promise<void>`

Optimize database performance with indexes and settings.

#### `optimizeMemory(): Promise<void>`

Optimize memory usage and perform cleanup.

#### `optimizeBattery(): Promise<void>`

Optimize battery usage and background CPU.

### Metrics and Monitoring

#### `getPerformanceMetrics(): Promise<PerformanceMetrics>`

Get comprehensive performance metrics.

#### `getErrorMetrics(): Promise<ErrorMetrics>`

Get error handling metrics and statistics.

#### `getNetworkMetrics(): Promise<NetworkMetrics>`

Get network efficiency metrics (ETag support).

#### `getMemoryMetrics(): Promise<MemoryMetrics>`

Get memory usage metrics and statistics.

#### `getObjectPoolMetrics(): Promise<ObjectPoolMetrics>`

Get object pooling efficiency metrics.

### Utility Methods

#### `resetPerformanceMetrics(): Promise<void>`

Reset all performance metrics to zero.

#### `resetErrorMetrics(): Promise<void>`

Reset error handling metrics.

#### `clearRetryStates(): Promise<void>`

Clear all retry states and operations.

#### `cleanExpiredETags(): Promise<void>`

Clean expired ETag cache entries.

## Data Types

### ConfigureOptions

```typescript
interface ConfigureOptions {
  storage?: 'shared' | 'tiered';
  ttlSeconds?: number;
  prefetchLeadMinutes?: number;
  enableETagSupport?: boolean;
  enableErrorHandling?: boolean;
  enablePerformanceOptimization?: boolean;
  maxRetries?: number;
  baseRetryDelay?: number;
  maxRetryDelay?: number;
  backoffMultiplier?: number;
  memoryWarningThreshold?: number;
  memoryCriticalThreshold?: number;
  objectPoolSize?: number;
  maxObjectPoolSize?: number;
}
```

### NotificationOptions

```typescript
interface NotificationOptions {
  url: string;
  time: string;
  title: string;
  body: string;
  sound?: boolean;
  retryConfig?: RetryConfiguration;
}
```

### ExactAlarmStatus (Android)

```typescript
interface ExactAlarmStatus {
  supported: boolean;
  enabled: boolean;
  canSchedule: boolean;
  fallbackWindow: string;
}
```

### NotificationPermissionStatus (iOS)

```typescript
interface NotificationPermissionStatus {
  authorized: boolean;
  denied: boolean;
  notDetermined: boolean;
  provisional: boolean; // iOS 12+
}
```

### PendingNotification (iOS)

```typescript
interface PendingNotification {
  identifier: string;
  title: string;
  body: string;
  triggerDate: number; // epoch ms
  triggerType: 'calendar' | 'timeInterval' | 'location';
  repeats: boolean;
}
```

### BackgroundTaskStatus (iOS)

```typescript
interface BackgroundTaskStatus {
  fetchTaskRegistered: boolean;
  notifyTaskRegistered: boolean;
  lastFetchExecution: number | null; // epoch ms
  lastNotifyExecution: number | null; // epoch ms
  backgroundRefreshEnabled: boolean;
}
```

### PerformanceMetrics

```typescript
interface PerformanceMetrics {
  overallScore: number;
  databasePerformance: number;
  memoryEfficiency: number;
  batteryEfficiency: number;
  objectPoolEfficiency: number;
  totalDatabaseQueries: number;
  averageMemoryUsage: number;
  objectPoolHits: number;
  backgroundCpuUsage: number;
  totalNetworkRequests: number;
  recommendations: string[];
}
```

### ErrorMetrics

```typescript
interface ErrorMetrics {
  totalErrors: number;
  networkErrors: number;
  storageErrors: number;
  schedulingErrors: number;
  permissionErrors: number;
  configurationErrors: number;
  systemErrors: number;
  unknownErrors: number;
  cacheHitRatio: number;
}
```

## Error Handling

All methods return promises that reject with descriptive error messages. The plugin includes comprehensive error categorization and retry logic.

### Common Error Types

- **Network Errors**: Connection timeouts, DNS failures
- **Storage Errors**: Database corruption, disk full
- **Permission Errors**: Missing exact alarm permission (Android) or notification permission (iOS)
- **Configuration Errors**: Invalid parameters, unsupported settings
- **System Errors**: Out of memory, platform limitations

### Platform-Specific Errors

#### Android

- `EXACT_ALARM_PERMISSION_DENIED`: User denied exact alarm permission
- `BOOT_RECEIVER_NOT_REGISTERED`: Boot receiver not properly registered
- `ALARM_MANAGER_UNAVAILABLE`: AlarmManager service unavailable

#### iOS

- `NOTIFICATION_PERMISSION_DENIED`: User denied notification permission
- `BACKGROUND_REFRESH_DISABLED`: Background App Refresh disabled in Settings
- `PENDING_NOTIFICATION_LIMIT_EXCEEDED`: Exceeded 64 notification limit
- `BG_TASK_NOT_REGISTERED`: Background task not registered in Info.plist
- `BG_TASK_EXECUTION_FAILED`: Background task execution failed

## Platform Differences

### Android

- Requires `SCHEDULE_EXACT_ALARM` permission for precise timing
- Falls back to windowed alarms (±10m) if exact permission denied
- Supports reboot recovery with broadcast receivers
- Full performance optimization features
- Alarms do NOT persist across reboot (must reschedule)
- Force stop clears all alarms (cannot bypass)
- App code CAN run when alarm fires (via PendingIntent)

### iOS

- Uses `BGTaskScheduler` for background prefetch
- Uses `UNUserNotificationCenter` for notification scheduling
- Limited to 64 pending notifications (OS constraint)
- Automatic background task management
- Battery optimization built-in
- Notifications persist across app termination and reboot (OS-guaranteed)
- App code does NOT run when notification fires (only if user taps)
- ±180 second timing tolerance for calendar-based notifications
- Background execution severely limited (BGTaskScheduler only, system-controlled)
- No user-facing "force stop" equivalent
- Must request notification permission before scheduling

### Key Differences Summary

| Feature | Android | iOS |
| ------- | ------- | --- |
| **Notification Persistence** | ❌ Must reschedule after reboot | ✅ Automatic (OS-guaranteed) |
| **Code Execution on Fire** | ✅ Yes (PendingIntent) | ❌ No (only if user taps) |
| **Background Execution** | ✅ WorkManager, JobScheduler | ⚠️ Limited (BGTaskScheduler) |
| **Timing Accuracy** | ✅ Exact (with permission) | ⚠️ ±180 seconds tolerance |
| **Force Stop** | ✅ User-facing option | ❌ No equivalent |
| **Boot Recovery** | ✅ Must implement | ✅ Automatic (notifications persist) |
| **Permission Model** | ✅ Runtime permission | ✅ Runtime permission |
| **Pending Limit** | ✅ No limit | ❌ 64 notifications max |

### Electron

- Desktop notification support
- SQLite or LocalStorage fallback
- Native desktop notification APIs
- Cross-platform desktop compatibility

## TimeSafari-Specific Integration Examples

### Basic TimeSafari Integration

```typescript
import { DailyNotification } from '@timesafari/daily-notification-plugin';
import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin';

// Initialize TimeSafari integration
const integrationService = TimeSafariIntegrationService.getInstance();

// Configure with TimeSafari-specific settings
await integrationService.initialize({
  activeDid: 'did:example:timesafari-user-123',
  storageAdapter: timeSafariStorageAdapter,
  endorserApiBaseUrl: 'https://endorser.ch/api/v1'
});

// Schedule TimeSafari community notifications
await DailyNotification.scheduleDailyNotification({
  title: 'New Community Update',
  body: 'You have new offers and project updates',
  time: '09:00',
  channel: 'timesafari_community_updates'
});
```

### TimeSafari Community Features

```typescript
// Fetch community data with rate limiting
const communityService = new TimeSafariCommunityIntegrationService();

await communityService.initialize({
  maxRequestsPerMinute: 30,
  maxRequestsPerHour: 1000,
  basePollingIntervalMs: 300000, // 5 minutes
  adaptivePolling: true
});

// Fetch community data
const bundle = await communityService.fetchCommunityDataWithRateLimit({
  activeDid: 'did:example:timesafari-user-123',
  fetchOffersToPerson: true,
  fetchOffersToProjects: true,
  fetchProjectUpdates: true,
  starredPlanIds: ['plan-1', 'plan-2', 'plan-3']
});
```

### DID-Signed Payloads

```typescript
// Generate DID-signed notification payloads
const samplePayloads = integrationService.generateSampleDidPayloads();

for (const payload of samplePayloads) {
  // Verify signature
  const isValid = await integrationService.verifyDidSignature(
    JSON.stringify(payload.payload),
    payload.signature
  );
  
  console.log(`Payload ${payload.type} signature valid: ${isValid}`);
}
```

### Privacy-Preserving Storage

```typescript
// Configure privacy-preserving storage
const storageAdapter = new TimeSafariStorageAdapterImpl(
  nativeStorage, 
  'timesafari_notifications'
);

// Store with TTL and redaction
await storageAdapter.store('community_data', bundle, 3600); // 1 hour TTL

// Get data retention policy
const policy = integrationService.getDataRetentionPolicy();
console.log('Data retention policy:', policy);
```
