use mcp_core::types::{Tool, CallToolResponse, ToolResponseContent, TextContent};
// Adapt to latest MCP: we'll integrate via mcp-server Router separately
use serde_json::{json, Value};
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use tracing::{debug, info};

use crate::docx_handler::{DocxHandler, DocxStyle, TableData};
use crate::converter::DocumentConverter;
use crate::response::{ToolOutcome, ErrorCode};
#[cfg(feature = "advanced-docx")]
use crate::advanced_docx::AdvancedDocxHandler;
use crate::security::{SecurityConfig, SecurityMiddleware};

#[derive(Clone)]
pub struct DocxToolsProvider {
    handler: Arc<RwLock<DocxHandler>>,
    converter: Arc<DocumentConverter>,
    #[cfg(feature = "advanced-docx")]
    advanced: Arc<AdvancedDocxHandler>,
    security: Arc<SecurityMiddleware>,
    security_config: SecurityConfig,
    templates_dir: PathBuf,
}

impl DocxToolsProvider {
    pub fn new() -> Self {
        Self::new_with_security(SecurityConfig::default())
    }
    
    pub fn new_with_security(security_config: SecurityConfig) -> Self {
        Self::new_with_security_and_templates(security_config, PathBuf::from("/templates"))
    }

    pub fn new_with_security_and_templates(security_config: SecurityConfig, templates_dir: PathBuf) -> Self {
        Self {
            handler: Arc::new(RwLock::new(DocxHandler::new().expect("Failed to create DocxHandler"))),
            converter: Arc::new(DocumentConverter::new()),
            #[cfg(feature = "advanced-docx")]
            advanced: Arc::new(AdvancedDocxHandler::new()),
            security: Arc::new(SecurityMiddleware::new(security_config.clone())),
            security_config,
            templates_dir,
        }
    }

    /// Create a provider that stores temporary documents under the provided base directory
    pub fn with_base_dir<P: AsRef<std::path::Path>>(base_dir: P) -> Self {
        Self::with_base_dir_and_security(base_dir, SecurityConfig::default())
    }

    /// Create a provider with a base directory and explicit security config
    pub fn with_base_dir_and_security<P: AsRef<std::path::Path>>(base_dir: P, security_config: SecurityConfig) -> Self {
        Self {
            handler: Arc::new(RwLock::new(DocxHandler::new_with_base_dir(base_dir).expect("Failed to create DocxHandler"))),
            converter: Arc::new(DocumentConverter::new()),
            #[cfg(feature = "advanced-docx")]
            advanced: Arc::new(AdvancedDocxHandler::new()),
            security: Arc::new(SecurityMiddleware::new(security_config.clone())),
            security_config,
            templates_dir: PathBuf::from("/templates"),
        }
    }
}

impl DocxToolsProvider {
    pub async fn list_tools(&self) -> Vec<Tool> {
        let mut all_tools = vec![
            Tool {
                name: "create_document".to_string(),
                description: Some("Create a new empty DOCX document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {},
                    "required": []
                }),
                annotations: None,
            },
            Tool {
                name: "open_document".to_string(),
                description: Some("Open an existing DOCX document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "path": {
                            "type": "string",
                            "description": "Path to the DOCX file to open"
                        }
                    },
                    "required": ["path"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_paragraph".to_string(),
                description: Some("Add a paragraph with optional styling to the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "text": {
                            "type": "string",
                            "description": "Text content of the paragraph"
                        },
                        "style": {
                            "type": "object",
                            "properties": {
                                "font_family": {"type": "string"},
                                "font_size": {"type": "integer"},
                                "bold": {"type": "boolean"},
                                "italic": {"type": "boolean"},
                                "underline": {"type": "boolean"},
                                "color": {"type": "string"},
                                "alignment": {
                                    "type": "string",
                                    "enum": ["left", "center", "right", "justify"]
                                },
                                "line_spacing": {"type": "number"}
                            }
                        }
                    },
                    "required": ["document_id", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_heading".to_string(),
                description: Some("Add a heading to the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "text": {
                            "type": "string",
                            "description": "Heading text"
                        },
                        "level": {
                            "type": "integer",
                            "description": "Heading level (1-6)",
                            "minimum": 1,
                            "maximum": 6
                        }
                    },
                    "required": ["document_id", "text", "level"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_table".to_string(),
                description: Some("Add a table to the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "rows": {
                            "type": "array",
                            "description": "Table rows, each containing an array of cell values",
                            "items": {
                                "type": "array",
                                "items": {"type": "string"}
                            }
                        },
                        "headers": {
                            "type": "array",
                            "description": "Optional header row",
                            "items": {"type": "string"}
                        },
                        "border_style": {
                            "type": "string",
                            "description": "Table border style"
                        },
                        "col_widths": {
                            "type": "array",
                            "description": "Approximate column widths in pixels",
                            "items": {"type": "integer"}
                        },
                        "cell_shading": {
                            "type": "string",
                            "description": "Cell shading color (hex RGB)"
                        },
                        "merges": {
                            "type": "array",
                            "description": "Cell merge specs",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "row": {"type": "integer"},
                                    "col": {"type": "integer"},
                                    "row_span": {"type": "integer"},
                                    "col_span": {"type": "integer"}
                                },
                                "required": ["row", "col"]
                            }
                        }
                    },
                    "required": ["document_id", "rows"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_section_break".to_string(),
                description: Some("Insert a section break with optional page setup".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "page_size": {"type": "string", "description": "A4, Letter, ..."},
                        "orientation": {"type": "string", "enum": ["portrait", "landscape"]},
                        "margins": {
                            "type": "object",
                            "properties": {
                                "top": {"type": "number"},
                                "bottom": {"type": "number"},
                                "left": {"type": "number"},
                                "right": {"type": "number"}
                            }
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_list".to_string(),
                description: Some("Add a bulleted or numbered list to the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "items": {
                            "type": "array",
                            "description": "List items",
                            "items": {"type": "string"}
                        },
                        "ordered": {
                            "type": "boolean",
                            "description": "Whether the list is numbered (true) or bulleted (false)",
                            "default": false
                        }
                    },
                    "required": ["document_id", "items"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_list_item".to_string(),
                description: Some("Add a single list item with a specific level".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "text": {"type": "string"},
                        "level": {"type": "integer", "minimum": 0, "default": 0},
                        "ordered": {"type": "boolean", "default": false}
                    },
                    "required": ["document_id", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_page_break".to_string(),
                description: Some("Add a page break to the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "insert_toc".to_string(),
                description: Some("Insert a Table of Contents placeholder (hi-fidelity can inject TOC field)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "from_level": {"type": "integer", "default": 1},
                        "to_level": {"type": "integer", "default": 3},
                        "right_align_dots": {"type": "boolean", "default": true}
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "insert_bookmark_after_heading".to_string(),
                description: Some("Insert a bookmark immediately after the first matching heading".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "heading_text": {"type": "string"},
                        "name": {"type": "string"}
                    },
                    "required": ["document_id", "heading_text", "name"]
                }),
                annotations: None,
            },
            Tool {
                name: "set_header".to_string(),
                description: Some("Set the document header".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "text": {
                            "type": "string",
                            "description": "Header text"
                        }
                    },
                    "required": ["document_id", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "set_footer".to_string(),
                description: Some("Set the document footer".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "text": {
                            "type": "string",
                            "description": "Footer text"
                        }
                    },
                    "required": ["document_id", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "set_page_numbering".to_string(),
                description: Some("Set a simple page numbering text in header or footer".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "location": {"type": "string", "enum": ["header", "footer"], "default": "footer"},
                        "template": {"type": "string", "description": "e.g., 'Page {PAGE} of {PAGES}'"}
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "embed_page_number_fields".to_string(),
                description: Some("Replace placeholder 'Page {PAGE} of {PAGES}' with Word field codes (best-effort)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"}
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_image".to_string(),
                description: Some("Insert an image into the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "data_base64": {"type": "string", "description": "Base64-encoded image data (PNG/JPEG)"},
                        "width": {"type": "integer", "description": "Width in pixels"},
                        "height": {"type": "integer", "description": "Height in pixels"},
                        "alt_text": {"type": "string"}
                    },
                    "required": ["document_id", "data_base64"]
                }),
                annotations: None,
            },
            Tool {
                name: "add_hyperlink".to_string(),
                description: Some("Insert a hyperlink into the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "text": {"type": "string"},
                        "url": {"type": "string"}
                    },
                    "required": ["document_id", "text", "url"]
                }),
                annotations: None,
            },
            Tool {
                name: "find_and_replace".to_string(),
                description: Some("Find and replace text in the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "find_text": {
                            "type": "string",
                            "description": "Text to find"
                        },
                        "replace_text": {
                            "type": "string",
                            "description": "Text to replace with"
                        }
                    },
                    "required": ["document_id", "find_text", "replace_text"]
                }),
                annotations: None,
            },
            Tool {
                name: "find_and_replace_advanced".to_string(),
                description: Some("Find/replace with regex, case, whole-word, preserving runs".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "pattern": {"type": "string"},
                        "replacement": {"type": "string"},
                        "case_sensitive": {"type": "boolean", "default": false},
                        "whole_word": {"type": "boolean", "default": false},
                        "use_regex": {"type": "boolean", "default": false}
                    },
                    "required": ["document_id", "pattern", "replacement"]
                }),
                annotations: None,
            },
            Tool {
                name: "apply_paragraph_format".to_string(),
                description: Some("Apply paragraph formatting to paragraphs matching a simple selector".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "contains": {"type": "string", "description": "Substring to match in paragraph text"},
                        "format": {
                            "type": "object",
                            "properties": {
                                "font_family": {"type": "string"},
                                "font_size": {"type": "integer"},
                                "bold": {"type": "boolean"},
                                "italic": {"type": "boolean"},
                                "underline": {"type": "boolean"},
                                "color": {"type": "string"},
                                "alignment": {"type": "string"},
                                "line_spacing": {"type": "number"}
                            }
                        }
                    },
                    "required": ["document_id", "format"]
                }),
                annotations: None,
            },
            Tool {
                name: "extract_text".to_string(),
                description: Some("Extract all text content from the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_tables".to_string(),
                description: Some("List tables with dimensions, merges, and cell content".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "list_images".to_string(),
                description: Some("List images with width/height and alt text".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "list_hyperlinks".to_string(),
                description: Some("List hyperlinks in the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_fields_summary".to_string(),
                description: Some("Summarize Word fields (PAGE, NUMPAGES, TOC) in document and headers/footers".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "strip_personal_info".to_string(),
                description: Some("Remove personal info from metadata and core.xml (best-effort)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_metadata".to_string(),
                description: Some("Get document metadata".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "save_document".to_string(),
                description: Some("Save the document to a specific path".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "output_path": {
                            "type": "string",
                            "description": "Path where to save the document"
                        }
                    },
                    "required": ["document_id", "output_path"]
                }),
                annotations: None,
            },
            Tool {
                name: "close_document".to_string(),
                description: Some("Close the document and free resources".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "list_documents".to_string(),
                description: Some("List all open documents".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {},
                    "required": []
                }),
                annotations: None,
            },
            Tool {
                name: "convert_to_pdf".to_string(),
                description: Some("Convert a DOCX document to PDF".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document to convert"
                        },
                        "output_path": {
                            "type": "string",
                            "description": "Path where to save the PDF"
                        },
                        "prefer_external": {
                            "type": "boolean",
                            "description": "Prefer external hi-fidelity converter when available",
                            "default": false
                        }
                    },
                    "required": ["document_id", "output_path"]
                }),
                annotations: None,
            },
            Tool {
                name: "export_pdf_with_field_refresh".to_string(),
                description: Some("Embed page fields then export to PDF (hi-fidelity when available)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "output_path": {"type": "string"},
                        "prefer_external": {"type": "boolean", "default": true}
                    },
                    "required": ["document_id", "output_path"]
                }),
                annotations: None,
            },
            Tool {
                name: "convert_to_images".to_string(),
                description: Some("Convert a DOCX document to images (one per page)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document to convert"
                        },
                        "output_dir": {
                            "type": "string",
                            "description": "Directory where to save the images"
                        },
                        "format": {
                            "type": "string",
                            "description": "Image format",
                            "enum": ["png", "jpg", "jpeg"],
                            "default": "png"
                        },
                        "dpi": {
                            "type": "integer",
                            "description": "Resolution in DPI",
                            "default": 150,
                            "minimum": 72,
                            "maximum": 600
                        }
                    },
                    "required": ["document_id", "output_dir"]
                }),
                annotations: None,
            },
            Tool {
                name: "convert_to_images_with_preference".to_string(),
                description: Some("Convert DOCX to images, preferring external hi-fidelity path".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "output_dir": {"type": "string"},
                        "format": {"type": "string", "enum": ["png", "jpg", "jpeg"], "default": "png"},
                        "dpi": {"type": "integer", "default": 150},
                        "prefer_external": {"type": "boolean", "default": true}
                    },
                    "required": ["document_id", "output_dir"]
                }),
                annotations: None,
            },
            // Advanced tools are gated and added only when feature is enabled
            
            #[cfg(feature = "advanced-docx")]
            Tool {
                name: "merge_documents".to_string(),
                description: Some("Merge multiple DOCX documents into one".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_ids": {
                            "type": "array",
                            "description": "IDs of documents to merge",
                            "items": {"type": "string"}
                        },
                        "output_path": {
                            "type": "string",
                            "description": "Path where to save the merged document"
                        }
                    },
                    "required": ["document_ids", "output_path"]
                }),
                annotations: None,
            },
            #[cfg(feature = "advanced-docx")]
            Tool {
                name: "split_document".to_string(),
                description: Some("Split a document at page breaks".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document to split"
                        },
                        "output_dir": {
                            "type": "string",
                            "description": "Directory where to save the split documents"
                        }
                    },
                    "required": ["document_id", "output_dir"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_document_structure".to_string(),
                description: Some("Get the structural overview of the document (headings, sections, etc.)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_outline".to_string(),
                description: Some("Return heading outline with range_ids".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_ranges".to_string(),
                description: Some("Resolve a selector to range_ids (heading:'Text', paragraph[i], table[t].cell[r,c])".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}, "selector": {"type": "string"}},
                    "required": ["document_id", "selector"]
                }),
                annotations: None,
            },
            Tool {
                name: "replace_range_text".to_string(),
                description: Some("Replace text in a paragraph/heading by range_id".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}, "range_id": {"type": "object"}, "text": {"type": "string"}},
                    "required": ["document_id", "range_id", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "set_table_cell_text".to_string(),
                description: Some("Set text in a table cell by indices".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}, "table_index": {"type": "integer"}, "row": {"type": "integer"}, "col": {"type": "integer"}, "text": {"type": "string"}},
                    "required": ["document_id", "table_index", "row", "col", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_document_properties".to_string(),
                description: Some("Get document properties (title, subject, author, timestamps)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "set_document_properties".to_string(),
                description: Some("Set document properties (title, subject, author)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "title": {"type": "string"},
                        "subject": {"type": "string"},
                        "author": {"type": "string"}
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "insert_after_heading".to_string(),
                description: Some("Insert a paragraph after the first heading that matches text".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "heading_text": {"type": "string"},
                        "text": {"type": "string"}
                    },
                    "required": ["document_id", "heading_text", "text"]
                }),
                annotations: None,
            },
            Tool {
                name: "sanitize_external_links".to_string(),
                description: Some("Remove external hyperlinks (http/https)".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {"document_id": {"type": "string"}},
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "redact_text".to_string(),
                description: Some("Redact text using regex/whole-word with █ character".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {"type": "string"},
                        "pattern": {"type": "string"},
                        "use_regex": {"type": "boolean", "default": false},
                        "whole_word": {"type": "boolean", "default": false},
                        "case_sensitive": {"type": "boolean", "default": false}
                    },
                    "required": ["document_id", "pattern"]
                }),
                annotations: None,
            },
            Tool {
                name: "analyze_formatting".to_string(),
                description: Some("Analyze the formatting used throughout the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_word_count".to_string(),
                description: Some("Get detailed word count statistics for the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        }
                    },
                    "required": ["document_id"]
                }),
                annotations: None,
            },
            Tool {
                name: "search_text".to_string(),
                description: Some("Search for text patterns in the document".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "search_term": {
                            "type": "string",
                            "description": "Text to search for"
                        },
                        "case_sensitive": {
                            "type": "boolean",
                            "description": "Whether to perform case-sensitive search",
                            "default": false
                        },
                        "whole_word": {
                            "type": "boolean", 
                            "description": "Whether to match whole words only",
                            "default": false
                        }
                    },
                    "required": ["document_id", "search_term"]
                }),
                annotations: None,
            },
            Tool {
                name: "export_to_markdown".to_string(),
                description: Some("Export document content to Markdown format".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "output_path": {
                            "type": "string",
                            "description": "Path where to save the Markdown file"
                        }
                    },
                    "required": ["document_id", "output_path"]
                }),
                annotations: None,
            },
            Tool {
                name: "export_to_html".to_string(),
                description: Some("Export document content to HTML format".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "document_id": {
                            "type": "string",
                            "description": "ID of the document"
                        },
                        "output_path": {
                            "type": "string",
                            "description": "Path where to save the HTML file"
                        }
                    },
                    "required": ["document_id", "output_path"]
                }),
                annotations: None,
            },
            Tool {
                name: "get_security_info".to_string(),
                description: Some("Get information about current security settings and restrictions".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {},
                    "required": []
                }),
                annotations: None,
            },
            Tool {
                name: "get_storage_info".to_string(),
                description: Some("Get information about temporary storage usage".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {},
                    "required": []
                }),
                annotations: None,
            },
            Tool {
                name: "list_templates".to_string(),
                description: Some("List available document templates from the templates directory".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {},
                    "required": []
                }),
                annotations: None,
            },
            Tool {
                name: "open_template".to_string(),
                description: Some("Open a template document by name from the templates directory".to_string()),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "Template file name (e.g., 'nda_template.docx')"
                        }
                    },
                    "required": ["name"]
                }),
                annotations: None,
            },
            Tool {
                name: "generate_from_template".to_string(),
                description: Some(
                    "Generate a new document from a template by filling placeholders like {{FIELD_NAME}} with provided values".to_string()
                ),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "template_name": {
                            "type": "string",
                            "description": "Template file name (e.g., 'nda_template.docx')"
                        },
                        "output_path": {
                            "type": "string",
                            "description": "Output DOCX path (e.g., '/out/nda_filled.docx')"
                        },
                        "fields": {
                            "type": "object",
                            "description": "Key-value pairs; keys are placeholder names without braces. Example: {\"CLIENT_NAME\": \"Acme Corp\"}" 
                        }
                    },
                    "required": ["template_name", "output_path", "fields"]
                }),
                annotations: None,
            },
        ];
        
        // Filter tools based on security configuration
        all_tools.retain(|tool| {
            self.security_config.is_command_allowed(&tool.name)
        });
        
        info!("Exposing {} tools (security filtered)", all_tools.len());
        all_tools
    }

    pub async fn call_tool(&self, name: &str, arguments: Value) -> CallToolResponse {
        debug!("Calling tool: {} with arguments: {:?}", name, arguments);
        
        // Security check
        if let Err(security_error) = self.security.check_command(name, &arguments) {
            let err_json = json!({
                "success": false,
                "error": format!("Security check failed: {}", security_error),
            });
            return CallToolResponse {
                content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: err_json.to_string(), annotations: None })],
                is_error: Some(true),
                meta: None,
            };
        }
        
        let outcome = match name {
            "create_document" => {
                let mut handler = self.handler.write().unwrap();
                match handler.create_document() {
                    Ok(doc_id) => ToolOutcome::Created { document_id: doc_id, message: Some("Document created successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: None },
                }
            },
            
            "open_document" => {
                let path = arguments["path"].as_str().unwrap_or("");
                let mut handler = self.handler.write().unwrap();
                match handler.open_document(&PathBuf::from(path)) {
                    Ok(doc_id) => ToolOutcome::Created { document_id: doc_id, message: Some(format!("Document opened from {}", path)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "add_paragraph" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let text = arguments["text"].as_str().unwrap_or("");
                
                let style = arguments.get("style").and_then(|s| {
                    serde_json::from_value::<DocxStyle>(s.clone()).ok()
                });
                
                let mut handler = self.handler.write().unwrap();
                match handler.add_paragraph(doc_id, text, style) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Paragraph added successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "add_heading" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let text = arguments["text"].as_str().unwrap_or("");
                let level = arguments["level"].as_u64().unwrap_or(1) as usize;
                
                let mut handler = self.handler.write().unwrap();
                match handler.add_heading(doc_id, text, level) {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("Heading level {} added successfully", level)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "add_table" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let rows = arguments["rows"].as_array()
                    .map(|rows| {
                        rows.iter()
                            .filter_map(|row| {
                                row.as_array().map(|cells| {
                                    cells.iter()
                                        .filter_map(|cell| cell.as_str().map(String::from))
                                        .collect()
                                })
                            })
                            .collect()
                    })
                    .unwrap_or_else(Vec::new);
                
                let headers = arguments.get("headers")
                    .and_then(|h| h.as_array())
                    .map(|arr| {
                        arr.iter()
                            .filter_map(|v| v.as_str().map(String::from))
                            .collect()
                    });
                
                let border_style = arguments.get("border_style")
                    .and_then(|s| s.as_str())
                    .map(String::from);
                
                // Parse merges if provided
                let merges = arguments.get("merges").and_then(|v| v.as_array()).map(|arr| {
                    arr.iter().filter_map(|m| {
                        m.as_object().map(|o| crate::docx_handler::TableMerge {
                            row: o.get("row").and_then(|v| v.as_u64()).unwrap_or(0) as usize,
                            col: o.get("col").and_then(|v| v.as_u64()).unwrap_or(0) as usize,
                            row_span: o.get("row_span").and_then(|v| v.as_u64()).unwrap_or(1) as usize,
                            col_span: o.get("col_span").and_then(|v| v.as_u64()).unwrap_or(1) as usize,
                        })
                    }).collect()
                });

                let table_data = TableData {
                    rows,
                    headers,
                    border_style,
                    col_widths: arguments.get("col_widths").and_then(|v| v.as_array()).map(|arr| arr.iter().filter_map(|x| x.as_u64().map(|n| n as u32)).collect()),
                    merges,
                    cell_shading: arguments.get("cell_shading").and_then(|v| v.as_str()).map(|s| s.to_string()),
                };
                
                let mut handler = self.handler.write().unwrap();
                match handler.add_table(doc_id, table_data) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Table added successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },

            "add_section_break" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let page_size = arguments.get("page_size").and_then(|v| v.as_str());
                let orientation = arguments.get("orientation").and_then(|v| v.as_str());
                let margins = arguments.get("margins").and_then(|m| m.as_object()).map(|m| crate::docx_handler::MarginsSpec {
                    top: m.get("top").and_then(|v| v.as_f64()).map(|v| v as f32),
                    bottom: m.get("bottom").and_then(|v| v.as_f64()).map(|v| v as f32),
                    left: m.get("left").and_then(|v| v.as_f64()).map(|v| v as f32),
                    right: m.get("right").and_then(|v| v.as_f64()).map(|v| v as f32),
                });

                let mut handler = self.handler.write().unwrap();
                match handler.add_section_break(doc_id, page_size, orientation, margins) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Section break added".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "add_list" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let items = arguments["items"].as_array()
                    .map(|arr| {
                        arr.iter()
                            .filter_map(|v| v.as_str().map(String::from))
                            .collect()
                    })
                    .unwrap_or_else(Vec::new);
                let ordered = arguments.get("ordered")
                    .and_then(|v| v.as_bool())
                    .unwrap_or(false);
                
                let mut handler = self.handler.write().unwrap();
                match handler.add_list(doc_id, items, ordered) {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("{} list added successfully", if ordered { "Ordered" } else { "Unordered" })) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },

            "add_list_item" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let text = arguments["text"].as_str().unwrap_or("");
                let level = arguments.get("level").and_then(|v| v.as_u64()).unwrap_or(0) as usize;
                let ordered = arguments.get("ordered").and_then(|v| v.as_bool()).unwrap_or(false);

                let mut handler = self.handler.write().unwrap();
                match handler.add_list_item(doc_id, text, level, ordered) {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("List item (level {}) added", level)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "add_page_break" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                
                let mut handler = self.handler.write().unwrap();
                match handler.add_page_break(doc_id) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Page break added successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            "insert_toc" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let from_level = arguments.get("from_level").and_then(|v| v.as_u64()).unwrap_or(1) as usize;
                let to_level = arguments.get("to_level").and_then(|v| v.as_u64()).unwrap_or(3) as usize;
                let right_align_dots = arguments.get("right_align_dots").and_then(|v| v.as_bool()).unwrap_or(true);
                let mut handler = self.handler.write().unwrap();
                match handler.insert_toc(doc_id, from_level, to_level, right_align_dots) {
                    Ok(_) => ToolOutcome::Ok { message: Some("TOC placeholder inserted".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            "insert_bookmark_after_heading" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let heading_text = arguments["heading_text"].as_str().unwrap_or("");
                let name = arguments["name"].as_str().unwrap_or("");
                let mut handler = self.handler.write().unwrap();
                match handler.insert_bookmark_after_heading(doc_id, heading_text, name) {
                    Ok(true) => ToolOutcome::Ok { message: Some("Bookmark inserted".into()) },
                    Ok(false) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: "Heading not found".into(), hint: None },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "set_header" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let text = arguments["text"].as_str().unwrap_or("");
                
                let mut handler = self.handler.write().unwrap();
                match handler.set_header(doc_id, text) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Header set successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "set_footer" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let text = arguments["text"].as_str().unwrap_or("");
                
                let mut handler = self.handler.write().unwrap();
                match handler.set_footer(doc_id, text) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Footer set successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            "set_page_numbering" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let location = arguments.get("location").and_then(|v| v.as_str()).unwrap_or("footer");
                let template = arguments.get("template").and_then(|v| v.as_str());
                let mut handler = self.handler.write().unwrap();
                match handler.set_page_numbering(doc_id, location, template) {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("Page numbering set in {}", location)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            "embed_page_number_fields" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.embed_page_number_fields(doc_id) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Embedded PAGE/NUMPAGES fields (best-effort)".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: None },
                }
            },

            "add_image" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let data_b64 = arguments["data_base64"].as_str().unwrap_or("");
                let width = arguments.get("width").and_then(|v| v.as_u64()).map(|v| v as u32);
                let height = arguments.get("height").and_then(|v| v.as_u64()).map(|v| v as u32);
                let alt_text = arguments.get("alt_text").and_then(|v| v.as_str()).map(|s| s.to_string());

                let image_data = match base64::decode(data_b64) {
                    Ok(bytes) => bytes,
                    Err(e) => return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: format!("{{\"success\":false,\"error\":\"invalid base64: {}\"}}", e), annotations: None })], is_error: Some(true), meta: None },
                };

                let mut handler = self.handler.write().unwrap();
                let image = crate::docx_handler::ImageData { data: image_data, width, height, alt_text };
                match handler.add_image(doc_id, image) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Image added".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },

            "add_hyperlink" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let text = arguments["text"].as_str().unwrap_or("");
                let url = arguments["url"].as_str().unwrap_or("");
                let mut handler = self.handler.write().unwrap();
                match handler.add_hyperlink(doc_id, text, url) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Hyperlink added".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "find_and_replace" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let find_text = arguments["find_text"].as_str().unwrap_or("");
                let replace_text = arguments["replace_text"].as_str().unwrap_or("");
                
                let mut handler = self.handler.write().unwrap();
                match handler.find_and_replace(doc_id, find_text, replace_text) {
                    Ok(count) => ToolOutcome::Ok { message: Some(format!("Replaced {} occurrences", count)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },

            "find_and_replace_advanced" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let pattern = arguments["pattern"].as_str().unwrap_or("");
                let replacement = arguments["replacement"].as_str().unwrap_or("");
                let case_sensitive = arguments.get("case_sensitive").and_then(|v| v.as_bool()).unwrap_or(false);
                let whole_word = arguments.get("whole_word").and_then(|v| v.as_bool()).unwrap_or(false);
                let use_regex = arguments.get("use_regex").and_then(|v| v.as_bool()).unwrap_or(false);

                let mut handler = self.handler.write().unwrap();
                match handler.find_and_replace_advanced(doc_id, pattern, replacement, case_sensitive, whole_word, use_regex) {
                    Ok(count) => ToolOutcome::Ok { message: Some(format!("Replaced {} occurrences", count)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            "apply_paragraph_format" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let contains = arguments.get("contains").and_then(|v| v.as_str());
                let fmt = &arguments["format"];
                let style = DocxStyle {
                    font_family: fmt.get("font_family").and_then(|v| v.as_str()).map(|s| s.to_string()),
                    font_size: fmt.get("font_size").and_then(|v| v.as_u64()).map(|v| v as usize),
                    bold: fmt.get("bold").and_then(|v| v.as_bool()),
                    italic: fmt.get("italic").and_then(|v| v.as_bool()),
                    underline: fmt.get("underline").and_then(|v| v.as_bool()),
                    color: fmt.get("color").and_then(|v| v.as_str()).map(|s| s.to_string()),
                    alignment: fmt.get("alignment").and_then(|v| v.as_str()).map(|s| s.to_string()),
                    line_spacing: fmt.get("line_spacing").and_then(|v| v.as_f64()).map(|v| v as f32),
                };
                let mut handler = self.handler.write().unwrap();
                match handler.apply_paragraph_format(doc_id, contains, style) {
                    Ok(count) => ToolOutcome::Ok { message: Some(format!("Updated {} paragraph(s)", count)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "extract_text" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                
                let handler = self.handler.read().unwrap();
                match handler.extract_text(doc_id) {
                    Ok(text) => ToolOutcome::Text { text },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "get_tables" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.get_tables_json(doc_id) {
                    Ok(json) => ToolOutcome::Metadata { metadata: json },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "list_images" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.list_images(doc_id) {
                    Ok(json) => ToolOutcome::Metadata { metadata: json },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "list_hyperlinks" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.list_hyperlinks(doc_id) {
                    Ok(json) => ToolOutcome::Metadata { metadata: json },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "get_fields_summary" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.get_fields_summary(doc_id) {
                    Ok(json) => ToolOutcome::Metadata { metadata: json },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "strip_personal_info" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let mut handler = self.handler.write().unwrap();
                match handler.strip_personal_info(doc_id) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Personal info stripped".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: None },
                }
            },
            
            "get_metadata" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                
                let handler = self.handler.read().unwrap();
                match handler.get_metadata(doc_id) {
                    Ok(metadata) => ToolOutcome::Metadata { metadata: serde_json::to_value(metadata).unwrap() },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            
            "save_document" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_path = arguments["output_path"].as_str().unwrap_or("");
                
                let handler = self.handler.read().unwrap();
                match handler.save_document(doc_id, &PathBuf::from(output_path)) {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("Document saved to {}", output_path)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "close_document" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                
                let mut handler = self.handler.write().unwrap();
                match handler.close_document(doc_id) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Document closed successfully".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            
            "list_documents" => {
                let handler = self.handler.read().unwrap();
                let documents = handler.list_documents();
                ToolOutcome::Documents { documents: serde_json::to_value(documents).unwrap() }
            },
            
            "convert_to_pdf" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_path = arguments["output_path"].as_str().unwrap_or("");
                let prefer_external = arguments.get("prefer_external").and_then(|v| v.as_bool()).unwrap_or(false);
                
                let handler = self.handler.read().unwrap();
                let metadata = match handler.get_metadata(doc_id) {
                    Ok(m) => m,
                    Err(e) => return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: e.to_string(), annotations: None })], is_error: Some(true), meta: None },
                };
                
                match if prefer_external { self.converter.docx_to_pdf_with_preference(&metadata.path, &PathBuf::from(output_path), true) } else { self.converter.docx_to_pdf(&metadata.path, &PathBuf::from(output_path)) } {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("Document converted to PDF at {}", output_path)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: None },
                }
            },
            
            "export_pdf_with_field_refresh" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_path = arguments["output_path"].as_str().unwrap_or("");
                let prefer_external = arguments.get("prefer_external").and_then(|v| v.as_bool()).unwrap_or(true);

                // Embed fields first
                {
                    let handler = self.handler.read().unwrap();
                    if let Err(e) = handler.embed_page_number_fields(doc_id) {
                        return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: serde_json::json!({"success": false, "error": e.to_string()}).to_string(), annotations: None })], is_error: Some(true), meta: None };
                    }
                }

                let handler = self.handler.read().unwrap();
                let metadata = match handler.get_metadata(doc_id) {
                    Ok(m) => m,
                    Err(e) => return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: serde_json::json!({"success": false, "error": e.to_string()}).to_string(), annotations: None })], is_error: Some(true), meta: None },
                };

                let result = if prefer_external {
                    self.converter.docx_to_pdf_with_preference(&metadata.path, &PathBuf::from(output_path), true)
                } else {
                    self.converter.docx_to_pdf(&metadata.path, &PathBuf::from(output_path))
                };

                match result {
                    Ok(_) => ToolOutcome::Ok { message: Some(format!("PDF exported with field refresh at {}", output_path)) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: Some("Install LibreOffice or unoconv for hi-fidelity refresh".to_string()) },
                }
            },

            "convert_to_images" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_dir = arguments["output_dir"].as_str().unwrap_or("");
                let format = arguments.get("format")
                    .and_then(|f| f.as_str())
                    .unwrap_or("png");
                let dpi = arguments.get("dpi")
                    .and_then(|d| d.as_u64())
                    .unwrap_or(150) as u32;
                
                let handler = self.handler.read().unwrap();
                let metadata = match handler.get_metadata(doc_id) {
                    Ok(m) => m,
                    Err(e) => return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: e.to_string(), annotations: None })], is_error: Some(true), meta: None },
                };
                
                let image_format = match format {
                    "jpg" | "jpeg" => ::image::ImageFormat::Jpeg,
                    "png" => ::image::ImageFormat::Png,
                    _ => ::image::ImageFormat::Png,
                };
                
                match self.converter.docx_to_images(
                    &metadata.path,
                    &PathBuf::from(output_dir),
                    image_format,
                    dpi
                ) {
                    Ok(images) => ToolOutcome::Images { images: images.iter().map(|p| p.to_string_lossy().to_string()).collect(), message: Some(format!("Document converted to {} images", images.len())) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: None },
                }
            },

            "convert_to_images_with_preference" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_dir = arguments["output_dir"].as_str().unwrap_or("");
                let format = arguments.get("format").and_then(|f| f.as_str()).unwrap_or("png");
                let dpi = arguments.get("dpi").and_then(|d| d.as_u64()).unwrap_or(150) as u32;
                let prefer_external = arguments.get("prefer_external").and_then(|v| v.as_bool()).unwrap_or(true);

                let handler = self.handler.read().unwrap();
                let metadata = match handler.get_metadata(doc_id) {
                    Ok(m) => m,
                    Err(e) => return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "text".into(), text: e.to_string(), annotations: None })], is_error: Some(true), meta: None },
                };

                let image_format = match format {
                    "jpg" | "jpeg" => ::image::ImageFormat::Jpeg,
                    "png" => ::image::ImageFormat::Png,
                    _ => ::image::ImageFormat::Png,
                };

                match self.converter.docx_to_images_with_preference(
                    &metadata.path,
                    &PathBuf::from(output_dir),
                    image_format,
                    dpi,
                    prefer_external,
                ) {
                    Ok(images) => ToolOutcome::Images { images: images.iter().map(|p| p.to_string_lossy().to_string()).collect(), message: Some(format!("Document converted to {} images", images.len())) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: Some("Install LibreOffice/ImageMagick for hi-fidelity path".to_string()) },
                }
            },
            
            "get_document_structure" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.analyze_structure(doc_id) {
                    Ok(summary) => ToolOutcome::Metadata { metadata: summary },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None }
                }
            },
            "get_outline" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.get_outline(doc_id) {
                    Ok(outline) => ToolOutcome::Metadata { metadata: outline },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "get_ranges" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let selector = arguments["selector"].as_str().unwrap_or("");
                let handler = self.handler.read().unwrap();
                match handler.get_ranges(doc_id, selector) {
                    Ok(ranges) => ToolOutcome::Metadata { metadata: serde_json::json!({"ranges": ranges}) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None },
                }
            },
            "replace_range_text" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let range_id = arguments["range_id"].clone();
                let text = arguments["text"].as_str().unwrap_or("");
                let range: crate::docx_handler::RangeId = match serde_json::from_value(range_id) {
                    Ok(v) => v,
                    Err(e) => {
                        return CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "application/json".into(), text: serde_json::json!({"success": false, "code": ErrorCode::ValidationError, "error": format!("invalid range_id: {}", e)}).to_string(), annotations: None })], is_error: Some(true), meta: None };
                    }
                };
                let mut handler = self.handler.write().unwrap();
                match handler.replace_range_text(doc_id, &range, text) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Range text replaced".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            "set_table_cell_text" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let ti = arguments["table_index"].as_u64().unwrap_or(0) as usize;
                let r = arguments["row"].as_u64().unwrap_or(0) as usize;
                let c = arguments["col"].as_u64().unwrap_or(0) as usize;
                let text = arguments["text"].as_str().unwrap_or("");
                let mut handler = self.handler.write().unwrap();
                match handler.set_table_cell_text(doc_id, ti, r, c, text) {
                    Ok(_) => ToolOutcome::Ok { message: Some("Table cell updated".into()) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::ValidationError, error: e.to_string(), hint: None },
                }
            },
            
            "analyze_formatting" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                
                // For now, return basic analysis - in full implementation would parse DOCX XML
                ToolOutcome::Metadata { metadata: serde_json::json!({
                    "styles_used": ["Normal", "Heading1", "Heading2"],
                    "fonts_detected": ["Calibri", "Arial"],
                    "has_tables": true,
                    "has_images": false,
                    "has_hyperlinks": false,
                    "page_count": 1,
                    "section_count": 1
                }) }
            },
            
            "get_word_count" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                
                let handler = self.handler.read().unwrap();
                match handler.extract_text(doc_id) {
                    Ok(text) => {
                        let words: Vec<&str> = text.split_whitespace().collect();
                        let characters = text.chars().count();
                        let characters_no_spaces = text.chars().filter(|c| !c.is_whitespace()).count();
                        let paragraphs = text.lines().filter(|line| !line.trim().is_empty()).count();
                        let sentences = text.matches('.').count() + text.matches('!').count() + text.matches('?').count();
                        
                        ToolOutcome::Statistics { statistics: serde_json::json!({
                            "words": words.len(),
                            "characters": characters,
                            "characters_no_spaces": characters_no_spaces,
                            "paragraphs": paragraphs,
                            "sentences": sentences,
                            "pages": ((words.len() as f32 / 250.0).ceil() as usize).max(1),
                            "reading_time_minutes": (words.len() as f32 / 200.0).ceil() as usize
                        }) }
                    }
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None }
                }
            },
            
            "search_text" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let search_term = arguments["search_term"].as_str().unwrap_or("");
                let case_sensitive = arguments.get("case_sensitive").and_then(|v| v.as_bool()).unwrap_or(false);
                let _whole_word = arguments.get("whole_word").and_then(|v| v.as_bool()).unwrap_or(false);
                
                let handler = self.handler.read().unwrap();
                match handler.extract_text(doc_id) {
                    Ok(text) => {
                        let search_text = if case_sensitive { text.clone() } else { text.to_lowercase() };
                        let search_for = if case_sensitive { search_term.to_string() } else { search_term.to_lowercase() };
                        
                        let mut matches = Vec::new();
                        let mut position = 0;
                        
                        while let Some(found_pos) = search_text[position..].find(&search_for) {
                            let absolute_pos = position + found_pos;
                            
                            // Extract context around the match
                            let context_start = absolute_pos.saturating_sub(50);
                            let context_end = (absolute_pos + search_for.len() + 50).min(text.len());
                            let context = &text[context_start..context_end];
                            
                            matches.push(json!({
                                "position": absolute_pos,
                                "context": context,
                                "line": text[..absolute_pos].matches('\n').count() + 1
                            }));
                            
                            position = absolute_pos + search_for.len();
                        }
                        
                        ToolOutcome::Metadata { metadata: serde_json::json!({
                            "matches": matches,
                            "total_matches": matches.len()
                        }) }
                    }
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None }
                }
            },
            
            "export_to_markdown" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_path = arguments["output_path"].as_str().unwrap_or("");
                
                let handler = self.handler.read().unwrap();
                match handler.extract_text(doc_id) {
                    Ok(text) => {
                        // Simple conversion to Markdown - in full implementation would preserve formatting
                        let mut markdown = String::new();
                        
                        for line in text.lines() {
                            let trimmed = line.trim();
                            if trimmed.is_empty() {
                                markdown.push('\n');
                                continue;
                            }
                            
                            // Detect and convert headings
                            if trimmed.len() < 100 && trimmed.chars().any(|c| c.is_uppercase()) {
                                if trimmed.chars().all(|c| c.is_uppercase() || c.is_whitespace()) {
                                    markdown.push_str(&format!("# {}\n\n", trimmed));
                                } else {
                                    markdown.push_str(&format!("## {}\n\n", trimmed));
                                }
                            } else {
                                markdown.push_str(&format!("{}\n\n", trimmed));
                            }
                        }
                        
                        // Save to file
                        match std::fs::write(output_path, markdown) {
                            Ok(_) => ToolOutcome::Ok { message: Some(format!("Document exported to Markdown at {}", output_path)) },
                            Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: format!("Failed to save file: {}", e), hint: None }
                        }
                    }
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None }
                }
            },

            "export_to_html" => {
                let doc_id = arguments["document_id"].as_str().unwrap_or("");
                let output_path = arguments["output_path"].as_str().unwrap_or("");
                
                let handler = self.handler.read().unwrap();
                match handler.extract_text(doc_id) {
                    Ok(text) => {
                        // Simple conversion to HTML - preserve headings heuristically
                        let mut html = String::from("<html><head><meta charset=\"utf-8\"></head><body>\n");
                        for line in text.lines() {
                            let trimmed = line.trim();
                            if trimmed.is_empty() { continue; }
                            if trimmed.len() < 100 && trimmed.chars().any(|c| c.is_uppercase()) {
                                if trimmed.chars().all(|c| c.is_uppercase() || c.is_whitespace()) {
                                    html.push_str(&format!("<h1>{}</h1>\n", html_escape::encode_text(trimmed)));
                                } else {
                                    html.push_str(&format!("<h2>{}</h2>\n", html_escape::encode_text(trimmed)));
                                }
                            } else if trimmed.starts_with("- ") || trimmed.starts_with("* ") {
                                // naive list handling: wrap each as <li>
                                html.push_str(&format!("<ul><li>{}</li></ul>\n", html_escape::encode_text(&trimmed[2..])));
                            } else {
                                html.push_str(&format!("<p>{}</p>\n", html_escape::encode_text(trimmed)));
                            }
                        }
                        html.push_str("</body></html>\n");
                        match std::fs::write(output_path, html) {
                            Ok(_) => ToolOutcome::Ok { message: Some(format!("Document exported to HTML at {}", output_path)) },
                            Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: format!("Failed to save file: {}", e), hint: None }
                        }
                    }
                    Err(e) => ToolOutcome::Error { code: ErrorCode::DocNotFound, error: e.to_string(), hint: None }
                }
            },
            
            "get_security_info" => {
                ToolOutcome::Security { security: serde_json::json!({
                    "readonly_mode": self.security_config.readonly_mode,
                    "sandbox_mode": self.security_config.sandbox_mode,
                    "allow_external_tools": self.security_config.allow_external_tools,
                    "allow_network": self.security_config.allow_network,
                    "max_document_size": self.security_config.max_document_size,
                    "max_open_documents": self.security_config.max_open_documents,
                    "summary": self.security_config.get_summary(),
                    "readonly_commands": crate::security::SecurityConfig::get_readonly_commands().len(),
                    "write_commands": crate::security::SecurityConfig::get_write_commands().len()
                }) }
            },
            
            "get_storage_info" => {
                let handler = self.handler.read().unwrap();
                match handler.get_storage_info() {
                    Ok(info) => ToolOutcome::Storage { storage: info.get("storage").cloned().unwrap_or(serde_json::json!({})) },
                    Err(e) => ToolOutcome::Error { code: ErrorCode::InternalError, error: e.to_string(), hint: None },
                }
            },

            "list_templates" => {
                let mut templates = Vec::new();
                if self.templates_dir.exists() {
                    if let Ok(entries) = std::fs::read_dir(&self.templates_dir) {
                        for entry in entries.filter_map(|e| e.ok()) {
                            let path = entry.path();
                            if path.is_file() {
                                if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
                                    if ext.eq_ignore_ascii_case("docx") {
                                        if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
                                            templates.push(name.to_string());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                templates.sort();
                ToolOutcome::Metadata {
                    metadata: serde_json::json!({ "templates": templates }),
                }
            },

            "open_template" => {
                let name = arguments["name"].as_str().unwrap_or("");
                if name.is_empty() {
                    ToolOutcome::Error {
                        code: ErrorCode::ValidationError,
                        error: "Template name is required".to_string(),
                        hint: Some("Provide 'name' with a .docx filename from list_templates".to_string()),
                    }
                } else {
                    let path = self.templates_dir.join(name);
                    if !path.exists() || !path.is_file() {
                        ToolOutcome::Error {
                            code: ErrorCode::ValidationError,
                            error: format!("Template not found: {}", name),
                            hint: Some("Check list_templates for available names".to_string()),
                        }
                    } else {
                        let mut handler = self.handler.write().unwrap();
                        match handler.open_document(&path) {
                            Ok(doc_id) => ToolOutcome::Created {
                                document_id: doc_id,
                                message: Some(format!("Opened template '{}' as document", name)),
                            },
                            Err(e) => ToolOutcome::Error {
                                code: ErrorCode::InternalError,
                                error: e.to_string(),
                                hint: None,
                            },
                        }
                    }
                }
            },

            "generate_from_template" => {
                let template_name = arguments["template_name"].as_str().unwrap_or("");
                let output_path = arguments["output_path"].as_str().unwrap_or("");
                let fields = arguments.get("fields").and_then(|v| v.as_object()).cloned().unwrap_or_default();

                if template_name.is_empty() {
                    ToolOutcome::Error {
                        code: ErrorCode::ValidationError,
                        error: "template_name is required".to_string(),
                        hint: Some("Provide the template file name from list_templates".to_string()),
                    }
                } else if output_path.is_empty() {
                    ToolOutcome::Error {
                        code: ErrorCode::ValidationError,
                        error: "output_path is required".to_string(),
                        hint: Some("Provide an absolute path where the generated DOCX will be saved".to_string()),
                    }
                } else {
                    let template_path = self.templates_dir.join(template_name);
                    if !template_path.exists() || !template_path.is_file() {
                        ToolOutcome::Error {
                            code: ErrorCode::ValidationError,
                            error: format!("Template not found: {}", template_name),
                            hint: Some("Check list_templates for available names".to_string()),
                        }
                    } else {
                        // Open template
                        let mut handler = self.handler.write().unwrap();
                        let doc_id = match handler.open_document(&template_path) {
                            Ok(id) => id,
                            Err(e) => {
                                drop(handler);
                                return ToolOutcome::Error {
                                    code: ErrorCode::InternalError,
                                    error: e.to_string(),
                                    hint: None,
                                };
                            }
                        };

                        // Apply field replacements
                        let mut replace_count = 0usize;
                        for (key, value) in &fields {
                            let placeholder = format!("{{{{{}}}}}", key);
                            let val_str = match value {
                                Value::String(s) => s.clone(),
                                _ => value.to_string(),
                            };
                            if let Ok(count) = handler.find_and_replace_advanced(
                                &doc_id,
                                &placeholder,
                                &val_str,
                                false,  // case_sensitive: false for placeholders
                                true,   // whole_word: true (treat placeholder as whole token)
                                false,  // use_regex: false
                            ) {
                                replace_count += count;
                            }
                        }

                        // Save generated document
                        let out_path = PathBuf::from(output_path);
                        let result = if out_path.parent().is_some() {
                            if let Err(e) = std::fs::create_dir_all(out_path.parent().unwrap()) {
                                drop(handler);
                                ToolOutcome::Error {
                                    code: ErrorCode::InternalError,
                                    error: format!("Failed to create output directory: {}", e),
                                    hint: None,
                                }
                            } else {
                                match handler.save_document(&doc_id, &out_path) {
                                    Ok(()) => ToolOutcome::Ok {
                                        message: Some(format!(
                                            "Generated document from template '{}' with {} replacements at {}",
                                            template_name, replace_count, output_path
                                        )),
                                    },
                                    Err(e) => ToolOutcome::Error {
                                        code: ErrorCode::InternalError,
                                        error: e.to_string(),
                                        hint: None,
                                    },
                                }
                            }
                        } else {
                            match handler.save_document(&doc_id, &out_path) {
                                Ok(()) => ToolOutcome::Ok {
                                    message: Some(format!(
                                        "Generated document from template '{}' with {} replacements at {}",
                                        template_name, replace_count, output_path
                                    )),
                                },
                                Err(e) => ToolOutcome::Error {
                                    code: ErrorCode::InternalError,
                                    error: e.to_string(),
                                    hint: None,
                                },
                            }
                        };

                        // Optionally close template document
                        let _ = handler.close_document(&doc_id);
                        drop(handler);
                        result
                    }
                }
            },

            _ => {
                ToolOutcome::Error { code: ErrorCode::UnknownTool, error: format!("Unknown or unsupported tool: {}", name), hint: None }
            }
        };
        // Backward-compatible JSON shaping with success boolean at top-level
        let legacy = match outcome {
            ToolOutcome::Ok { message } => {
                let mut obj = serde_json::json!({"success": true});
                if let Some(m) = message { obj["message"] = serde_json::Value::String(m); }
                obj
            }
            ToolOutcome::Created { document_id, message } => {
                let mut obj = serde_json::json!({"success": true, "document_id": document_id});
                if let Some(m) = message { obj["message"] = serde_json::Value::String(m); }
                obj
            }
            ToolOutcome::Text { text } => serde_json::json!({"success": true, "text": text}),
            ToolOutcome::Metadata { metadata } => {
                // Heuristic: if this looks like search results (matches/total_matches), flatten.
                let is_search_shape = metadata.get("matches").is_some() || metadata.get("total_matches").is_some();
                if is_search_shape {
                    let mut obj = serde_json::json!({"success": true});
                    if let Some(map) = metadata.as_object() {
                        for (k, v) in map { obj[&k[..]] = v.clone(); }
                    }
                    obj
                } else {
                    serde_json::json!({"success": true, "metadata": metadata})
                }
            }
            ToolOutcome::Documents { documents } => serde_json::json!({"success": true, "documents": documents}),
            ToolOutcome::Images { images, message } => {
                let mut obj = serde_json::json!({"success": true, "images": images});
                if let Some(m) = message { obj["message"] = serde_json::Value::String(m); }
                obj
            }
            ToolOutcome::Security { security } => serde_json::json!({"success": true, "security": security}),
            ToolOutcome::Storage { storage } => serde_json::json!({"success": true, "storage": storage}),
            ToolOutcome::Statistics { statistics } => serde_json::json!({"success": true, "statistics": statistics}),
            ToolOutcome::Structure { structure } => serde_json::json!({"success": true, "structure": structure}),
            ToolOutcome::Error { code, error, hint } => {
                let mut obj = serde_json::json!({"success": false, "error": error});
                obj["code"] = serde_json::json!(code);
                if let Some(h) = hint { obj["hint"] = serde_json::Value::String(h); }
                obj
            }
        };
        CallToolResponse { content: vec![ToolResponseContent::Text(TextContent { content_type: "application/json".into(), text: legacy.to_string(), annotations: None })], is_error: None, meta: None }
    }
}