pub mod claude;

use std::fmt;
use std::str::FromStr;

use anyhow::{anyhow, Error};
use clap::ValueEnum;
use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum, Serialize, Deserialize)]
#[clap(rename_all = "lowercase")]
#[serde(rename_all = "lowercase")]
pub enum Tool {
    Claude,
    Codex,
    Cursor,
}

impl Tool {
    pub fn as_str(self) -> &'static str {
        match self {
            Tool::Claude => "claude",
            Tool::Codex => "codex",
            Tool::Cursor => "cursor",
        }
    }

    pub fn instructions_path(self) -> &'static str {
        match self {
            Tool::Claude => claude::INSTRUCTIONS_PATH,
            Tool::Codex => "AGENTS.md",
            Tool::Cursor => ".cursor/rules",
        }
    }

    #[allow(dead_code)] // used once `[[merge]]` blocks are wired up
    pub fn settings_path(self) -> Option<&'static str> {
        match self {
            Tool::Claude => Some(claude::SETTINGS_PATH),
            Tool::Codex => None,
            Tool::Cursor => None,
        }
    }
}

impl fmt::Display for Tool {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl FromStr for Tool {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "claude" => Ok(Tool::Claude),
            "codex" => Ok(Tool::Codex),
            "cursor" => Ok(Tool::Cursor),
            other => Err(anyhow!("unknown tool '{other}' (claude|codex|cursor)")),
        }
    }
}
