/**
 * Native Notification Service
 *
 * Implementation of notification service using the DailyNotificationPlugin
 * for native iOS and Android platforms. Provides full native notification
 * capabilities including background delivery, exact alarm scheduling, and
 * offline operation.
 *
 * @author Matthew Raymer
 * @version 1.0.0
 * @since 2026-01-21
 */

import { DailyNotification } from "@/plugins/DailyNotificationPlugin";

/**
 * Extended type for DailyNotification that includes the actual Swift implementation
 * signature for cancelDailyReminder (which expects an object, not a string)
 */
interface DailyNotificationWithObjectCancel {
  cancelDailyReminder(options: { reminderId: string }): Promise<void>;
}
import type {
  NotificationServiceInterface,
  DailyNotificationOptions,
  NotificationStatus,
  PermissionStatus,
} from "./NotificationService";
import { logger } from "@/utils/logger";

/**
 * Native notification implementation using DailyNotificationPlugin
 * Used for iOS and Android builds
 *
 * Features:
 * - Full background notification support
 * - Survives app restarts and device reboots
 * - Exact alarm scheduling (Android 12+)
 * - No network dependency for delivery
 * - Native OS notification UI
 */
export class NativeNotificationService implements NotificationServiceInterface {
  private readonly reminderId = "timesafari_daily_reminder";
  private readonly platformName = "native";

  /**
   * Native notifications are always supported on iOS/Android
   */
  isSupported(): boolean {
    return true;
  }

  /**
   * Request notification permissions from the OS
   * Shows native permission dialog on first call
   */
  async requestPermissions(): Promise<boolean> {
    try {
      logger.debug("[NativeNotificationService] Requesting permissions");

      // Use requestNotificationPermissions() which is the method exposed by iOS
      // For Android, this should also work via the plugin bridge
      const result = await DailyNotification.requestNotificationPermissions();

      logger.debug("[NativeNotificationService] Permission result:", result);

      // The result may be PermissionStatus (with granted boolean) or PermissionStatusResult
      // Handle both formats for compatibility
      if ("granted" in result && typeof result.granted === "boolean") {
        return result.granted;
      }
      if (
        "allPermissionsGranted" in result &&
        typeof result.allPermissionsGranted === "boolean"
      ) {
        return result.allPermissionsGranted;
      }
      // Fallback: check status after requesting
      const status = await DailyNotification.checkPermissionStatus();
      return status.allPermissionsGranted;
    } catch (error) {
      logger.error(
        "[NativeNotificationService] Permission request failed:",
        error,
      );
      return false;
    }
  }

  /**
   * Check current permission status without prompting
   */
  async checkPermissions(): Promise<PermissionStatus> {
    try {
      const status = await DailyNotification.checkPermissionStatus();

      return {
        granted: status.allPermissionsGranted,
        details: {
          notifications: status.notificationsEnabled,
          exactAlarm: status.exactAlarmEnabled,
          backgroundRefresh: true, // Native always has background capability
        },
      };
    } catch (error) {
      logger.error(
        "[NativeNotificationService] Permission check failed:",
        error,
      );
      return {
        granted: false,
        details: {
          notifications: false,
          exactAlarm: false,
          backgroundRefresh: false,
        },
      };
    }
  }

  /**
   * Schedule a daily notification using native alarms
   */
  async scheduleDailyNotification(
    options: DailyNotificationOptions,
  ): Promise<boolean> {
    try {
      logger.info(
        "[NativeNotificationService] Scheduling daily notification:",
        {
          time: options.time,
          title: options.title,
          body: options.body,
        },
      );

      // Cancel any existing notification with the same ID before scheduling a new one
      // This ensures the old notification is removed from iOS notification center
      try {
        logger.debug(
          "[NativeNotificationService] Canceling existing notification before rescheduling",
        );
        // The Swift plugin expects an object with reminderId property
        // Even though TypeScript definition says string, we need to pass an object
        await (
          DailyNotification as unknown as DailyNotificationWithObjectCancel
        ).cancelDailyReminder({
          reminderId: this.reminderId,
        });
      } catch (cancelError) {
        // Ignore errors if notification doesn't exist - that's fine
        logger.debug(
          "[NativeNotificationService] No existing notification to cancel (or cancel failed):",
          cancelError,
        );
      }

      await DailyNotification.scheduleDailyReminder({
        id: this.reminderId,
        title: options.title,
        body: options.body,
        time: options.time, // HH:mm format
        repeatDaily: true,
        sound: true,
        vibration: true,
        priority: options.priority || "normal",
      });

      // Verify the notification was actually scheduled
      logger.debug(
        "[NativeNotificationService] Verifying notification was scheduled",
      );
      const remindersResult = await DailyNotification.getScheduledReminders();
      // Handle both array and object with reminders property
      const reminders = Array.isArray(remindersResult)
        ? remindersResult
        : (remindersResult as { reminders: typeof remindersResult })
            .reminders || [];
      const scheduledReminder = reminders.find((r) => r.id === this.reminderId);

      if (scheduledReminder && scheduledReminder.isScheduled) {
        // Verify the time matches what we scheduled
        if (scheduledReminder.time !== options.time) {
          logger.error(
            "[NativeNotificationService] Notification time mismatch!",
            {
              scheduled: scheduledReminder.time,
              requested: options.time,
              reminderId: this.reminderId,
            },
          );
          return false;
        }

        logger.info(
          "[NativeNotificationService] Daily notification scheduled successfully:",
          {
            id: scheduledReminder.id,
            time: scheduledReminder.time,
            requestedTime: options.time,
            nextTriggerTime: scheduledReminder.nextTriggerTime,
          },
        );
        return true;
      } else {
        logger.warn(
          "[NativeNotificationService] Notification was not found in scheduled reminders after scheduling",
          {
            reminderId: this.reminderId,
            requestedTime: options.time,
            allReminders: reminders.map((r) => ({
              id: r.id,
              time: r.time,
              isScheduled: r.isScheduled,
            })),
          },
        );
        return false;
      }
    } catch (error) {
      logger.error("[NativeNotificationService] Schedule failed:", error);
      return false;
    }
  }

  /**
   * Cancel the daily notification
   */
  async cancelDailyNotification(): Promise<void> {
    try {
      logger.info("[NativeNotificationService] Cancelling daily notification");
      // The Swift plugin expects an object with reminderId property
      // Even though TypeScript definition says string, we need to pass an object
      await (
        DailyNotification as unknown as DailyNotificationWithObjectCancel
      ).cancelDailyReminder({
        reminderId: this.reminderId,
      });
      logger.info(
        "[NativeNotificationService] Daily notification cancelled successfully",
      );
    } catch (error) {
      logger.error("[NativeNotificationService] Cancel failed:", error);
      // Don't throw - cancellation failures are non-critical
    }
  }

  /**
   * Get current notification status from the plugin
   */
  async getStatus(): Promise<NotificationStatus> {
    try {
      const remindersResult = await DailyNotification.getScheduledReminders();
      // Handle both array and object with reminders property
      const reminders = Array.isArray(remindersResult)
        ? remindersResult
        : (remindersResult as { reminders: typeof remindersResult })
            .reminders || [];
      const reminder = reminders.find((r) => r.id === this.reminderId);

      if (reminder) {
        logger.debug("[NativeNotificationService] Found active reminder:", {
          time: reminder.time,
          isScheduled: reminder.isScheduled,
        });

        return {
          enabled: reminder.isScheduled,
          scheduledTime: reminder.time,
          message: reminder.body,
          notificationType: "native",
        };
      }

      logger.debug("[NativeNotificationService] No active reminder found");
      return {
        enabled: false,
        notificationType: "native",
      };
    } catch (error) {
      logger.error("[NativeNotificationService] Get status failed:", error);
      return {
        enabled: false,
        notificationType: "native",
      };
    }
  }

  /**
   * Get platform identifier
   */
  getPlatformName(): string {
    return this.platformName;
  }
}
