use crate::error::AppError;
use crate::models::project::Project;
use crate::models::ticket::ProcessedTicket;
use crate::models::tracker::WatchedTracker;
use crate::models::worktree::Worktree;
use crate::services::worktree_manager;
use crate::AppState;
use tauri::State;

#[tauri::command]
pub fn list_worktrees(
    state: State<'_, AppState>,
    project_id: String,
) -> Result<Vec<Worktree>, AppError> {
    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
    let worktrees = Worktree::list_by_project(&conn, &project_id)?;
    Ok(worktrees)
}

#[tauri::command]
pub fn get_worktree_diff(
    state: State<'_, AppState>,
    worktree_id: String,
) -> Result<String, AppError> {
    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;

    let wt = Worktree::get_by_id(&conn, &worktree_id)?;
    let ticket = ProcessedTicket::get_by_id(&conn, &wt.ticket_id)?;
    let tracker = WatchedTracker::get_by_id(&conn, &ticket.tracker_id)?;
    let project = Project::get_by_id(&conn, &tracker.project_id)?;

    drop(conn);

    let diff = worktree_manager::get_diff(&project.path, &project.base_branch, &wt.branch_name)
        .map_err(AppError::from)?;

    Ok(diff)
}

#[tauri::command]
pub fn apply_fix_to_branch(
    state: State<'_, AppState>,
    worktree_id: String,
    target_branch: String,
) -> Result<(), AppError> {
    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;

    let wt = Worktree::get_by_id(&conn, &worktree_id)?;
    let ticket = ProcessedTicket::get_by_id(&conn, &wt.ticket_id)?;
    let tracker = WatchedTracker::get_by_id(&conn, &ticket.tracker_id)?;
    let project = Project::get_by_id(&conn, &tracker.project_id)?;

    drop(conn);

    worktree_manager::apply_fix(
        &project.path,
        &project.base_branch,
        &wt.branch_name,
        &target_branch,
    )
    .map_err(AppError::from)?;

    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
    Worktree::set_merged(&conn, &worktree_id, &target_branch)?;

    Ok(())
}

#[tauri::command]
pub fn delete_worktree_cmd(
    state: State<'_, AppState>,
    worktree_id: String,
) -> Result<(), AppError> {
    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;

    let wt = Worktree::get_by_id(&conn, &worktree_id)?;
    let ticket = ProcessedTicket::get_by_id(&conn, &wt.ticket_id)?;
    let tracker = WatchedTracker::get_by_id(&conn, &ticket.tracker_id)?;
    let project = Project::get_by_id(&conn, &tracker.project_id)?;

    drop(conn);

    worktree_manager::delete_worktree(&project.path, &wt.path, &wt.branch_name)
        .map_err(AppError::from)?;

    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
    Worktree::delete(&conn, &worktree_id)?;

    Ok(())
}

#[tauri::command]
pub fn list_local_branches(
    state: State<'_, AppState>,
    project_id: String,
) -> Result<Vec<String>, AppError> {
    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
    let project = Project::get_by_id(&conn, &project_id)?;

    drop(conn);

    let branches = worktree_manager::list_local_branches(&project.path).map_err(AppError::from)?;
    Ok(branches)
}
