mod app;       // Declare the app module (state/actions/reducer to come)
mod async_result; // Async operation results
mod commands;  // Command layer for side effects
mod components; // Component-based architecture
mod config;    // Config module (settings, keymaps, themes to come)
mod errors;    // Error types for components, commands, services
mod git;       // Git layer (git CLI primary, libgit2 for local ops to come)
mod input;     // Input event normalization
mod jobs;      // Async job executor module to come
mod palette;   // Command palette system
mod services;  // Service layer (GitService, etc.)
mod ui;        // UI helpers (styles)

use anyhow::Result;
use tracing_subscriber::EnvFilter; 
use ratatui::{backend::CrosstermBackend, Terminal};
use std::io;
use crossterm::terminal::{enable_raw_mode, disable_raw_mode};
use crossterm::execute;
use crossterm::terminal::{EnterAlternateScreen, LeaveAlternateScreen};
use crossterm::event::{EnableMouseCapture, DisableMouseCapture};
use std::sync::Arc;
use tokio::sync::{watch, mpsc};
use notify::{Watcher, RecursiveMode, RecommendedWatcher};

// Initialize tracing/logging; override with RUST_LOG=debug ./eazygit
fn init_tracing() {
    let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
    tracing_subscriber::fmt()
        .with_env_filter(filter)
        .with_target(false)
        .without_time()
        .with_writer(std::io::stderr)
        .init();
}

#[tokio::main]
async fn main() -> Result<()> {
    // Parse command-line arguments before initializing TUI
    let args: Vec<String> = std::env::args().collect();
    
    // Handle --version and -v flags
    if args.iter().any(|arg| arg == "--version" || arg == "-v") {
        println!("eazygit {}", env!("CARGO_PKG_VERSION"));
        return Ok(());
    }
    
    // Handle --help and -h flags
    if args.iter().any(|arg| arg == "--help" || arg == "-h") {
        println!("eazygit - A fast, easy-to-use Git TUI");
        println!();
        println!("USAGE:");
        println!("    eazygit [OPTIONS]");
        println!();
        println!("OPTIONS:");
        println!("    -v, --version    Print version information");
        println!("    -h, --help       Print this help message");
        println!();
        println!("Run eazygit in a Git repository to start the TUI.");
        return Ok(());
    }
    
    init_tracing();
    tracing::info!("Starting eazygit");

    // Ensure default config exists
    if let Err(e) = config::create_default_config() {
        tracing::warn!("config create failed: {e}");
    }

    // Load settings
    let settings = config::load()?;
    tracing::info!("Loaded theme: {}, border: {}", settings.theme, settings.theme_config.border);
    let themes = config::list_themes();

    // Initialize services
    let git_service = Arc::new(services::GitService::new());

    // Initialize state
    let mut state = app::AppState::new();
    state.repo_path = settings.repo_path.clone();
    state.theme = settings.theme_config.clone();
    state.available_themes = themes;
    state.pull_timeout_secs = settings.pull_timeout_secs;
    state.rebase_timeout_secs = settings.rebase_timeout_secs;
    state.font_family = settings.font_family.clone();
    state.font_size = settings.font_size;
    state.commit_template = settings.commit_template.clone();
    state.custom_commands = settings.custom_commands.clone();
    
    // Check delta availability
    let git_cli = git::cli::GitCli::new();
    state = app::reducer(state, app::Action::SetHasDelta(git_cli.has_delta()));

    // Initialize component manager
    let component_manager = components::ComponentManager::new(git_service.clone());

    // Setup cancellation channel
    let (cancel_tx, cancel_rx) = watch::channel(false);
    
    // Spawn cancellation handler (Ctrl+C)
    let cancel_tx_clone = cancel_tx.clone();
    tokio::spawn(async move {
        if tokio::signal::ctrl_c().await.is_ok() {
            let _ = cancel_tx_clone.send(true);
        }
    });
    
    // Setup async task channel
    let (async_tx, async_rx) = mpsc::unbounded_channel::<crate::async_result::AsyncResult>();
    
    // Setup file watcher
    let watcher_tx = async_tx.clone();
    let watch_path = state.repo_path.clone();
    let watcher: Option<RecommendedWatcher> = {
        let tx = watcher_tx.clone();
        let debounce = Arc::new(std::sync::Mutex::new(std::time::Instant::now()));
        match notify::recommended_watcher(move |res: Result<notify::Event, notify::Error>| {
            if let Ok(event) = res {
                let dominated_by_write = event.kind.is_modify() || event.kind.is_create() || event.kind.is_remove();
                if dominated_by_write {
                    // Defensive: handle mutex poisoning gracefully
                    // If mutex is poisoned, log warning and skip debounce check
                    match debounce.lock() {
                        Ok(mut last) => {
                            if last.elapsed().as_millis() > 200 {
                                *last = std::time::Instant::now();
                                let _ = tx.send(crate::async_result::AsyncResult::FileChanged);
                            }
                        }
                        Err(_) => {
                            // Mutex poisoned - log and send event anyway (better than missing file changes)
                            tracing::warn!("File watcher debounce mutex poisoned, sending event anyway");
                            let _ = tx.send(crate::async_result::AsyncResult::FileChanged);
                        }
                    }
                }
            }
        }) {
            Ok(mut w) => {
                if w.watch(std::path::Path::new(&watch_path), RecursiveMode::Recursive).is_ok() {
                    tracing::info!("File watcher enabled for {}", watch_path);
                    Some(w)
                } else {
                    tracing::warn!("File watcher failed to watch path");
                    None
                }
            }
            Err(e) => {
                tracing::warn!("File watcher not available: {}", e);
                None
            }
        }
    };
    
    // Setup terminal
    enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    // Initialize application
    let mut application = app::Application::new(
                    state,
        component_manager,
        git_service,
        cancel_rx,
        async_tx,
        async_rx,
        watcher,
    )?;

    // Run application
    if let Err(e) = application.run(&mut terminal).await {
        tracing::error!(error = %e, "Application error");
    }

    // Restore terminal
    disable_raw_mode()?;
    let mut out = io::stdout();
    execute!(out, DisableMouseCapture, LeaveAlternateScreen)?;

    tracing::info!("Exiting eazygit");
    Ok(())
}