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

// Define the structure of the push token data expected by the backend
interface PushTokenData {
    token: string;
    device_name?: string;
    token_type: 'expo'; // Indicate the type of token
}

// --- Android Notification Channel Setup ---
async function setupNotificationChannelsAndroid() {
    if (Platform.OS === 'android') {
        await Notifications.setNotificationChannelAsync('default', {
            name: 'Default',
            importance: Notifications.AndroidImportance.MAX,
            vibrationPattern: [0, 250, 250, 250],
            lightColor: '#FF231F7C',
        });
        console.log('[Notifications] Default Android channel set up.');
    }
}

// --- Request Permissions and Get Token ---
export async function registerForPushNotificationsAsync(): Promise<string | null> {
    if (Platform.OS !== 'android' && Platform.OS !== 'ios') {
        console.warn('[Notifications] Push notifications are only supported on Android and iOS.');
        return null;
    }
    let token: string | null = null;

    if (!Device.isDevice) {
        console.warn('[Notifications] Push notifications require a physical device.');
        alert('Must use physical device for Push Notifications');
        return null;
    }

    // 1. Setup Android Channels
    await setupNotificationChannelsAndroid();

    // 2. Request Permissions
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    if (existingStatus !== 'granted') {
        console.log('[Notifications] Requesting notification permissions...');
        const { status } = await Notifications.requestPermissionsAsync();
        finalStatus = status;
    }

    if (finalStatus !== 'granted') {
        console.warn('[Notifications] Failed to get push token: Permission not granted.');
        alert('Failed to get push token for push notification!');
        return null;
    }

    // 3. Get Expo Push Token
    try {
        // Use the default experience ID
        const projectId = process.env.EXPO_PROJECT_ID || Constants.expoConfig?.extra?.eas?.projectId;
        if (!projectId) {
            console.error('[Notifications] EAS project ID not found in app config. Cannot get push token.');
            alert('Configuration error: Project ID missing. Cannot get push token.');
            return null;
        }
        console.log(`[Notifications] Getting Expo push token with projectId: ${projectId}`);
        const expoPushToken = await Notifications.getExpoPushTokenAsync({ projectId });
        token = expoPushToken.data;
        console.log('[Notifications] Received Expo Push Token:', token);
    } catch (error) {
        console.error('[Notifications] Error getting Expo push token:', error);
        alert(`Error getting push token: ${error instanceof Error ? error.message : String(error)}`);
        return null;
    }

    return token;
}

// --- Send Token to Backend ---
export async function sendPushTokenToBackend(expoPushToken: string): Promise<boolean> {
    if (!expoPushToken) {
        console.warn('[Notifications] No push token provided to send to backend.');
        return false;
    }

    const tokenData: PushTokenData = {
        token: expoPushToken,
        device_name: Device.deviceName ?? undefined,
        token_type: 'expo',
    };

    try {
        console.log('[Notifications] Sending push token to backend:', tokenData);
        const response = await apiClient.post('/user/push-token', tokenData);

        if (response.status === 200 || response.status === 201) {
            console.log('[Notifications] Push token successfully sent to backend.');
            return true;
        } else {
            console.warn(`[Notifications] Backend returned status ${response.status} when sending push token.`);
            return false;
        }
    } catch (error: any) {
        console.error('[Notifications] Error sending push token to backend:', error.response?.data || error.message);
        return false;
    }
}

// --- Notification Handling Setup ---
export function setupNotificationHandlers() {
    // Handle notifications that arrive while the app is foregrounded
    Notifications.setNotificationHandler({
        handleNotification: async () => ({
            shouldShowAlert: true,
            shouldPlaySound: true,
            shouldSetBadge: false,
        }),
    });

    // Handle user interaction with notifications (tapping) when app is foregrounded/backgrounded
    const foregroundInteractionSubscription = Notifications.addNotificationResponseReceivedListener(response => {
        console.log('[Notifications] User interacted with notification (foreground/background):', response.notification.request.content);
        
        // const data = response.notification.request.content.data;
        // if (data?.screen) {
        //   navigation.navigate(data.screen);
        // }
    });

    // Handle user interaction with notifications (tapping) when app was killed/not running
    // This requires careful setup, potentially using Linking or initial URL handling
    // Notifications.getLastNotificationResponseAsync().then(response => {
    //   if (response) {
    //      console.log('[Notifications] User opened app via notification (killed state):', response.notification.request.content);
    //      // Handle navigation or action based on response.notification.request.content.data
    //   }
    // });


    console.log('[Notifications] Notification handlers set up.');

    // Return cleanup function for useEffect
    return () => {
        console.log('[Notifications] Removing notification listeners.');
        Notifications.removeNotificationSubscription(foregroundInteractionSubscription);
    };
}
