import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';
import {
  getReminderLeadMinutes,
  getRemindersEnabled,
} from '@/features/notifications/reminderPrefs';

/**
 * Session-expiry reminders are purely LOCAL scheduled notifications: the app knows
 * the session's end time, so it schedules the reminder on-device via AlarmManager.
 * No server, no FCM, no push, no Play Services — works fully offline on GrapheneOS.
 */

const CHANNEL_ID = 'session-reminders';

/** Android 8+ needs a notification channel; ensure it exists once. */
async function ensureChannel(): Promise<void> {
  if (Platform.OS !== 'android') return;
  await Notifications.setNotificationChannelAsync(CHANNEL_ID, {
    name: 'Parking reminders',
    importance: Notifications.AndroidImportance.HIGH,
    sound: 'default',
    vibrationPattern: [0, 250, 250, 250],
  });
}

export async function ensureNotificationPermission(): Promise<boolean> {
  await ensureChannel();
  const settings = await Notifications.getPermissionsAsync();
  if (settings.granted) return true;
  const req = await Notifications.requestPermissionsAsync();
  return req.granted;
}

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    // shouldShowAlert is the legacy field; Banner/List are the newer split.
    shouldShowAlert: true,
    shouldShowBanner: true,
    shouldShowList: true,
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
});

export interface ScheduleReminderArgs {
  transactionId: string | number;
  zoneName: string;
  /** When the parking session ends. */
  endTime: Date;
  /** Override the user's configured lead time (minutes before end). */
  leadMinutes?: number;
}

/**
 * Schedule an expiry reminder using the user's Notifications preferences
 * (lead time + enabled). Returns the notification id, or null if disabled/late.
 */
export async function scheduleExpiryReminder(
  args: ScheduleReminderArgs,
): Promise<string | null> {
  if (!(await getRemindersEnabled())) return null;
  const leadMinutes = args.leadMinutes ?? (await getReminderLeadMinutes());
  const lead = leadMinutes * 60 * 1000;
  const fireAt = new Date(args.endTime.getTime() - lead);
  if (fireAt.getTime() <= Date.now()) return null; // already too late

  await ensureChannel();
  return Notifications.scheduleNotificationAsync({
    identifier: `session-${args.transactionId}`,
    content: {
      title: 'Parking expiring soon',
      body: `${args.zoneName} ends at ${args.endTime.toLocaleTimeString()}. Extend if you need more time.`,
      data: { transactionId: String(args.transactionId) },
    },
    trigger: {
      type: Notifications.SchedulableTriggerInputTypes.DATE,
      date: fireAt,
      channelId: CHANNEL_ID,
    },
  });
}

export async function cancelExpiryReminder(transactionId: string | number): Promise<void> {
  await Notifications.cancelScheduledNotificationAsync(`session-${transactionId}`);
}

/** Fire a test reminder a few seconds out — lets you confirm reminders work on-device. */
export async function sendTestReminder(seconds = 10): Promise<boolean> {
  if (!(await ensureNotificationPermission())) return false;
  await Notifications.scheduleNotificationAsync({
    content: {
      title: 'Test reminder',
      body: `This is what a parking-expiry reminder looks like (fired after ${seconds}s).`,
    },
    trigger: {
      type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL,
      seconds,
      channelId: CHANNEL_ID,
    },
  });
  return true;
}
