use std::sync::Arc;

use soul_core::tool::Tool;

use crate::auth::GoogleAuth;
use crate::client::GoogleApiClient;
use crate::tools::*;

/// All 7 Google tools: Calendar (2) + Gmail (2) + Sheets (3)
pub fn all_tools(auth: Arc<dyn GoogleAuth>) -> Vec<Box<dyn Tool>> {
    let client = Arc::new(GoogleApiClient::new(auth));
    vec![
        Box::new(CalendarListTool::new(client.clone())),
        Box::new(CalendarCreateTool::new(client.clone())),
        Box::new(GmailSearchTool::new(client.clone())),
        Box::new(GmailReadTool::new(client.clone())),
        Box::new(SheetsReadTool::new(client.clone())),
        Box::new(SheetsWriteTool::new(client.clone())),
        Box::new(SheetsAppendTool::new(client)),
    ]
}

/// Calendar tools only: list + create events
pub fn calendar_tools(auth: Arc<dyn GoogleAuth>) -> Vec<Box<dyn Tool>> {
    let client = Arc::new(GoogleApiClient::new(auth));
    vec![
        Box::new(CalendarListTool::new(client.clone())),
        Box::new(CalendarCreateTool::new(client)),
    ]
}

/// Gmail tools only: search + read messages
pub fn gmail_tools(auth: Arc<dyn GoogleAuth>) -> Vec<Box<dyn Tool>> {
    let client = Arc::new(GoogleApiClient::new(auth));
    vec![
        Box::new(GmailSearchTool::new(client.clone())),
        Box::new(GmailReadTool::new(client)),
    ]
}

/// Sheets tools only: read + write + append
pub fn sheets_tools(auth: Arc<dyn GoogleAuth>) -> Vec<Box<dyn Tool>> {
    let client = Arc::new(GoogleApiClient::new(auth));
    vec![
        Box::new(SheetsReadTool::new(client.clone())),
        Box::new(SheetsWriteTool::new(client.clone())),
        Box::new(SheetsAppendTool::new(client)),
    ]
}

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

    fn mock_auth() -> Arc<dyn GoogleAuth> {
        Arc::new(MockGoogleAuth::new("test-token"))
    }

    #[test]
    fn all_tools_returns_seven() {
        let tools = all_tools(mock_auth());
        assert_eq!(tools.len(), 7);
    }

    #[test]
    fn calendar_tools_returns_two() {
        let tools = calendar_tools(mock_auth());
        assert_eq!(tools.len(), 2);
        assert_eq!(tools[0].name(), "google_calendar_list");
        assert_eq!(tools[1].name(), "google_calendar_create");
    }

    #[test]
    fn gmail_tools_returns_two() {
        let tools = gmail_tools(mock_auth());
        assert_eq!(tools.len(), 2);
        assert_eq!(tools[0].name(), "google_gmail_search");
        assert_eq!(tools[1].name(), "google_gmail_read");
    }

    #[test]
    fn sheets_tools_returns_three() {
        let tools = sheets_tools(mock_auth());
        assert_eq!(tools.len(), 3);
        assert_eq!(tools[0].name(), "google_sheets_read");
        assert_eq!(tools[1].name(), "google_sheets_write");
        assert_eq!(tools[2].name(), "google_sheets_append");
    }

    #[test]
    fn all_tools_have_non_empty_schemas() {
        let tools = all_tools(mock_auth());
        for tool in &tools {
            let def = tool.definition();
            assert!(!def.name.is_empty(), "Tool name should not be empty");
            assert!(!def.description.is_empty(), "Tool {} description should not be empty", def.name);
            assert_eq!(def.input_schema["type"], "object", "Tool {} schema should be object type", def.name);
            assert!(def.input_schema["properties"].is_object(), "Tool {} should have properties", def.name);
        }
    }
}
