use crate::error::AppError;
use crate::models::project::Project;
use crate::AppState;
use std::process::Command;
use tauri::State;

#[tauri::command]
pub fn create_project(
    state: State<'_, AppState>,
    name: String,
    path_or_url: String,
    base_branch: String,
) -> Result<Project, AppError> {
    let is_url = path_or_url.starts_with("http://")
        || path_or_url.starts_with("https://")
        || path_or_url.starts_with("git@");

    let (local_path, cloned_from) = if is_url {
        let home = dirs::home_dir().ok_or_else(|| AppError::from("Cannot determine home directory".to_string()))?;
        let clone_dir = home.join("orchai-repos").join(&name);
        std::fs::create_dir_all(&clone_dir)?;

        let clone_dir_str = clone_dir.to_str()
            .ok_or_else(|| AppError::from("Clone path contains invalid characters".to_string()))?;

        let output = Command::new("git")
            .args(["clone", &path_or_url, clone_dir_str])
            .output()?;

        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AppError::from(format!("git clone failed: {}", stderr)));
        }

        (clone_dir.to_string_lossy().to_string(), Some(path_or_url))
    } else {
        let path = std::path::Path::new(&path_or_url);
        if !path.exists() {
            return Err(AppError::from(format!("Path does not exist: {}", path_or_url)));
        }
        if !path.join(".git").exists() {
            return Err(AppError::from(format!("Not a git repository: {}", path_or_url)));
        }
        (path_or_url, None)
    };

    let db = state.db.lock().map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;
    let project = Project::insert(&db, &name, &local_path, cloned_from.as_deref(), &base_branch)?;
    Ok(project)
}

#[tauri::command]
pub fn list_projects(state: State<'_, AppState>) -> Result<Vec<Project>, AppError> {
    let db = state.db.lock().map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;
    let projects = Project::list(&db)?;
    Ok(projects)
}

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

#[tauri::command]
pub fn update_project(
    state: State<'_, AppState>,
    id: String,
    name: String,
    base_branch: String,
) -> Result<(), AppError> {
    let db = state.db.lock().map_err(|e| AppError::from(format!("Database lock failed: {}", e)))?;
    Project::update(&db, &id, &name, &base_branch)?;
    Ok(())
}

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