mod menu;
mod tray;
mod updater;

use frenocorp_lib::{
    menu::create_menu,
    tray::create_system_tray,
    updater::check_for_updates,
};
use log::{info, LevelFilter};
use std::env;
use tauri::{
    menu::{Menu, MenuEvent},
    tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
    AppHandle, Emitter, Manager, RunEvent,
};
use tauri_plugin_store::StoreExt;

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

#[tauri::command]
fn get_app_version(app_handle: AppHandle) -> String {
    app_handle
        .package_info()
        .version
        .to_string()
}

#[tauri::command]
async fn save_window_state(app_handle: AppHandle, state: WindowState) -> Result<(), String> {
    let mut store = app_handle.store("window-state.bin")?;
    store.insert("window", state).map_err(|e| e.to_string())?;
    store.save().map_err(|e| e.to_string())
}

#[tauri::command]
async fn load_window_state(app_handle: AppHandle) -> Result<Option<WindowState>, String> {
    let store = app_handle.store("window-state.bin");
    match store {
        Ok(store) => {
            let state = store.get::<WindowState>("window");
            Ok(state)
        }
        Err(_) => Ok(None),
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct WindowState {
    width: f64,
    height: f64,
    x: i32,
    y: i32,
    is_maximized: bool,
}

fn init_logger() {
    let env_level = env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
    let level = match env_level.as_str() {
        "debug" => LevelFilter::Debug,
        "warn" => LevelFilter::Warn,
        "error" => LevelFilter::Error,
        _ => LevelFilter::Info,
    };

    env_logger::Builder::from_env(env::var("RUST_LOG").unwrap_or_default())
        .format_module_path(false)
        .format_timestamp(Some(env_logger::TimestampPrecision::Millis))
        .filter_level(level)
        .init();
}

#[tokio::main]
async fn main() {
    init_logger();
    info!("Starting FrenoCorp Desktop application");

    let mut tauri_app = tauri::Builder::default();

    tauri_app
        .plugin(tauri_plugin_fs::init())
        .plugin(tauri_plugin_http::init())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_shell::init())
        .plugin(tauri_plugin_store::init())
        .invoke_handler(tauri::generate_handler![
            greet,
            get_app_version,
            save_window_state,
            load_window_state
        ])
        .menu(create_menu())
        .on_menu_event(|app, event| {
            info!("Menu event received: {:?}", event.id());
            handle_menu_event(app, event.id())
        })
        .system_tray(create_system_tray())
        .on_system_tray_event(handle_tray_event)
        .setup(|app| {
            info!("Setting up application");
            
            // Check for updates on startup
            let app_handle = app.handle().clone();
            tokio::spawn(async move {
                if let Err(e) = check_for_updates(app_handle).await {
                    log::error!("Failed to check for updates: {}", e);
                }
            });

            Ok(())
        })
        .on_window_event(|window, event| match event {
            tauri::WindowEvent::CloseRequested { api, .. } => {
                let window = window.clone();
                let app_handle = window.app_handle().clone();
                
                api.prevent_close();
                
                window.hide().unwrap();
                
                let mut store = app_handle.store("window-state.bin").unwrap_or_default();
                store.insert("last_window_hidden", true).unwrap();
                store.save().unwrap();
            }
            tauri::WindowEvent::Focused(focused) => {
                if *focused {
                    log::debug!("Window focused");
                }
            }
            _ => {}
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");

    info!("Application exited");
}

fn handle_menu_event(app_handle: &AppHandle, menu_item_id: tauri::menu::MenuItemId) {
    match menu_item_id.0.as_str() {
        "quit" => {
            info!("Quitting application");
            app_handle.exit(0);
        }
        "preferences" => {
            info!("Opening preferences");
            // TODO: Open preferences window
        }
        "check_updates" => {
            info!("Checking for updates");
            let app_handle = app_handle.clone();
            tokio::spawn(async move {
                if let Err(e) = check_for_updates(app_handle).await {
                    log::error!("Update check failed: {}", e);
                }
            });
        }
        _ => {
            info!("Unknown menu item: {}", menu_item_id.0);
        }
    }
}

fn handle_tray_event(app: &AppHandle, event: TrayIconEvent) {
    match event {
        TrayIconEvent::Click {
            button: MouseButton::Left,
            button_state: MouseButtonState::Up,
            ..
        } => {
            info!("Tray icon clicked");
            if let Some(window) = app.get_webview_window("main") {
                let is_visible = window.is_visible().unwrap();
                if is_visible {
                    window.hide().unwrap();
                } else {
                    window.show().unwrap();
                    window.set_focus().unwrap();
                }
            }
        }
        TrayIconEvent::RightClick { .. } => {
            info!("Right click on tray icon");
        }
        TrayIconEvent::DoubleClick { .. } => {
            info!("Double click on tray icon");
            if let Some(window) = app.get_webview_window("main") {
                window.show().unwrap();
                window.set_focus().unwrap();
            }
        }
        _ => {}
    }
}
