/**
 * Core Error Codes and Error Types
 * 
 * Canonical error codes shared across all platforms (Android, iOS, Web).
 * These codes must match native implementations exactly.
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 */

/**
 * Error code enum - stable identifiers for all error conditions
 * 
 * These codes are append-only. Never repurpose existing values.
 * New codes must be added at the end of their category.
 */
export enum ErrorCode {
  // Permission Errors
  NOTIFICATIONS_DENIED = 'notifications_denied',
  BACKGROUND_REFRESH_DISABLED = 'background_refresh_disabled',
  PERMISSION_DENIED = 'permission_denied',
  NOTIFICATION_PERMISSION_DENIED = 'notification_permission_denied',
  
  // Configuration Errors
  INVALID_TIME_FORMAT = 'invalid_time_format',
  INVALID_TIME_VALUES = 'invalid_time_values',
  CONFIGURATION_FAILED = 'configuration_failed',
  MISSING_REQUIRED_PARAMETER = 'missing_required_parameter',
  
  // Scheduling Errors
  SCHEDULING_FAILED = 'scheduling_failed',
  TASK_SCHEDULING_FAILED = 'task_scheduling_failed',
  NOTIFICATION_SCHEDULING_FAILED = 'notification_scheduling_failed',
  PENDING_NOTIFICATION_LIMIT_EXCEEDED = 'pending_notification_limit_exceeded',
  
  // Storage Errors
  STORAGE_ERROR = 'storage_error',
  DATABASE_ERROR = 'database_error',
  
  // Network Errors
  NETWORK_ERROR = 'network_error',
  FETCH_FAILED = 'fetch_failed',
  TIMEOUT = 'timeout',
  
  // Background Task Errors (iOS-specific but cross-platform compatible)
  BG_TASK_NOT_REGISTERED = 'bg_task_not_registered',
  BG_TASK_EXECUTION_FAILED = 'bg_task_execution_failed',
  
  // System Errors
  PLUGIN_NOT_INITIALIZED = 'plugin_not_initialized',
  INTERNAL_ERROR = 'internal_error',
  SYSTEM_ERROR = 'system_error',
  
  // Platform Errors
  NOT_SUPPORTED = 'not_supported',
}

/**
 * Error code metadata with actionable guidance
 * 
 * Provides human-readable messages and actionable guidance for each error code.
 * Platform-specific hints help developers resolve issues quickly.
 */
export const ERROR_GUIDANCE: Record<ErrorCode, { 
  message: string; 
  guidance: string; 
  platformHints?: Record<string, string> 
}> = {
  [ErrorCode.NOTIFICATIONS_DENIED]: {
    message: 'Notification permission denied',
    guidance: 'Request permission using requestPermission() before scheduling notifications',
    platformHints: {
      ios: 'Check Info.plist for notification permission description',
      android: 'Check AndroidManifest.xml for POST_NOTIFICATIONS permission'
    }
  },
  [ErrorCode.BACKGROUND_REFRESH_DISABLED]: {
    message: 'Background refresh is disabled',
    guidance: 'Enable background app refresh in device settings',
    platformHints: {
      ios: 'Settings > General > Background App Refresh',
      android: 'Settings > Apps > Battery optimization'
    }
  },
  [ErrorCode.PERMISSION_DENIED]: {
    message: 'Permission denied',
    guidance: 'Request permission before performing this operation'
  },
  [ErrorCode.NOTIFICATION_PERMISSION_DENIED]: {
    message: 'Notification permission denied',
    guidance: 'Request notification permission using requestPermission()'
  },
  [ErrorCode.INVALID_TIME_FORMAT]: {
    message: 'Invalid time format',
    guidance: 'Use HH:mm format (e.g., "09:30" for 9:30 AM)'
  },
  [ErrorCode.INVALID_TIME_VALUES]: {
    message: 'Invalid time values',
    guidance: 'Ensure hours are 0-23 and minutes are 0-59'
  },
  [ErrorCode.CONFIGURATION_FAILED]: {
    message: 'Configuration failed',
    guidance: 'Check configuration parameters and platform-specific requirements'
  },
  [ErrorCode.MISSING_REQUIRED_PARAMETER]: {
    message: 'Missing required parameter',
    guidance: 'Provide all required parameters for this operation'
  },
  [ErrorCode.SCHEDULING_FAILED]: {
    message: 'Scheduling failed',
    guidance: 'Check schedule parameters and platform permissions'
  },
  [ErrorCode.TASK_SCHEDULING_FAILED]: {
    message: 'Background task scheduling failed',
    guidance: 'Ensure background tasks are properly registered and permissions granted'
  },
  [ErrorCode.NOTIFICATION_SCHEDULING_FAILED]: {
    message: 'Notification scheduling failed',
    guidance: 'Check notification permissions and platform limits'
  },
  [ErrorCode.PENDING_NOTIFICATION_LIMIT_EXCEEDED]: {
    message: 'Pending notification limit exceeded',
    guidance: 'Reduce number of scheduled notifications or clear old ones'
  },
  [ErrorCode.STORAGE_ERROR]: {
    message: 'Storage error',
    guidance: 'Check storage permissions and available space'
  },
  [ErrorCode.DATABASE_ERROR]: {
    message: 'Database error',
    guidance: 'Check database integrity and migration status'
  },
  [ErrorCode.NETWORK_ERROR]: {
    message: 'Network error',
    guidance: 'Check network connectivity and retry'
  },
  [ErrorCode.FETCH_FAILED]: {
    message: 'Fetch operation failed',
    guidance: 'Check network connectivity and API endpoint availability'
  },
  [ErrorCode.TIMEOUT]: {
    message: 'Operation timed out',
    guidance: 'Retry operation or increase timeout value'
  },
  [ErrorCode.BG_TASK_NOT_REGISTERED]: {
    message: 'Background task not registered',
    guidance: 'Register background task using registerBackgroundTask()',
    platformHints: {
      ios: 'Register BGTaskScheduler tasks in AppDelegate',
      android: 'Register WorkManager tasks in Application class'
    }
  },
  [ErrorCode.BG_TASK_EXECUTION_FAILED]: {
    message: 'Background task execution failed',
    guidance: 'Check background task implementation and platform constraints'
  },
  [ErrorCode.PLUGIN_NOT_INITIALIZED]: {
    message: 'Plugin not initialized',
    guidance: 'Call configure() before using plugin methods'
  },
  [ErrorCode.INTERNAL_ERROR]: {
    message: 'Internal error',
    guidance: 'Check logs for details and report issue if persistent'
  },
  [ErrorCode.SYSTEM_ERROR]: {
    message: 'System error',
    guidance: 'Check system logs and platform-specific error details'
  },
  [ErrorCode.NOT_SUPPORTED]: {
    message: 'Operation not supported',
    guidance: 'This operation is not supported on this platform',
    platformHints: {
      web: 'Use native iOS or Android implementation for this feature'
    }
  },
};

/**
 * Error response shape for cross-platform error handling
 * 
 * Matches the format expected by Capacitor bridge:
 * {
 *   "error": "error_code",
 *   "message": "Human-readable error message"
 * }
 */
export interface ErrorResponse {
  /** Error code (from ErrorCode enum) */
  error: string;
  /** Human-readable error message */
  message: string;
  /** Optional additional context */
  details?: Record<string, unknown>;
}

/**
 * Daily Notification Error class
 * 
 * Structured error for plugin operations with error code and message
 */
export class DailyNotificationError extends Error {
  public readonly code: ErrorCode;
  public readonly details?: Record<string, unknown>;
  
  constructor(
    code: ErrorCode,
    message: string,
    details?: Record<string, unknown>
  ) {
    super(message);
    this.name = 'DailyNotificationError';
    this.code = code;
    this.details = details;
    
    // Maintains proper stack trace for where error was thrown
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, DailyNotificationError);
    }
  }
  
  /**
   * Convert to ErrorResponse format for bridge serialization
   */
  toResponse(): ErrorResponse {
    return {
      error: this.code,
      message: this.message,
      ...(this.details && { details: this.details }),
    };
  }
  
  /**
   * Convert error to JSON for structured logging
   * @returns JSON-serializable error representation
   */
  toJSON(): Record<string, unknown> {
    return {
      code: this.code,
      message: this.message,
      stack: this.stack,
      timestamp: Date.now(),
      ...(this.details && { details: this.details }),
    };
  }
  
  /**
   * Create error for missing required parameter
   */
  static missingParameter(parameter: string): DailyNotificationError {
    return new DailyNotificationError(
      ErrorCode.MISSING_REQUIRED_PARAMETER,
      `Missing required parameter: ${parameter}`,
      { parameter }
    );
  }
  
  /**
   * Create error for invalid time format
   */
  static invalidTimeFormat(): DailyNotificationError {
    return new DailyNotificationError(
      ErrorCode.INVALID_TIME_FORMAT,
      'Invalid time format. Use HH:mm'
    );
  }
  
  /**
   * Create error for invalid time values
   */
  static invalidTimeValues(): DailyNotificationError {
    return new DailyNotificationError(
      ErrorCode.INVALID_TIME_VALUES,
      'Invalid time values'
    );
  }
  
  /**
   * Create error for notifications denied
   */
  static notificationsDenied(): DailyNotificationError {
    return new DailyNotificationError(
      ErrorCode.NOTIFICATIONS_DENIED,
      'Notification permissions denied'
    );
  }
  
  /**
   * Create error for configuration failure
   */
  static configurationFailed(reason?: string): DailyNotificationError {
    return new DailyNotificationError(
      ErrorCode.CONFIGURATION_FAILED,
      reason ? `Configuration failed: ${reason}` : 'Configuration failed',
      reason ? { reason } : undefined
    );
  }
}

