use anyhow::Result;
use std::path::Path;
use std::sync::Arc;
use tokio::time;
use tracing::{error, info, warn};

use crate::core::db::{Database, PostgresDb};
use crate::core::ingestion::IngestionService;

pub struct WatcherConfig {
    pub directories: Vec<String>,
    pub poll_interval_ms: u64,
}

impl Default for WatcherConfig {
    fn default() -> Self {
        // Default to SFTP demo directory if not specified
        let default_dir = std::env::var("MOMENTRY_SFTP_ROOT")
            .unwrap_or_else(|_| "/Users/accusys/momentry/var/sftpgo/data/demo/".to_string());

        Self {
            directories: vec![default_dir],
            poll_interval_ms: 60000, // 60 seconds polling interval
        }
    }
}

/// Starts the file watcher in the background.
/// Scans directories for video files and registers them if not already present.
pub async fn run_watcher() -> Result<()> {
    let config = WatcherConfig::default();
    let dirs = config.directories.clone();

    if dirs.is_empty() {
        warn!("No directories configured for watching.");
        return Err(anyhow::anyhow!("No watch directories"));
    }

    info!("Initializing Database for Watcher...");
    // Use Database::init() which handles config and pool creation
    let db = PostgresDb::init().await?;
    let service = Arc::new(IngestionService::new(db));

    info!("Starting Ingestion Poller for: {:?}", dirs);

    // Spawn background task
    tokio::spawn(async move {
        let mut interval = time::interval(time::Duration::from_millis(config.poll_interval_ms));

        // Run once immediately on startup to catch existing files
        scan_and_ingest(&dirs, &service).await;

        loop {
            interval.tick().await;
            scan_and_ingest(&dirs, &service).await;
        }
    });

    Ok(())
}

async fn scan_and_ingest(directories: &[String], service: &Arc<IngestionService>) {
    // Allowed extensions list
    let allowed_extensions = vec!["mp4", "mov", "mkv"];

    info!("Scanning directories for new videos...");

    for dir in directories {
        let path = Path::new(dir);
        if !path.exists() {
            warn!("Directory does not exist, skipping: {}", dir);
            continue;
        }

        if let Ok(entries) = std::fs::read_dir(path) {
            for entry in entries.flatten() {
                let file_path = entry.path();
                if file_path.is_file() {
                    // Check extension
                    let is_video = if let Some(ext) = file_path.extension().and_then(|e| e.to_str())
                    {
                        allowed_extensions.contains(&ext.to_lowercase().as_str())
                    } else {
                        false
                    };

                    if is_video {
                        if let Some(p_str) = file_path.to_str() {
                            // Try to ingest. The service checks if it already exists.
                            match service.ingest(p_str).await {
                                Ok(Some(uuid)) => {
                                    info!("Auto-registered: {} -> {}", file_path.display(), uuid);
                                }
                                Ok(None) => {
                                    // Already registered
                                }
                                Err(e) => {
                                    error!("Failed to ingest {}: {}", file_path.display(), e);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
