use std::time::Duration;
use tokio::time::{interval, MissedTickBehavior};
use tracing::{error, info, warn};
use anyhow::Result;

use crate::utils::backup::DatabaseBackup;

pub struct BackupScheduler {
    database_url: String,
    backup_dir: String,
    interval_hours: u64,
    keep_backups: usize,
}

impl BackupScheduler {
    pub fn new(
        database_url: String,
        backup_dir: String,
        interval_hours: u64,
        keep_backups: usize,
    ) -> Self {
        Self {
            database_url,
            backup_dir,
            interval_hours,
            keep_backups,
        }
    }

    /// Start the backup scheduler task
    pub async fn start(self) -> Result<()> {
        info!(
            "Starting backup scheduler: every {} hours, keeping {} backups",
            self.interval_hours, self.keep_backups
        );

        // Create initial backup immediately after startup (with a small delay)
        let backup = DatabaseBackup::new(self.database_url.clone(), &self.backup_dir);
        
        tokio::time::sleep(Duration::from_secs(30)).await;
        
        match backup.create_backup().await {
            Ok(path) => info!("Initial backup created: {}", path.display()),
            Err(e) => error!("Failed to create initial backup: {}", e),
        }

        // Setup periodic backups
        let mut timer = interval(Duration::from_secs(self.interval_hours * 3600));
        timer.set_missed_tick_behavior(MissedTickBehavior::Skip);

        loop {
            timer.tick().await;
            
            info!("Starting scheduled database backup...");
            
            let backup = DatabaseBackup::new(self.database_url.clone(), &self.backup_dir);
            
            // Create backup
            match backup.create_backup().await {
                Ok(path) => {
                    info!("Scheduled backup completed: {}", path.display());
                    
                    // Cleanup old backups
                    if let Err(e) = backup.cleanup_old_backups(self.keep_backups).await {
                        warn!("Failed to cleanup old backups: {}", e);
                    }
                }
                Err(e) => {
                    error!("Scheduled backup failed: {}", e);
                }
            }
        }
    }

    /// Create a default scheduler with sensible defaults
    pub fn default_config(database_url: String) -> Self {
        Self::new(
            database_url,
            "/media/archive".to_string(),
            24, // Every 24 hours
            7,  // Keep 7 backups (1 week)
        )
    }

    /// Create a more frequent scheduler for critical systems
    pub fn frequent_config(database_url: String) -> Self {
        Self::new(
            database_url,
            "/media/archive".to_string(),
            6,  // Every 6 hours
            14, // Keep 14 backups (3.5 days)
        )
    }
}