import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
import * as Constants from 'expo-constants';
import { Platform } from 'react-native';
import api from './api';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowBanner: true,
    shouldShowList: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

let _cachedToken: string | null = null;

export async function registerForPushNotifications() {
  if (!Device.isDevice) {
    console.log('Push notifications require a physical device');
    return null;
  }

  const { status: existingStatus } = await Notifications.getPermissionsAsync();
  let finalStatus = existingStatus;

  if (existingStatus !== 'granted') {
    const { status } = await Notifications.requestPermissionsAsync();
    finalStatus = status;
  }

  if (finalStatus !== 'granted') {
    console.log('Failed to get push token for push notification');
    return null;
  }

  if (Platform.OS === 'android') {
    await Notifications.setNotificationChannelAsync('default', {
      name: 'default',
      importance: Notifications.AndroidImportance.MAX,
      vibrationPattern: [0, 250, 250, 250],
      lightColor: '#007AFF',
    });
  }

  try {
    const projectId =
      Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;

    const token = await Notifications.getExpoPushTokenAsync({
      projectId,
    });

    _cachedToken = token.data;

    // Register token with backend (fire and forget)
    registerTokenWithBackend(token.data).catch(() => {});

    return token.data;
  } catch (e) {
    console.log('Error getting push token:', e);
    return null;
  }
}

async function registerTokenWithBackend(token: string) {
  try {
    await api.post('/notifications/expo-register', { token });
  } catch (e) {
    console.log('Failed to register push token with backend:', e);
  }
}

export async function subscribeToMedicine(
  medicineNregistro: string,
  medicineName: string | null,
  pharmacyId?: number | null
) {
  const token = _cachedToken;
  if (!token) {
    console.log('No push token available for subscription');
    return;
  }
  try {
    await api.post('/notifications/expo-register', {
      token,
      medicine_nregistro: medicineNregistro,
      medicine_name: medicineName,
      pharmacy_id: pharmacyId || null,
    });
  } catch (e) {
    console.log('Failed to subscribe to medicine notifications:', e);
  }
}

export async function unsubscribeFromMedicine(
  medicineNregistro: string,
  pharmacyId?: number | null
) {
  try {
    await api.delete('/notifications/expo-unregister', {
      data: {
        medicine_nregistro: medicineNregistro,
        pharmacy_id: pharmacyId || null,
      },
    });
  } catch (e) {
    console.log('Failed to unsubscribe from medicine notifications:', e);
  }
}

export async function scheduleMedicineAvailabilityNotification(
  medicineName: string,
  pharmacyName: string
) {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: 'Medicamento disponible',
      body: `${medicineName} está disponible en ${pharmacyName}`,
      data: { type: 'medicine_availability' },
    },
    trigger: null,
  });
}

export function addNotificationListener(
  handler: (notification: Notifications.Notification) => void
): Notifications.EventSubscription {
  return Notifications.addNotificationReceivedListener(handler);
}

export function addNotificationResponseListener(
  handler: (response: Notifications.NotificationResponse) => void
): Notifications.EventSubscription {
  return Notifications.addNotificationResponseReceivedListener(handler);
}
