/**
 * NotificationDeliveryDao.java
 * 
 * Data Access Object for NotificationDeliveryEntity operations
 * Provides efficient queries for delivery tracking and analytics
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 * @since 2025-10-20
 */

package org.timesafari.dailynotification.dao;

import androidx.room.*;
import org.timesafari.dailynotification.entities.NotificationDeliveryEntity;

import java.util.List;

/**
 * Data Access Object for notification delivery tracking operations
 * 
 * Provides efficient database operations for:
 * - Delivery event tracking and analytics
 * - Performance monitoring and debugging
 * - User interaction analysis
 * - Error tracking and reporting
 */
@Dao
public interface NotificationDeliveryDao {
    
    // ===== BASIC CRUD OPERATIONS =====
    
    /**
     * Insert a new delivery tracking entity
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertDelivery(NotificationDeliveryEntity delivery);
    
    /**
     * Insert multiple delivery tracking entities
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertDeliveries(List<NotificationDeliveryEntity> deliveries);
    
    /**
     * Update an existing delivery tracking entity
     */
    @Update
    void updateDelivery(NotificationDeliveryEntity delivery);
    
    /**
     * Delete a delivery tracking entity by ID
     */
    @Query("DELETE FROM notification_delivery WHERE id = :id")
    void deleteDelivery(String id);
    
    /**
     * Delete delivery tracking entities by notification ID
     */
    @Query("DELETE FROM notification_delivery WHERE notification_id = :notificationId")
    void deleteDeliveriesByNotificationId(String notificationId);
    
    // ===== QUERY OPERATIONS =====
    
    /**
     * Get delivery tracking by ID
     */
    @Query("SELECT * FROM notification_delivery WHERE id = :id")
    NotificationDeliveryEntity getDeliveryById(String id);
    
    /**
     * Get all delivery tracking entities
     */
    @Query("SELECT * FROM notification_delivery ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getAllDeliveries();
    
    /**
     * Get delivery tracking by notification ID
     */
    @Query("SELECT * FROM notification_delivery WHERE notification_id = :notificationId ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByNotificationId(String notificationId);
    
    /**
     * Get delivery tracking by TimeSafari DID
     */
    @Query("SELECT * FROM notification_delivery WHERE timesafari_did = :timesafariDid ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByTimeSafariDid(String timesafariDid);
    
    /**
     * Get delivery tracking by status
     */
    @Query("SELECT * FROM notification_delivery WHERE delivery_status = :deliveryStatus ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByStatus(String deliveryStatus);
    
    /**
     * Get successful deliveries
     */
    @Query("SELECT * FROM notification_delivery WHERE delivery_status = 'delivered' ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getSuccessfulDeliveries();
    
    /**
     * Get failed deliveries
     */
    @Query("SELECT * FROM notification_delivery WHERE delivery_status = 'failed' ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getFailedDeliveries();
    
    /**
     * Get deliveries with user interactions
     */
    @Query("SELECT * FROM notification_delivery WHERE user_interaction_type IS NOT NULL ORDER BY user_interaction_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesWithUserInteractions();
    
    // ===== TIME-BASED QUERIES =====
    
    /**
     * Get deliveries in time range
     */
    @Query("SELECT * FROM notification_delivery WHERE delivery_timestamp BETWEEN :startTime AND :endTime ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesInTimeRange(long startTime, long endTime);
    
    /**
     * Get recent deliveries
     */
    @Query("SELECT * FROM notification_delivery WHERE delivery_timestamp > :sinceTime ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getRecentDeliveries(long sinceTime);
    
    /**
     * Get deliveries by delivery method
     */
    @Query("SELECT * FROM notification_delivery WHERE delivery_method = :deliveryMethod ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByMethod(String deliveryMethod);
    
    // ===== ANALYTICS QUERIES =====
    
    /**
     * Get delivery success rate
     */
    @Query("SELECT COUNT(*) FROM notification_delivery WHERE delivery_status = 'delivered'")
    int getSuccessfulDeliveryCount();
    
    /**
     * Get delivery failure count
     */
    @Query("SELECT COUNT(*) FROM notification_delivery WHERE delivery_status = 'failed'")
    int getFailedDeliveryCount();
    
    /**
     * Get total delivery count
     */
    @Query("SELECT COUNT(*) FROM notification_delivery")
    int getTotalDeliveryCount();
    
    /**
     * Get average delivery duration
     */
    @Query("SELECT AVG(delivery_duration_ms) FROM notification_delivery WHERE delivery_duration_ms > 0")
    double getAverageDeliveryDuration();
    
    /**
     * Get user interaction count
     */
    @Query("SELECT COUNT(*) FROM notification_delivery WHERE user_interaction_type IS NOT NULL")
    int getUserInteractionCount();
    
    /**
     * Get average user interaction duration
     */
    @Query("SELECT AVG(user_interaction_duration_ms) FROM notification_delivery WHERE user_interaction_duration_ms > 0")
    double getAverageUserInteractionDuration();
    
    // ===== ERROR ANALYSIS QUERIES =====
    
    /**
     * Get deliveries by error code
     */
    @Query("SELECT * FROM notification_delivery WHERE error_code = :errorCode ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByErrorCode(String errorCode);
    
    /**
     * Get most common error codes
     */
    @Query("SELECT error_code AS errorCode, COUNT(*) AS count FROM notification_delivery WHERE error_code IS NOT NULL GROUP BY error_code ORDER BY count DESC")
    List<ErrorCodeCount> getErrorCodeCounts();
    
    /**
     * Get deliveries with specific error messages
     */
    @Query("SELECT * FROM notification_delivery WHERE error_message LIKE :errorPattern ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByErrorPattern(String errorPattern);
    
    // ===== PERFORMANCE ANALYSIS QUERIES =====
    
    /**
     * Get deliveries by battery level
     */
    @Query("SELECT * FROM notification_delivery WHERE battery_level BETWEEN :minBattery AND :maxBattery ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesByBatteryLevel(int minBattery, int maxBattery);
    
    /**
     * Get deliveries in doze mode
     */
    @Query("SELECT * FROM notification_delivery WHERE doze_mode_active = 1 ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesInDozeMode();
    
    /**
     * Get deliveries without exact alarm permission
     */
    @Query("SELECT * FROM notification_delivery WHERE exact_alarm_permission = 0 ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesWithoutExactAlarmPermission();
    
    /**
     * Get deliveries without notification permission
     */
    @Query("SELECT * FROM notification_delivery WHERE notification_permission = 0 ORDER BY delivery_timestamp DESC")
    List<NotificationDeliveryEntity> getDeliveriesWithoutNotificationPermission();
    
    // ===== CLEANUP OPERATIONS =====
    
    /**
     * Delete old delivery tracking data
     */
    @Query("DELETE FROM notification_delivery WHERE delivery_timestamp < :cutoffTime")
    int deleteOldDeliveries(long cutoffTime);
    
    /**
     * Delete delivery tracking by TimeSafari DID
     */
    @Query("DELETE FROM notification_delivery WHERE timesafari_did = :timesafariDid")
    int deleteDeliveriesByTimeSafariDid(String timesafariDid);
    
    /**
     * Delete failed deliveries older than specified time
     */
    @Query("DELETE FROM notification_delivery WHERE delivery_status = 'failed' AND delivery_timestamp < :cutoffTime")
    int deleteOldFailedDeliveries(long cutoffTime);
    
    // ===== BULK OPERATIONS =====
    
    /**
     * Update delivery status for multiple deliveries
     */
    @Query("UPDATE notification_delivery SET delivery_status = :deliveryStatus WHERE id IN (:ids)")
    void updateDeliveryStatusForDeliveries(List<String> ids, String deliveryStatus);
    
    /**
     * Record user interactions for multiple deliveries
     */
    @Query("UPDATE notification_delivery SET user_interaction_type = :interactionType, user_interaction_timestamp = :timestamp, user_interaction_duration_ms = :duration WHERE id IN (:ids)")
    void recordUserInteractionsForDeliveries(List<String> ids, String interactionType, long timestamp, long duration);
    
    // ===== REPORTING QUERIES =====
    
    /**
     * Get delivery statistics by day
     */
    @Query("SELECT DATE(delivery_timestamp/1000, 'unixepoch') as day, COUNT(*) as count, SUM(CASE WHEN delivery_status = 'delivered' THEN 1 ELSE 0 END) as successful FROM notification_delivery GROUP BY DATE(delivery_timestamp/1000, 'unixepoch') ORDER BY day DESC")
    List<DailyDeliveryStats> getDailyDeliveryStats();
    
    /**
     * Get delivery statistics by hour
     */
    @Query("SELECT strftime('%H', delivery_timestamp/1000, 'unixepoch') as hour, COUNT(*) as count, SUM(CASE WHEN delivery_status = 'delivered' THEN 1 ELSE 0 END) as successful FROM notification_delivery GROUP BY strftime('%H', delivery_timestamp/1000, 'unixepoch') ORDER BY hour")
    List<HourlyDeliveryStats> getHourlyDeliveryStats();
    
    // ===== DATA CLASSES FOR COMPLEX QUERIES =====
    
    /**
     * Data class for error code counts
     */
    class ErrorCodeCount {
        public String errorCode;
        public int count;
        
        public ErrorCodeCount(String errorCode, int count) {
            this.errorCode = errorCode;
            this.count = count;
        }
    }
    
    /**
     * Data class for daily delivery statistics
     */
    class DailyDeliveryStats {
        public String day;
        public int count;
        public int successful;
        
        public DailyDeliveryStats(String day, int count, int successful) {
            this.day = day;
            this.count = count;
            this.successful = successful;
        }
    }
    
    /**
     * Data class for hourly delivery statistics
     */
    class HourlyDeliveryStats {
        public String hour;
        public int count;
        public int successful;
        
        public HourlyDeliveryStats(String hour, int count, int successful) {
            this.hour = hour;
            this.count = count;
            this.successful = successful;
        }
    }
}
