use serde::{Serialize, Deserialize};
use tauri::State;

use crate::config::AppConfig;
use crate::credentials::{Session,BaseCredentials};
use crate::errors::*;
use crate::clientinfo::Client;
use crate::state::AppState;
use crate::terminal;


#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AwsRequestNotification {
    pub id: u64,
    pub client: Client,
    pub base: bool,
}


#[derive(Debug, Serialize, Deserialize)]
pub struct RequestResponse {
    pub id: u64,
    pub approval: Approval,
}


#[derive(Debug, Serialize, Deserialize)]
pub enum Approval {
    Approved,
    Denied,
}


#[tauri::command]
pub async fn respond(response: RequestResponse, app_state: State<'_, AppState>) -> Result<(), SendResponseError> {
    app_state.send_response(response).await
}


#[tauri::command]
pub async fn unlock(passphrase: String, app_state: State<'_, AppState>) -> Result<(), UnlockError> {
    app_state.unlock(&passphrase).await
}


#[tauri::command]
pub async fn get_session_status(app_state: State<'_, AppState>) -> Result<String, ()> {
    let session = app_state.session.read().await;
    let status = match *session {
        Session::Locked(_) => "locked".into(),
        Session::Unlocked{..} => "unlocked".into(),
        Session::Empty => "empty".into()
    };
    Ok(status)
}


#[tauri::command]
pub async fn save_credentials(
    credentials: BaseCredentials,
    passphrase: String,
    app_state: State<'_, AppState>
) -> Result<(), UnlockError> {
    app_state.new_creds(credentials, &passphrase).await
}


#[tauri::command]
pub async fn get_config(app_state: State<'_, AppState>) -> Result<AppConfig, ()> {
    let config = app_state.config.read().await;
    Ok(config.clone())
}


#[tauri::command]
pub async fn save_config(config: AppConfig, app_state: State<'_, AppState>) -> Result<(), String>  {
    app_state.update_config(config)
        .await
        .map_err(|e| format!("Error saving config: {e}"))?;
        Ok(())
}


#[tauri::command]
pub async fn launch_terminal(base: bool) -> Result<(), LaunchTerminalError> {
    terminal::launch(base).await
}


#[tauri::command]
pub async fn get_setup_errors(app_state: State<'_, AppState>) -> Result<Vec<String>, ()> {
    Ok(app_state.setup_errors.clone())
}
