/**
 * useNotifications Hook
 *
 * Hook for managing push notifications in the app
 */

import { useEffect, useRef, useCallback } from 'react';
import { AppState, AppStateStatus } from 'react-native';
import * as Notifications from 'expo-notifications';
import {
  useNotificationStore,
  notificationService,
  generateNotificationId,
  PushNotification,
} from '@/services/notifications';

interface UseNotificationsOptions {
  onNotificationReceived?: (notification: PushNotification) => void;
  onNotificationTapped?: (notification: PushNotification, actionId?: string) => void;
}

interface UseNotificationsResult {
  // State
  pushToken: string | null;
  isPermissionGranted: boolean;
  canAskPermission: boolean;
  notifications: PushNotification[];
  unreadCount: number;

  // Actions
  requestPermission: () => Promise<boolean>;
  scheduleNotification: (
    title: string,
    body: string,
    options?: {
      data?: Record<string, any>;
      delaySeconds?: number;
      channelId?: string;
    }
  ) => Promise<string>;
  cancelNotification: (id: string) => Promise<void>;
  cancelAllNotifications: () => Promise<void>;
  markAsRead: (id: string) => void;
  markAllAsRead: () => void;
  removeNotification: (id: string) => void;
  clearAll: () => void;
  setBadge: (count: number) => Promise<void>;
}

export function useNotifications(
  options: UseNotificationsOptions = {}
): UseNotificationsResult {
  const { onNotificationReceived, onNotificationTapped } = options;

  const {
    pushToken,
    permissions,
    notifications,
    unreadCount,
    addNotification,
    markAsRead,
    markAllAsRead,
    removeNotification,
    clearAll,
  } = useNotificationStore();

  const notificationReceivedRef = useRef<Notifications.Subscription>();
  const notificationResponseRef = useRef<Notifications.Subscription>();
  const appStateRef = useRef<AppStateStatus>(AppState.currentState);

  // Request notification permission
  const requestPermission = useCallback(async (): Promise<boolean> => {
    const token = await notificationService.register();
    return token !== null;
  }, []);

  // Schedule a local notification
  const scheduleNotification = useCallback(
    async (
      title: string,
      body: string,
      opts?: {
        data?: Record<string, any>;
        delaySeconds?: number;
        channelId?: string;
      }
    ): Promise<string> => {
      const trigger = opts?.delaySeconds
        ? { seconds: opts.delaySeconds }
        : null;

      return await notificationService.scheduleLocal(title, body, {
        data: opts?.data,
        trigger,
        channelId: opts?.channelId,
      });
    },
    []
  );

  // Cancel a scheduled notification
  const cancelNotification = useCallback(async (id: string): Promise<void> => {
    await notificationService.cancelScheduled(id);
  }, []);

  // Cancel all scheduled notifications
  const cancelAllNotifications = useCallback(async (): Promise<void> => {
    await notificationService.cancelAllScheduled();
  }, []);

  // Set badge count
  const setBadge = useCallback(async (count: number): Promise<void> => {
    await notificationService.setBadgeCount(count);
  }, []);

  // Handle notification received
  const handleNotificationReceived = useCallback(
    (notification: Notifications.Notification) => {
      const { title, body, data } = notification.request.content;

      const pushNotification: PushNotification = {
        id: generateNotificationId(),
        title: title || '',
        body: body || '',
        data: data as Record<string, any>,
        receivedAt: Date.now(),
        read: false,
      };

      addNotification(pushNotification);
      onNotificationReceived?.(pushNotification);
    },
    [addNotification, onNotificationReceived]
  );

  // Handle notification tapped
  const handleNotificationResponse = useCallback(
    (response: Notifications.NotificationResponse) => {
      const { title, body, data } = response.notification.request.content;
      const actionId = response.actionIdentifier;

      const pushNotification: PushNotification = {
        id: generateNotificationId(),
        title: title || '',
        body: body || '',
        data: data as Record<string, any>,
        receivedAt: Date.now(),
        read: true,
      };

      onNotificationTapped?.(
        pushNotification,
        actionId !== Notifications.DEFAULT_ACTION_IDENTIFIER ? actionId : undefined
      );
    },
    [onNotificationTapped]
  );

  // Setup notification listeners
  useEffect(() => {
    // Register on mount if permission was already granted
    if (permissions.granted) {
      notificationService.register();
    }

    // Notification received listener
    notificationReceivedRef.current = notificationService.addNotificationReceivedListener(
      handleNotificationReceived
    );

    // Notification response listener
    notificationResponseRef.current = notificationService.addNotificationResponseListener(
      handleNotificationResponse
    );

    // Check for notification that launched the app
    notificationService.getLastResponse().then((response) => {
      if (response) {
        handleNotificationResponse(response);
      }
    });

    // Cleanup
    return () => {
      notificationReceivedRef.current?.remove();
      notificationResponseRef.current?.remove();
    };
  }, [handleNotificationReceived, handleNotificationResponse, permissions.granted]);

  // Update badge on app state change
  useEffect(() => {
    const subscription = AppState.addEventListener('change', (nextAppState) => {
      if (
        appStateRef.current.match(/inactive|background/) &&
        nextAppState === 'active'
      ) {
        // App came to foreground - update badge
        notificationService.setBadgeCount(unreadCount);
      }
      appStateRef.current = nextAppState;
    });

    return () => subscription.remove();
  }, [unreadCount]);

  // Keep badge in sync
  useEffect(() => {
    notificationService.setBadgeCount(unreadCount);
  }, [unreadCount]);

  return {
    // State
    pushToken,
    isPermissionGranted: permissions.granted,
    canAskPermission: permissions.canAskAgain,
    notifications,
    unreadCount,

    // Actions
    requestPermission,
    scheduleNotification,
    cancelNotification,
    cancelAllNotifications,
    markAsRead,
    markAllAsRead,
    removeNotification,
    clearAll,
    setBadge,
  };
}
