use notify::{Config, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::path::Path;
use std::sync::mpsc;
use std::time::Duration;
use tauri::{AppHandle, Emitter, Manager};

use crate::state::AppState;
use crate::types::FileEvent;
use crate::vault::operations::helixnotes_dir;

pub fn start_watcher(app: AppHandle, vault_path: String) -> Result<RecommendedWatcher, String> {
    let (tx, rx) = mpsc::channel();

    let mut watcher = RecommendedWatcher::new(
        tx,
        Config::default().with_poll_interval(Duration::from_secs(1)),
    )
    .map_err(|e| e.to_string())?;

    watcher
        .watch(Path::new(&vault_path), RecursiveMode::Recursive)
        .map_err(|e| e.to_string())?;

    let hn_dir = helixnotes_dir(&vault_path);

    std::thread::spawn(move || {
        while let Ok(result) = rx.recv() {
            match result {
                Ok(event) => {
                    // Skip all file events while importing
                    let state = app.state::<AppState>();
                    if state.importing.load(std::sync::atomic::Ordering::Relaxed) {
                        continue;
                    }
                    // Skip .helixnotes directory events
                    let dominated_by_hn = event.paths.iter().all(|p| p.starts_with(&hn_dir));
                    if dominated_by_hn {
                        continue;
                    }

                    // Only care about .md file events
                    let has_md = event.paths.iter().any(|p| {
                        p.extension().and_then(|x| x.to_str()) == Some("md") || p.is_dir()
                    });

                    if !has_md {
                        continue;
                    }

                    let event_type = match event.kind {
                        EventKind::Create(_) => "create",
                        EventKind::Modify(_) => "modify",
                        EventKind::Remove(_) => "remove",
                        _ => continue,
                    };

                    for path in &event.paths {
                        let fe = FileEvent {
                            event_type: event_type.to_string(),
                            path: path.to_string_lossy().to_string(),
                        };
                        let _ = app.emit("file-changed", &fe);
                    }
                }
                Err(e) => {
                    log::error!("File watcher error: {}", e);
                }
            }
        }
    });

    Ok(watcher)
}
