//! OSTP Setup Wizard - Rust Backend
//! 
//! Handles Windows Service installation, wintun driver extraction,
//! and Access Key parsing for the OSTP Client.

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod access_key;
mod service;
mod wintun;
mod system_check;

use tauri::{command, AppHandle, Emitter, Manager};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

// Re-export types from modules
pub use access_key::AccessKeyData;
pub use system_check::SystemCheckResult;

/// Installation configuration from the wizard
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstallConfig {
    pub access_key: String,
    pub country: String,
    pub install_path: PathBuf,
    pub launch_on_startup: bool,
    pub connect_now: bool,
}

/// Installation progress update
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgressUpdate {
    pub step: u8,
    pub total_steps: u8,
    pub message: String,
    pub percent: u8,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CountryOption {
    pub code: String,
    pub name: String,
    pub recommended: bool,
}

/// Check system requirements
#[command]
async fn check_system() -> Result<SystemCheckResult, String> {
    system_check::run_checks().await.map_err(|e| e.to_string())
}

/// Parse and validate access key
#[command]
async fn parse_access_key(key: String) -> Result<AccessKeyData, String> {
    access_key::parse(&key).map_err(|e| e.to_string())
}

/// Validate access key format without full parse
#[command]
fn validate_access_key(key: String) -> bool {
    access_key::validate(&key)
}

/// Get list of available countries for SNI
#[command]
fn get_countries() -> Vec<CountryOption> {
    vec![
        CountryOption { code: "RU".into(), name: "Russia".into(), recommended: true },
        CountryOption { code: "DE".into(), name: "Germany".into(), recommended: false },
        CountryOption { code: "NL".into(), name: "Netherlands".into(), recommended: false },
        CountryOption { code: "US".into(), name: "United States".into(), recommended: false },
        CountryOption { code: "SG".into(), name: "Singapore".into(), recommended: false },
        CountryOption { code: "JP".into(), name: "Japan".into(), recommended: false },
    ]
}

/// Run the full installation process
#[command]
async fn run_installation(
    app: AppHandle,
    config: InstallConfig,
) -> Result<(), String> {
    let window = app.get_webview_window("main").unwrap();
    
    // Step 1: Extract wintun.dll
    emit_progress(&window, 1, 5, "Extracting WinTUN driver...", 10);
    wintun::extract_driver(&config.install_path)
        .await
        .map_err(|e| format!("Failed to extract wintun: {}", e))?;
    
    // Step 2: Parse access key
    emit_progress(&window, 2, 5, "Parsing access key...", 25);
    let key_data = access_key::parse(&config.access_key)
        .map_err(|e| format!("Invalid access key: {}", e))?;
    
    // Step 3: Write configuration file
    emit_progress(&window, 3, 5, "Writing configuration...", 45);
    write_config(&config.install_path, &key_data, &config.country)
        .await
        .map_err(|e| format!("Failed to write config: {}", e))?;
    
    // Step 4: Install Windows Service
    emit_progress(&window, 4, 5, "Installing Windows Service...", 70);
    service::install_service(&config.install_path)
        .await
        .map_err(|e| format!("Failed to install service: {}", e))?;
    
    // Step 5: Configure startup
    emit_progress(&window, 5, 5, "Configuring startup options...", 90);
    if config.launch_on_startup {
        service::enable_autostart()
            .await
            .map_err(|e| format!("Failed to enable autostart: {}", e))?;
    }
    
    emit_progress(&window, 5, 5, "Installation complete!", 100);
    
    // Optionally connect now
    if config.connect_now {
        service::start_service()
            .await
            .map_err(|e| format!("Failed to start service: {}", e))?;
    }
    
    Ok(())
}

/// Emit progress update to frontend
fn emit_progress(window: &tauri::WebviewWindow, step: u8, total: u8, msg: &str, percent: u8) {
    let _ = window.emit("install-progress", ProgressUpdate {
        step,
        total_steps: total,
        message: msg.to_string(),
        percent,
    });
}

/// Write OSTP client configuration file
async fn write_config(
    install_path: &PathBuf,
    key_data: &AccessKeyData,
    country: &str,
) -> anyhow::Result<()> {
    use std::fs;
    
    let config_path = install_path.join("ostp-client.json");
    let config = serde_json::json!({
        "server": format!("{}:{}", key_data.server_ip, key_data.port),
        "psk": key_data.psk,
        "country": country,
        "dns": ["1.1.1.1", "8.8.8.8"],
        "mtu": 1400
    });
    
    fs::create_dir_all(install_path)?;
    fs::write(&config_path, serde_json::to_string_pretty(&config)?)?;
    
    Ok(())
}

/// Uninstall the OSTP client
#[command]
async fn uninstall() -> Result<(), String> {
    service::stop_service().await.map_err(|e| e.to_string())?;
    service::uninstall_service().await.map_err(|e| e.to_string())?;
    wintun::remove_driver().await.map_err(|e| e.to_string())?;
    Ok(())
}

/// Get default installation path
#[command]
fn get_default_install_path() -> PathBuf {
    PathBuf::from(r"C:\Program Files\Ospab Network\OSTP")
}

fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init())
        .invoke_handler(tauri::generate_handler![
            check_system,
            parse_access_key,
            validate_access_key,
            get_countries,
            run_installation,
            uninstall,
            get_default_install_path,
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
