mod commands;
mod models;
mod service;

use sea_orm::{ConnectionTrait, DatabaseConnection, Statement, TransactionTrait};
use std::fs::{self, File};
use std::sync::Arc;
use tauri::{AppHandle, Manager, path::BaseDirectory};

// 添加 AppState 结构体
#[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))?;
                migration_db(app, &conn).await?;
                app.manage(AppState {
                    conn: Arc::new(conn),
                });
                Ok(())
            })
        })
        .plugin(tauri_plugin_os::init())
        .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
            let _ = show_window(app);
        }))
        .plugin(tauri_plugin_upload::init())
        .plugin(tauri_plugin_http::init())
        .plugin(tauri_plugin_store::Builder::new().build())
        .plugin(tauri_plugin_opener::init())
        .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");
}

async fn migration_db(app: &tauri::App, conn: &DatabaseConnection) -> anyhow::Result<()> {
    let sql_path = app
        .path()
        .resolve("resources/init.sql", BaseDirectory::Resource)?;
    conn.execute(Statement::from_string(
        conn.get_database_backend(),
        "CREATE TABLE IF NOT EXISTS seaql_migrations (
            version VARCHAR(255) PRIMARY KEY,
            applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )"
        .to_owned(),
    ))
    .await?;
    let applied: Vec<String> = conn
        .query_all(Statement::from_string(
            conn.get_database_backend(),
            "SELECT version FROM seaql_migrations".to_owned(),
        ))
        .await?
        .into_iter()
        .filter_map(|row| row.try_get("", "version").ok())
        .collect();

    if let Some(sql_path_stem) = sql_path.file_stem() {
        if let Some(version) = sql_path_stem.to_str() {
            if !applied.contains(&version.to_string()) {
                let sql_str = fs::read_to_string(&sql_path)?;
                let tx = conn.begin().await?;
                tx.execute(Statement::from_string(conn.get_database_backend(), sql_str))
                    .await?;
                tx.execute(Statement::from_string(
                    conn.get_database_backend(),
                    format!(
                        "INSERT INTO seaql_migrations (version) VALUES ('{}')",
                        version
                    ),
                ))
                .await?;
                tx.commit().await?;
                println!("✅ Applied migration: {}", version);
            }
        }
    }

    Ok(())
}
