import * as Notifications from 'expo-notifications';
import React from 'react';
import type { WidgetTaskHandlerProps } from 'react-native-android-widget';
import { Category, CategoryQuery } from '../../models/category';
import { Task, TaskQuery } from '../../models/task';
import { CategoryRepository } from '../../repositories/CategoryRepository';
import { TaskRepository } from '../../repositories/TaskRepository';
import { SQLiteDataService } from '../../services/data/sqliteDataService';
import { HelloWidget } from './hello';


const taskRepository = new TaskRepository(new SQLiteDataService<Task>(TaskQuery));
const categoryRepository = new CategoryRepository(new SQLiteDataService<Category>(CategoryQuery));

let tasks: Task[] = [];
let categories: Category[] = [];

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

let notify_channels: Notifications.NotificationChannel[] = [];
let notify_notification: Notifications.Notification | undefined = undefined;
let notify_listener: Notifications.EventSubscription | null = null;
let notify_responseListener: Notifications.EventSubscription | null = null;

Notifications.getNotificationChannelsAsync().then((channels) => {
    if (channels.length === 0) {
        Notifications.setNotificationChannelAsync('default', {
            name: 'Default Channel',
            importance: Notifications.AndroidImportance.HIGH,
            sound: 'default',
            vibrationPattern: [0, 250, 250, 250],
        }).then((channel) => {
            if (channel) notify_channels = [channel];
        });
    }
    notify_channels = channels;
});

notify_listener = Notifications.addNotificationReceivedListener(notification => {
    notify_notification = notification;
});

notify_responseListener = Notifications.addNotificationResponseReceivedListener(response => { });

const CheckTaskAndNotify = async (): Promise<{ tasks: Task[], categories: Category[] }> => {
    tasks = await taskRepository.findAll();
    categories = await categoryRepository.findAll();

    const expiredTasks = tasks.filter(task => {
        const expirationDate = task.lastDone! + (task.daysToRedo! * 24 * 60 * 60 * 1000); // Convert days to milliseconds
        return expirationDate < Date.now();
    });

    if (expiredTasks.length > 0) {
        for (const task of expiredTasks) {
            const category = categories.find(cat => cat.id === task.category);
            await Notifications.scheduleNotificationAsync({
                identifier: `task-due-${task.id}`,
                content: {
                    title: 'Task Reminder',
                    body: `${category?.icon} "${task.title}" is due! ⌛`,
                    data: { taskId: task.id },
                },
                trigger: null
            });
        }
    }

    return { tasks, categories };
}

setInterval(async () => {
    CheckTaskAndNotify();
}, 1000 * 60 * 30); // Check every 30 minutes


export async function widgetTaskHandler(props: WidgetTaskHandlerProps) {

    async function updateAndRenderWidget() {
        const { tasks, categories } = await CheckTaskAndNotify();

        props.renderWidget(<HelloWidget tasks={tasks} categories={categories} />);
    }

    switch (props.widgetAction) {
        case 'WIDGET_ADDED':
        case 'WIDGET_UPDATE':
        case 'WIDGET_RESIZED':
            // Not needed for now
            updateAndRenderWidget();
            break;

        case 'WIDGET_DELETED':
            // Not needed for now
            break;

        case 'WIDGET_CLICK':
            switch (props.clickAction) {
                case 'REFRESH':
                    await updateAndRenderWidget();
                    break;
                case 'UPDATE_TASK':
                    if (props.clickActionData && props.clickActionData.id) {
                        const taskId = props.clickActionData.id;
                        const task = await taskRepository.findById(parseInt(taskId.toString()));
                        if (task) {
                            task.lastDone = Math.floor(Date.now() / 1000 / 60 / 60 / 24); // Set last done to today
                            await taskRepository.update(parseInt(taskId.toString()), { ...task, lastDone: new Date().getTime() });
                            await updateAndRenderWidget();
                        }
                    }
                    break;

                default:
                    break;
            }
    }
}