use crate::error::AppError;
use crate::models::ticket::ProcessedTicket;
use crate::models::worktree::Worktree;
use crate::AppState;
use serde::Serialize;
use tauri::State;

#[derive(Debug, Clone, Serialize)]
pub struct TicketResult {
    pub ticket: ProcessedTicket,
    pub worktree: Option<Worktree>,
}

#[tauri::command]
pub fn get_ticket_result(
    state: State<'_, AppState>,
    ticket_id: String,
) -> Result<TicketResult, AppError> {
    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
    let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?;
    let worktree = Worktree::get_by_ticket_id(&conn, &ticket_id)?;
    Ok(TicketResult { ticket, worktree })
}

#[tauri::command]
pub fn retry_ticket(state: State<'_, AppState>, ticket_id: String) -> Result<(), AppError> {
    let active_worktree_cleanup: Option<(crate::models::worktree::Worktree, String)> = {
        let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
        let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?;

        if ticket.status != "Error" && ticket.status != "Done" && ticket.status != "Cancelled" {
            return Err(AppError::from(format!(
                "Cannot retry ticket with status '{}'",
                ticket.status
            )));
        }

        ProcessedTicket::update_status(&conn, &ticket_id, "Pending")?;
        conn.execute(
            "UPDATE processed_tickets SET analyst_report = NULL, developer_report = NULL, \
             worktree_path = NULL, branch_name = NULL, processed_at = NULL WHERE id = ?1",
            rusqlite::params![ticket_id],
        )?;

        let cleanup_target = if let Some(wt) = Worktree::get_by_ticket_id(&conn, &ticket_id)? {
            if wt.status == "Active" {
                let project = crate::models::project::Project::get_by_id(&conn, &ticket.project_id)?;
                Some((wt, project.path))
            } else {
                Some((wt, String::new()))
            }
        } else {
            None
        };

        cleanup_target
    };

    if let Some((wt, project_path)) = &active_worktree_cleanup {
        if wt.status == "Active" {
            let _ = crate::services::worktree_manager::delete_worktree(
                project_path,
                &wt.path,
                &wt.branch_name,
            );
        }
    }

    if let Some((wt, _)) = active_worktree_cleanup {
        let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
        Worktree::delete(&conn, &wt.id)?;
    }

    Ok(())
}

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

        if ticket.status == "Done" || ticket.status == "Cancelled" {
            return Err(AppError::from(format!(
                "Cannot cancel ticket with status '{}'",
                ticket.status
            )));
        }
    }

    state.process_registry.cancel_ticket(&ticket_id).await;

    let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?;
    let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?;
    if ticket.status == "Done" || ticket.status == "Cancelled" {
        return Err(AppError::from(format!(
            "Cannot cancel ticket with status '{}'",
            ticket.status
        )));
    }

    ProcessedTicket::update_status(&conn, &ticket_id, "Cancelled")?;
    Ok(())
}
