use crate::error::AppError;
use crate::models::credential::{TuleapCredentials, TuleapCredentialsSafe};
use crate::services::crypto;
use crate::services::tuleap_client::TuleapClient;
use crate::AppState;
use tauri::State;

#[tauri::command]
pub fn set_tuleap_credentials(
    state: State<'_, AppState>,
    project_id: Option<String>,
    tuleap_url: String,
    username: String,
    password: String,
) -> Result<TuleapCredentialsSafe, AppError> {
    let (tuleap_url, username, password) =
        TuleapCredentials::validate_input(&tuleap_url, &username, &password)
            .map_err(AppError::from)?;

    let password_encrypted =
        crypto::encrypt(&state.encryption_key, &password).map_err(AppError::from)?;

    let db = state
        .db
        .lock()
        .map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;

    let creds = TuleapCredentials::upsert_for_scope(
        &db,
        project_id.as_deref(),
        &tuleap_url,
        &username,
        &password_encrypted,
    )?;
    Ok(creds.to_safe())
}

#[tauri::command]
pub fn get_tuleap_credentials(
    state: State<'_, AppState>,
    project_id: Option<String>,
) -> Result<Option<TuleapCredentialsSafe>, AppError> {
    let db = state
        .db
        .lock()
        .map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;

    let result = match project_id {
        Some(project_id) => TuleapCredentials::get_for_project(&db, &project_id)?,
        None => TuleapCredentials::get_global(&db)?,
    }
    .map(|c| c.to_safe());
    Ok(result)
}

#[tauri::command]
pub fn delete_tuleap_credentials(
    state: State<'_, AppState>,
    project_id: Option<String>,
) -> Result<(), AppError> {
    let db = state
        .db
        .lock()
        .map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;

    TuleapCredentials::delete_for_scope(&db, project_id.as_deref())?;
    Ok(())
}

#[tauri::command]
pub async fn test_tuleap_connection(
    state: State<'_, AppState>,
    project_id: Option<String>,
) -> Result<String, AppError> {
    let (tuleap_url, username, password) = {
        let db = state
            .db
            .lock()
            .map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;

        let creds = match &project_id {
            Some(project_id) => TuleapCredentials::get_for_project(&db, project_id)?,
            None => TuleapCredentials::get_global(&db)?,
        }
        .ok_or_else(|| AppError::from("No credentials configured".to_string()))?;

        let password = crypto::decrypt(&state.encryption_key, &creds.password_encrypted)
            .map_err(AppError::from)?;

        (creds.tuleap_url, creds.username, password)
    };

    let client = TuleapClient::new(&state.http_client, &tuleap_url, &username, &password);
    client.test_connection().await.map_err(AppError::from)?;

    Ok("Connection successful".to_string())
}
