use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use tauri::AppHandle;
use tauri_plugin_store::StoreExt;

const QUICK_ACTIONS_STORE_KEY: &str = "quick_actions";

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuickAction {
    pub id: String,
    pub name: String,
    pub prompt: String,
    pub icon: String,
    pub is_default: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

fn get_default_quick_actions() -> Vec<QuickAction> {
    let now = Utc::now();
    vec![
        QuickAction {
            id: "default-review-pr".to_string(),
            name: "Review PR".to_string(),
            prompt: "Please review this pull request and provide feedback on code quality, potential issues, and suggestions for improvement.".to_string(),
            icon: "git-pull-request".to_string(),
            is_default: true,
            created_at: now,
            updated_at: now,
        },
        QuickAction {
            id: "default-run-tests".to_string(),
            name: "Run Tests".to_string(),
            prompt: "Please run the test suite for this project and report any failures or issues.".to_string(),
            icon: "play".to_string(),
            is_default: true,
            created_at: now,
            updated_at: now,
        },
        QuickAction {
            id: "default-explain-file".to_string(),
            name: "Explain File".to_string(),
            prompt: "Please explain what this file does, its purpose, and how it fits into the overall project structure.".to_string(),
            icon: "file-text".to_string(),
            is_default: true,
            created_at: now,
            updated_at: now,
        },
        QuickAction {
            id: "default-fix-error".to_string(),
            name: "Fix Error".to_string(),
            prompt: "I'm getting an error. Can you help me identify the cause and fix it?".to_string(),
            icon: "alert-circle".to_string(),
            is_default: true,
            created_at: now,
            updated_at: now,
        },
        QuickAction {
            id: "default-write-tests".to_string(),
            name: "Write Tests".to_string(),
            prompt: "Please write comprehensive unit tests for the current code with good coverage.".to_string(),
            icon: "check-square".to_string(),
            is_default: true,
            created_at: now,
            updated_at: now,
        },
        QuickAction {
            id: "default-refactor".to_string(),
            name: "Refactor".to_string(),
            prompt: "Please refactor this code to improve readability, maintainability, and performance.".to_string(),
            icon: "refresh-cw".to_string(),
            is_default: true,
            created_at: now,
            updated_at: now,
        },
    ]
}

fn load_all_quick_actions(app: &AppHandle) -> Result<Vec<QuickAction>, String> {
    let store = app
        .store("hikari-quick-actions.json")
        .map_err(|e| e.to_string())?;

    match store.get(QUICK_ACTIONS_STORE_KEY) {
        Some(value) => {
            let mut actions: Vec<QuickAction> =
                serde_json::from_value(value.clone()).map_err(|e| e.to_string())?;

            let defaults = get_default_quick_actions();
            for default in defaults {
                if !actions.iter().any(|a| a.id == default.id) {
                    actions.push(default);
                }
            }

            Ok(actions)
        }
        None => Ok(get_default_quick_actions()),
    }
}

fn save_all_quick_actions(app: &AppHandle, actions: &[QuickAction]) -> Result<(), String> {
    let store = app
        .store("hikari-quick-actions.json")
        .map_err(|e| e.to_string())?;

    let value = serde_json::to_value(actions).map_err(|e| e.to_string())?;
    store.set(QUICK_ACTIONS_STORE_KEY, value);
    store.save().map_err(|e| e.to_string())?;

    Ok(())
}

#[tauri::command]
pub async fn list_quick_actions(app: AppHandle) -> Result<Vec<QuickAction>, String> {
    let mut actions = load_all_quick_actions(&app)?;

    actions.sort_by(|a, b| {
        let default_cmp = b.is_default.cmp(&a.is_default);
        if default_cmp == std::cmp::Ordering::Equal {
            a.name.cmp(&b.name)
        } else {
            default_cmp
        }
    });

    Ok(actions)
}

#[tauri::command]
pub async fn save_quick_action(app: AppHandle, action: QuickAction) -> Result<(), String> {
    let mut actions = load_all_quick_actions(&app)?;

    if let Some(existing) = actions.iter_mut().find(|a| a.id == action.id) {
        let mut updated = action;
        updated.is_default = existing.is_default;
        *existing = updated;
    } else {
        actions.push(action);
    }

    save_all_quick_actions(&app, &actions)
}

#[tauri::command]
pub async fn delete_quick_action(app: AppHandle, action_id: String) -> Result<(), String> {
    let mut actions = load_all_quick_actions(&app)?;

    if actions
        .iter()
        .any(|a| a.id == action_id && a.is_default)
    {
        return Err("Cannot delete default quick actions".to_string());
    }

    actions.retain(|a| a.id != action_id);
    save_all_quick_actions(&app, &actions)
}

#[tauri::command]
pub async fn reset_default_quick_actions(app: AppHandle) -> Result<(), String> {
    let mut actions = load_all_quick_actions(&app)?;

    actions.retain(|a| !a.is_default);
    actions.extend(get_default_quick_actions());

    save_all_quick_actions(&app, &actions)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_default_quick_actions_exist() {
        let defaults = get_default_quick_actions();
        assert!(!defaults.is_empty());
        assert!(defaults.iter().all(|a| a.is_default));
    }

    #[test]
    fn test_default_quick_actions_have_required_fields() {
        let defaults = get_default_quick_actions();
        for action in defaults {
            assert!(!action.id.is_empty());
            assert!(!action.name.is_empty());
            assert!(!action.prompt.is_empty());
            assert!(!action.icon.is_empty());
        }
    }
}
