/**
 * DailyReminderManager.java
 *
 * Manages daily reminder functionality including creation, updates,
 * cancellation, and retrieval. Handles persistent storage and
 * notification scheduling.
 *
 * @author Matthew Raymer
 * @version 1.0.0
 */

package org.timesafari.dailynotification;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.getcapacitor.JSObject;
import com.getcapacitor.PluginCall;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Manager class for daily reminder operations
 *
 * Responsibilities:
 * - Schedule daily reminders
 * - Cancel scheduled reminders
 * - Update existing reminders
 * - Retrieve reminder list
 * - Manage persistent storage
 */
public class DailyReminderManager {
    private static final String TAG = "DailyReminderManager";
    private static final String PREF_NAME = "daily_reminders";
    private static final String REMINDER_ID_PREFIX = "reminder_";
    
    private final Context context;
    private final DailyNotificationScheduler scheduler;
    
    /**
     * Initialize the DailyReminderManager
     *
     * @param context Android context
     * @param scheduler Notification scheduler instance
     */
    public DailyReminderManager(Context context, 
                                DailyNotificationScheduler scheduler) {
        this.context = context;
        this.scheduler = scheduler;
        Log.d(TAG, "DailyReminderManager initialized");
    }
    
    /**
     * Schedule a new daily reminder
     *
     * @param id Unique identifier for the reminder
     * @param title Reminder title
     * @param body Reminder body text
     * @param time Time in HH:mm format
     * @param sound Whether to play sound
     * @param vibration Whether to vibrate
     * @param priority Notification priority
     * @param repeatDaily Whether to repeat daily
     * @param timezone Optional timezone string
     * @return true if scheduled successfully
     */
    public boolean scheduleReminder(String id, String title, String body, 
                                   String time, boolean sound, 
                                   boolean vibration, String priority, 
                                   boolean repeatDaily, String timezone) {
        try {
            Log.d(TAG, "Scheduling daily reminder: " + id);
            
            // Validate time format
            String[] timeParts = time.split(":");
            if (timeParts.length != 2) {
                Log.e(TAG, "Invalid time format: " + time);
                return false;
            }
            
            int hour = Integer.parseInt(timeParts[0]);
            int minute = Integer.parseInt(timeParts[1]);
            
            if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
                Log.e(TAG, "Invalid time values");
                return false;
            }
            
            // Create reminder content
            NotificationContent reminderContent = new NotificationContent();
            reminderContent.setId(REMINDER_ID_PREFIX + id);
            reminderContent.setTitle(title);
            reminderContent.setBody(body);
            reminderContent.setSound(sound);
            reminderContent.setPriority(priority);
            
            // Calculate next trigger time
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, hour);
            calendar.set(Calendar.MINUTE, minute);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            
            // If time has passed today, schedule for tomorrow
            if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
            
            reminderContent.setScheduledTime(calendar.getTimeInMillis());
            
            // Store reminder in database
            storeReminderInDatabase(id, title, body, time, sound, 
                                  vibration, priority, repeatDaily, timezone);
            
            // Schedule the notification
            boolean scheduled = scheduler.scheduleNotification(reminderContent);
            
            if (scheduled) {
                Log.i(TAG, "Daily reminder scheduled successfully: " + id);
            } else {
                Log.e(TAG, "Failed to schedule daily reminder: " + id);
            }
            
            return scheduled;
            
        } catch (Exception e) {
            Log.e(TAG, "Error scheduling daily reminder", e);
            return false;
        }
    }
    
    /**
     * Cancel a scheduled reminder
     *
     * @param reminderId Reminder ID to cancel
     * @return true if cancelled successfully
     */
    public boolean cancelReminder(String reminderId) {
        try {
            Log.d(TAG, "Cancelling daily reminder: " + reminderId);
            
            // Cancel the scheduled notification
            scheduler.cancelNotification(REMINDER_ID_PREFIX + reminderId);
            
            // Remove from database
            removeReminderFromDatabase(reminderId);
            
            Log.i(TAG, "Daily reminder cancelled: " + reminderId);
            return true;
            
        } catch (Exception e) {
            Log.e(TAG, "Error cancelling daily reminder", e);
            return false;
        }
    }
    
    /**
     * Update an existing reminder
     *
     * @param reminderId Reminder ID to update
     * @param title Optional new title
     * @param body Optional new body
     * @param time Optional new time in HH:mm format
     * @param sound Optional new sound setting
     * @param vibration Optional new vibration setting
     * @param priority Optional new priority
     * @param repeatDaily Optional new repeat setting
     * @param timezone Optional new timezone
     * @return true if updated successfully
     */
    public boolean updateReminder(String reminderId, String title, 
                                 String body, String time, Boolean sound, 
                                 Boolean vibration, String priority, 
                                 Boolean repeatDaily, String timezone) {
        try {
            Log.d(TAG, "Updating daily reminder: " + reminderId);
            
            // Cancel existing reminder
            scheduler.cancelNotification(REMINDER_ID_PREFIX + reminderId);
            
            // Update in database
            updateReminderInDatabase(reminderId, title, body, time, 
                                   sound, vibration, priority, 
                                   repeatDaily, timezone);
            
            // Reschedule with new settings
            if (title != null && body != null && time != null) {
                // Parse time
                String[] timeParts = time.split(":");
                int hour = Integer.parseInt(timeParts[0]);
                int minute = Integer.parseInt(timeParts[1]);
                
                // Create new reminder content
                NotificationContent reminderContent = new NotificationContent();
                reminderContent.setId(REMINDER_ID_PREFIX + reminderId);
                reminderContent.setTitle(title);
                reminderContent.setBody(body);
                reminderContent.setSound(sound != null ? sound : true);
                reminderContent.setPriority(priority != null ? priority : "normal");
                
                // Calculate next trigger time
                Calendar calendar = Calendar.getInstance();
                calendar.set(Calendar.HOUR_OF_DAY, hour);
                calendar.set(Calendar.MINUTE, minute);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);
                
                if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
                }
                
                reminderContent.setScheduledTime(calendar.getTimeInMillis());
                
                // Schedule the updated notification
                boolean scheduled = scheduler.scheduleNotification(reminderContent);
                
                if (!scheduled) {
                    Log.e(TAG, "Failed to reschedule updated reminder");
                    return false;
                }
            }
            
            Log.i(TAG, "Daily reminder updated: " + reminderId);
            return true;
            
        } catch (Exception e) {
            Log.e(TAG, "Error updating daily reminder", e);
            return false;
        }
    }
    
    /**
     * Get all scheduled reminders
     *
     * @return List of DailyReminderInfo objects
     */
    public List<DailyReminderInfo> getReminders() {
        try {
            Log.d(TAG, "Getting scheduled reminders");
            return getRemindersFromDatabase();
        } catch (Exception e) {
            Log.e(TAG, "Error getting reminders from database", e);
            return new ArrayList<>();
        }
    }
    
    /**
     * Store reminder in SharedPreferences database
     */
    private void storeReminderInDatabase(String id, String title, String body, 
                                        String time, boolean sound, 
                                        boolean vibration, String priority, 
                                        boolean repeatDaily, String timezone) {
        try {
            SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, 
                                                                  Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            
            editor.putString(id + "_title", title);
            editor.putString(id + "_body", body);
            editor.putString(id + "_time", time);
            editor.putBoolean(id + "_sound", sound);
            editor.putBoolean(id + "_vibration", vibration);
            editor.putString(id + "_priority", priority);
            editor.putBoolean(id + "_repeatDaily", repeatDaily);
            editor.putString(id + "_timezone", timezone);
            editor.putLong(id + "_createdAt", System.currentTimeMillis());
            editor.putBoolean(id + "_isScheduled", true);
            
            editor.apply();
            Log.d(TAG, "Reminder stored in database: " + id);
            
        } catch (Exception e) {
            Log.e(TAG, "Error storing reminder in database", e);
        }
    }
    
    /**
     * Remove reminder from SharedPreferences database
     */
    private void removeReminderFromDatabase(String id) {
        try {
            SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, 
                                                                  Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            
            editor.remove(id + "_title");
            editor.remove(id + "_body");
            editor.remove(id + "_time");
            editor.remove(id + "_sound");
            editor.remove(id + "_vibration");
            editor.remove(id + "_priority");
            editor.remove(id + "_repeatDaily");
            editor.remove(id + "_timezone");
            editor.remove(id + "_createdAt");
            editor.remove(id + "_isScheduled");
            editor.remove(id + "_lastTriggered");
            
            editor.apply();
            Log.d(TAG, "Reminder removed from database: " + id);
            
        } catch (Exception e) {
            Log.e(TAG, "Error removing reminder from database", e);
        }
    }
    
    /**
     * Get reminders from SharedPreferences database
     */
    private List<DailyReminderInfo> getRemindersFromDatabase() {
        List<DailyReminderInfo> reminders = new ArrayList<>();
        
        try {
            SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, 
                                                                  Context.MODE_PRIVATE);
            Map<String, ?> allEntries = prefs.getAll();
            
            Set<String> reminderIds = new HashSet<>();
            for (String key : allEntries.keySet()) {
                if (key.endsWith("_title")) {
                    String id = key.substring(0, key.length() - 6); // Remove "_title"
                    reminderIds.add(id);
                }
            }
            
            for (String id : reminderIds) {
                DailyReminderInfo reminder = new DailyReminderInfo();
                reminder.id = id;
                reminder.title = prefs.getString(id + "_title", "");
                reminder.body = prefs.getString(id + "_body", "");
                reminder.time = prefs.getString(id + "_time", "");
                reminder.sound = prefs.getBoolean(id + "_sound", true);
                reminder.vibration = prefs.getBoolean(id + "_vibration", true);
                reminder.priority = prefs.getString(id + "_priority", "normal");
                reminder.repeatDaily = prefs.getBoolean(id + "_repeatDaily", true);
                reminder.timezone = prefs.getString(id + "_timezone", null);
                reminder.isScheduled = prefs.getBoolean(id + "_isScheduled", false);
                reminder.createdAt = prefs.getLong(id + "_createdAt", 0);
                reminder.lastTriggered = prefs.getLong(id + "_lastTriggered", 0);
                
                // Calculate next trigger time
                String[] timeParts = reminder.time.split(":");
                int hour = Integer.parseInt(timeParts[0]);
                int minute = Integer.parseInt(timeParts[1]);
                
                Calendar calendar = Calendar.getInstance();
                calendar.set(Calendar.HOUR_OF_DAY, hour);
                calendar.set(Calendar.MINUTE, minute);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);
                
                if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
                }
                
                reminder.nextTriggerTime = calendar.getTimeInMillis();
                
                reminders.add(reminder);
            }
            
        } catch (Exception e) {
            Log.e(TAG, "Error getting reminders from database", e);
        }
        
        return reminders;
    }
    
    /**
     * Update reminder in SharedPreferences database
     */
    private void updateReminderInDatabase(String id, String title, String body, 
                                         String time, Boolean sound, 
                                         Boolean vibration, String priority, 
                                         Boolean repeatDaily, String timezone) {
        try {
            SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, 
                                                                  Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            
            if (title != null) editor.putString(id + "_title", title);
            if (body != null) editor.putString(id + "_body", body);
            if (time != null) editor.putString(id + "_time", time);
            if (sound != null) editor.putBoolean(id + "_sound", sound);
            if (vibration != null) editor.putBoolean(id + "_vibration", vibration);
            if (priority != null) editor.putString(id + "_priority", priority);
            if (repeatDaily != null) editor.putBoolean(id + "_repeatDaily", repeatDaily);
            if (timezone != null) editor.putString(id + "_timezone", timezone);
            
            editor.apply();
            Log.d(TAG, "Reminder updated in database: " + id);
            
        } catch (Exception e) {
            Log.e(TAG, "Error updating reminder in database", e);
        }
    }
}

