/**
 * Typed Plugin Wrapper
 * 
 * Type-safe wrapper for the DailyNotification plugin with validation
 * Provides schema validation and error handling at the JavaScript boundary
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 */

import { 
  type DailyNotificationBridge, 
  type ScheduleRequest, 
  type ScheduleResponse,
  type PermissionStatus,
  type NotificationStatus,
  type ExactAlarmStatus,
  type PermissionResult,
  type NotificationContent
} from './bridge'

import { validateScheduleRequest } from './schema-validation'
import { handlePluginError, logError } from './error-handling'

export class TypedDailyNotificationPlugin implements DailyNotificationBridge {
  private plugin: unknown

  constructor(plugin: unknown) {
    this.plugin = plugin
  }

  /**
   * Schedule daily notification with validation
   */
  async scheduleDailyNotification(request: ScheduleRequest): Promise<ScheduleResponse> {
    try {
      // Validate input schema
      const validation = validateScheduleRequest(request)
      if (!validation.isValid) {
        return {
          success: false,
          error: {
            code: 'E_BAD_CONFIG',
            message: validation.message,
            hint: 'Check input format and try again'
          }
        }
      }

      // Call native plugin
      const result = await (this.plugin as { scheduleDailyNotification: (req: ScheduleRequest) => Promise<ScheduleResponse> }).scheduleDailyNotification(request)
      
      // Validate response
      if (result && typeof result.success === 'boolean') {
        return result
      }

      // Handle unexpected response format
      return {
        success: true,
        scheduledAt: Date.now()
      }

    } catch (error) {
      logError(error, 'scheduleDailyNotification')
      return {
        success: false,
        error: handlePluginError(error, 'scheduleDailyNotification')
      }
    }
  }

  /**
   * Check permissions with validation
   * Uses checkPermissionStatus() which is the correct method name for iOS
   */
  async checkPermissions(): Promise<PermissionStatus> {
    try {
      // Use checkPermissionStatus() which is implemented on both iOS and Android
      const result = await (this.plugin as { checkPermissionStatus: () => Promise<any> }).checkPermissionStatus()
      
      // Map PermissionStatusResult to PermissionStatus format
      return {
        notifications: result.notificationsEnabled ? 'granted' : 'denied',
        notificationsEnabled: Boolean(result.notificationsEnabled),
        exactAlarmEnabled: Boolean(result.exactAlarmEnabled),
        wakeLockEnabled: Boolean(result.wakeLockEnabled),
        allPermissionsGranted: Boolean(result.allPermissionsGranted)
      }

    } catch (error) {
      logError(error, 'checkPermissions')
      return {
        notifications: 'denied',
        notificationsEnabled: false
      }
    }
  }

  /**
   * Get notification status with validation
   */
  async getNotificationStatus(): Promise<NotificationStatus> {
    try {
      const result = await (this.plugin as { getNotificationStatus: () => Promise<NotificationStatus> }).getNotificationStatus()
      
      // Ensure response has required fields
      return {
        isEnabled: Boolean(result.isEnabled),
        isScheduled: Boolean(result.isScheduled),
        lastNotificationTime: result.lastNotificationTime,
        nextNotificationTime: result.nextNotificationTime,
        pending: Boolean(result.pending),
        error: result.error
      }

    } catch (error) {
      logError(error, 'getNotificationStatus')
      return {
        isEnabled: false,
        isScheduled: false,
        pending: false,
        error: error.message
      }
    }
  }

  /**
   * Get exact alarm status with validation
   */
  async getExactAlarmStatus(): Promise<ExactAlarmStatus> {
    try {
      const result = await (this.plugin as { getExactAlarmStatus: () => Promise<ExactAlarmStatus> }).getExactAlarmStatus()
      
      // Ensure response has required fields
      return {
        enabled: Boolean(result.enabled),
        supported: Boolean(result.supported)
      }

    } catch (error) {
      logError(error, 'getExactAlarmStatus')
      return {
        enabled: false,
        supported: false
      }
    }
  }

  /**
   * Request permissions
   */
  async requestPermissions(): Promise<PermissionResult> {
    try {
      const result = await (this.plugin as { requestPermissions: () => Promise<PermissionStatus> }).requestPermissions()
      
      return {
        granted: result.notifications === 'granted',
        permissions: result
      }

    } catch (error) {
      logError(error, 'requestPermissions')
      return {
        granted: false,
        permissions: {
          notifications: 'denied',
          notificationsEnabled: false
        }
      }
    }
  }

  /**
   * Request notification permissions (iOS method name)
   * This is an alias for requestPermissions() for iOS compatibility
   */
  async requestNotificationPermissions(): Promise<void> {
    try {
      // Try requestNotificationPermissions first (iOS), fallback to requestPermissions
      if (typeof (this.plugin as any).requestNotificationPermissions === 'function') {
        await (this.plugin as { requestNotificationPermissions: () => Promise<void> }).requestNotificationPermissions()
      } else if (typeof (this.plugin as any).requestPermissions === 'function') {
        await (this.plugin as { requestPermissions: () => Promise<PermissionStatus> }).requestPermissions()
      } else {
        throw new Error('Neither requestNotificationPermissions nor requestPermissions is available')
      }
    } catch (error) {
      logError(error, 'requestNotificationPermissions')
      throw error
    }
  }

  /**
   * Open exact alarm settings
   */
  async openExactAlarmSettings(): Promise<void> {
    try {
      await (this.plugin as { openExactAlarmSettings: () => Promise<void> }).openExactAlarmSettings()
    } catch (error) {
      logError(error, 'openExactAlarmSettings')
      throw error
    }
  }

  /**
   * Open channel settings
   */
  async openChannelSettings(): Promise<void> {
    try {
      await (this.plugin as { openChannelSettings: () => Promise<void> }).openChannelSettings()
    } catch (error) {
      logError(error, 'openChannelSettings')
      throw error
    }
  }

  /**
   * Request battery optimization exemption
   */
  async requestBatteryOptimizationExemption(): Promise<void> {
    try {
      await (this.plugin as { requestBatteryOptimizationExemption: () => Promise<void> }).requestBatteryOptimizationExemption()
    } catch (error) {
      logError(error, 'requestBatteryOptimizationExemption')
      throw error
    }
  }

  /**
   * Cancel all notifications
   */
  async cancelAllNotifications(): Promise<void> {
    try {
      await (this.plugin as { cancelAllNotifications: () => Promise<void> }).cancelAllNotifications()
    } catch (error) {
      logError(error, 'cancelAllNotifications')
      throw error
    }
  }

  /**
   * Get last notification
   */
  async getLastNotification(): Promise<NotificationContent | null> {
    try {
      const result = await (this.plugin as { getLastNotification: () => Promise<NotificationContent | null> }).getLastNotification()
      return result || null
    } catch (error) {
      logError(error, 'getLastNotification')
      return null
    }
  }
}

/**
 * Create typed plugin instance
 */
export async function createTypedPlugin(): Promise<TypedDailyNotificationPlugin | null> {
  try {
    const { DailyNotification } = await import('@timesafari/daily-notification-plugin')
    
    if (!DailyNotification) {
      console.warn('DailyNotification plugin not available')
      return null
    }

    return new TypedDailyNotificationPlugin(DailyNotification)
  } catch (error) {
    logError(error, 'createTypedPlugin')
    return null
  }
}

// Export types for use in components
export type { 
  ScheduleRequest, 
  ScheduleResponse,
  PermissionStatus,
  NotificationStatus,
  ExactAlarmStatus,
  PermissionResult,
  NotificationContent
} from './bridge'
