/**
 * Fogbreak Push Notification Service
 * Handles registration, permissions, and notification routing.
 * Critical events: new leads, showing requests, document signed, task overdue.
 */

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

export type NotificationType =
  | 'new_lead'
  | 'showing_requested'
  | 'showing_confirmed'
  | 'showing_cancelled'
  | 'document_signed'
  | 'task_overdue'
  | 'coaching_nudge'
  | 'property_match'
  | 'email_received'
  | 'deal_update';

export interface FogbreakNotification {
  type: NotificationType;
  title: string;
  body: string;
  data: Record<string, unknown>;
}

// Configure notification behavior
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

// Notification action categories for interactive notifications
export async function setupNotificationCategories(): Promise<void> {
  await Notifications.setNotificationCategoryAsync('showing_request', [
    {
      identifier: 'approve',
      buttonTitle: 'Approve',
      options: { opensAppToForeground: false },
    },
    {
      identifier: 'decline',
      buttonTitle: 'Decline',
      options: { opensAppToForeground: false, isDestructive: true },
    },
  ]);

  await Notifications.setNotificationCategoryAsync('task_reminder', [
    {
      identifier: 'complete',
      buttonTitle: 'Mark Complete',
      options: { opensAppToForeground: false },
    },
    {
      identifier: 'snooze',
      buttonTitle: 'Snooze 1hr',
      options: { opensAppToForeground: false },
    },
  ]);
}

export async function requestPermissions(): Promise<boolean> {
  if (!Device.isDevice) {
    console.warn('Push notifications require a physical device');
    return false;
  }

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

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

  if (finalStatus !== 'granted') {
    return false;
  }

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

    await Notifications.setNotificationChannelAsync('showings', {
      name: 'Showings',
      importance: Notifications.AndroidImportance.MAX,
      vibrationPattern: [0, 500, 250, 500],
      lightColor: '#1A3347',
    });

    await Notifications.setNotificationChannelAsync('leads', {
      name: 'New Leads',
      importance: Notifications.AndroidImportance.MAX,
      sound: 'default',
    });
  }

  return true;
}

export async function registerForPushNotifications(): Promise<string | null> {
  const permitted = await requestPermissions();
  if (!permitted) return null;

  try {
    const tokenData = await Notifications.getExpoPushTokenAsync({
      projectId: 'fogbreak',
    });
    const token = tokenData.data;

    await registerPushToken(token, Platform.OS);

    return token;
  } catch (err) {
    console.error('Failed to register push token:', err);
    return null;
  }
}

export type NotificationListener = (notification: Notifications.Notification) => void;
export type ResponseListener = (response: Notifications.NotificationResponse) => void;

export function addNotificationReceivedListener(
  callback: NotificationListener
): Notifications.EventSubscription {
  return Notifications.addNotificationReceivedListener(callback);
}

export function addNotificationResponseListener(
  callback: ResponseListener
): Notifications.EventSubscription {
  return Notifications.addNotificationResponseReceivedListener(callback);
}

export function parseNotificationData(
  notification: Notifications.Notification
): FogbreakNotification | null {
  const data = notification.request.content.data;
  if (!data?.type) return null;

  return {
    type: data.type as NotificationType,
    title: notification.request.content.title ?? '',
    body: notification.request.content.body ?? '',
    data: data as Record<string, unknown>,
  };
}

export function getNavigationRoute(type: NotificationType, data: Record<string, unknown>): {
  screen: string;
  params: Record<string, unknown>;
} {
  switch (type) {
    case 'new_lead':
      return { screen: 'ClientDetail', params: { id: data.client_id } };
    case 'showing_requested':
    case 'showing_confirmed':
    case 'showing_cancelled':
      return { screen: 'ShowingDetail', params: { id: data.showing_id } };
    case 'document_signed':
      return { screen: 'DocList', params: { deal_id: data.deal_id } };
    case 'task_overdue':
      return { screen: 'DealDetail', params: { id: data.deal_id } };
    case 'coaching_nudge':
      return { screen: 'MyGoals', params: {} };
    case 'property_match':
      return { screen: 'PropertyMatch', params: { client_id: data.client_id } };
    case 'email_received':
      return { screen: 'Inbox', params: { thread_id: data.thread_id } };
    case 'deal_update':
      return { screen: 'DealDetail', params: { id: data.deal_id } };
    default:
      return { screen: 'Dashboard', params: {} };
  }
}

export async function getBadgeCount(): Promise<number> {
  return Notifications.getBadgeCountAsync();
}

export async function setBadgeCount(count: number): Promise<void> {
  await Notifications.setBadgeCountAsync(count);
}

export async function clearAllNotifications(): Promise<void> {
  await Notifications.dismissAllNotificationsAsync();
  await setBadgeCount(0);
}
