// SPDX-FileCopyrightText: 2024 Gleb Smirnov <glebsmirnov0708@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-or-later

use anyhow::Result;
use smol::fs;
use textpieces_core::{providers, Action, Actions, Parameter, ParameterType};

use crate::application::Application;

#[derive(Debug, serde::Deserialize)]
struct OldConfig {
    tools: Vec<Tool>,
}

#[derive(Debug, serde::Deserialize)]
struct Tool {
    name: String,
    description: String,
    script: String,
    args: Vec<String>,
}

/// Migrates tools from Text Pieces before 4.0 to new actions.
pub fn try_migrate() -> Result<()> {
    let home_dir = dirs::home_dir().expect("Failed to get home directory");

    let old_scripts_dir = home_dir.join(".local/share/textpieces/scripts");
    let old_config_path = dirs::config_dir()
        .expect("Failed to get configuration directory")
        .join("textpieces")
        .join("tools.json");

    if !old_config_path.exists() {
        tracing::info!("Old configuration path is not found, skipping migration");
        return Ok(());
    }

    smol::block_on(async {
        let old_config: OldConfig =
            serde_json::from_str(&fs::read_to_string(&old_config_path).await?)?;

        let mut actions =
            Actions::new(providers::Scripts::new(Application::script_dir(), None)).await?;
        let scripts = actions.provider();

        let new_scripts_dir = scripts.scripts_dir();

        if !new_scripts_dir.exists() {
            fs::create_dir_all(new_scripts_dir).await?;
        }

        for tool in old_config.tools {
            let action = Action {
                name: tool.name,
                description: tool.description,
                parameters: tool
                    .args
                    .into_iter()
                    .map(|arg| Parameter {
                        type_: ParameterType::String,
                        label: arg,
                    })
                    .collect(),
            };

            actions.add(&tool.script, action).await?;

            let old_path = old_scripts_dir.join(&tool.script);
            let new_path = scripts.script_file(&tool.script);

            if old_path != new_path {
                fs::copy(&old_path, &new_path).await?;
                fs::remove_file(old_path).await?;
            }
        }

        fs::remove_file(old_config_path).await?;

        Ok(())
    })
}
