mod commands;
mod models;
mod service;
mod utils;

use commands::{category, commodity, table};
use sea_orm::{ConnectionTrait, DatabaseConnection};
use std::fs::File;
use std::sync::Arc;
use tauri::State;
use tauri::{AppHandle, Manager};

type CmdState<'a> = State<'a, AppState>;
type CmdResult<T> = Result<T, String>;

#[derive(Default)]
pub struct AppState {
    pub conn: Arc<DatabaseConnection>,
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            tauri::async_runtime::block_on(async {
                let app_dir = app.handle().path().app_data_dir()?;
                std::fs::create_dir_all(&app_dir)?;
                let db_path = app_dir.join("store.sqlite");
                if !db_path.exists() {
                    File::create(&db_path)?;
                }
                let db_url = format!("sqlite:{}", db_path.display());
                let conn = sea_orm::Database::connect(&db_url)
                    .await
                    .map_err(|e| anyhow::anyhow!("Database connection error: {}", e))?;
                conn.execute_unprepared("PRAGMA journal_mode=WAL;")
                    .await
                    .map_err(|e| anyhow::anyhow!("Failed to set WAL mode: {}", e))?;
                utils::migration_db(app, &conn).await?;
                app.manage(AppState {
                    conn: Arc::new(conn),
                });
                Ok(())
            })
        })
        .invoke_handler(tauri::generate_handler![
            table::get_table_area,
            category::get_category,
            commodity::get_commodity
        ])
        .plugin(tauri_plugin_os::init())
        .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
            let _ = show_window(app);
        }))
        .plugin(tauri_plugin_store::Builder::new().build())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

fn show_window(app: &AppHandle) {
    let windows = app.webview_windows();

    windows
        .values()
        .next()
        .expect("Sorry, no window found")
        .set_focus()
        .expect("Can't Bring Window to Focus");
}
