TOOL_NAME = "analyze_attachments"
TOOL_DESCRIPTION = """Analyze attachments (PDFs, Office documents, images, and text files) by extracting text and metadata"""
TOOL_ARGS = '{"file_path": {"type": "string", "description": "Path to the attachment file to analyze"}, "extract_text": {"type": "boolean", "default": true, "description": "Extract text content from documents"}, "extract_metadata": {"type": "boolean", "default": true, "description": "Extract metadata (EXIF, properties, etc.)"}}'

import os
import json
from pathlib import Path
from tools._std import tool_ok, tool_error

def run(args: dict) -> str:
    file_path = args.get("file_path", "")
    extract_text = args.get("extract_text", True)
    extract_metadata = args.get("extract_metadata", True)
    
    if not file_path or not os.path.exists(file_path):
        return tool_error(f"File not found: {file_path}")
    
    file_path = Path(file_path)
    ext = file_path.suffix.lower()
    result = {
        "file_name": file_path.name,
        "file_size": os.path.getsize(file_path),
        "file_type": ext,
        "analysis": {}
    }
    
    try:
        if ext == '.pdf':
            result["analysis"] = analyze_pdf_file(file_path, extract_text, extract_metadata)
        elif ext in ['.docx', '.doc']:
            result["analysis"] = analyze_word_doc(file_path, extract_text, extract_metadata)
        elif ext in ['.xlsx', '.xls']:
            result["analysis"] = analyze_excel_file(file_path, extract_text, extract_metadata)
        elif ext in ['.pptx', '.ppt']:
            result["analysis"] = analyze_powerpoint_file(file_path, extract_text, extract_metadata)
        elif ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp']:
            result["analysis"] = analyze_image(file_path, extract_text, extract_metadata)
        elif ext in ['.txt', '.csv', '.json', '.xml', '.html', '.htm', '.md', '.log']:
            result["analysis"] = analyze_text_file(file_path)
        else:
            result["analysis"] = {"info": f"Basic file analysis. Type '{ext}' not fully supported for deep analysis."}
            
    except Exception as e:
        result["error"] = str(e)
    
    return tool_ok(result, f"Analyzed {result['file_name']}")

def analyze_pdf_file(file_path, extract_text, extract_metadata):
    """Extract text and metadata from PDF files"""
    result = {}

    try:
        from backend.config import PDF_SUPPORT, pypdf
    except Exception as exc:
        return {"error": f"PDF support import failed: {exc}"}

    if not (PDF_SUPPORT and pypdf):
        return {"error": "PDF extraction is unavailable because pypdf is not installed."}

    try:
        with open(file_path, 'rb') as handle:
            reader = pypdf.PdfReader(handle)

            if extract_text:
                pages = []
                for page in reader.pages:
                    text = (page.extract_text() or '').strip()
                    if text:
                        pages.append(text)
                result["text_content"] = "\n\n".join(pages)
                result["page_count"] = len(reader.pages)

            if extract_metadata:
                raw_metadata = getattr(reader, 'metadata', None) or {}
                metadata = {}
                for key, value in dict(raw_metadata).items():
                    clean_key = str(key).lstrip('/')
                    metadata[clean_key] = str(value) if value is not None else None
                if metadata:
                    result["metadata"] = metadata
                result["is_encrypted"] = bool(getattr(reader, 'is_encrypted', False))

            if extract_text and not result.get("text_content"):
                result["note"] = "No extractable text found in the PDF."

    except Exception as exc:
        result["error"] = f"PDF analysis failed: {str(exc)}"

    return result

def analyze_word_doc(file_path, extract_text, extract_metadata):
    """Extract text and metadata from Word documents"""
    result = {}
    
    # Try python-docx first for .docx
    if file_path.suffix.lower() == '.docx':
        try:
            import docx
            doc = docx.Document(str(file_path))
            
            if extract_text:
                full_text = []
                for para in doc.paragraphs:
                    full_text.append(para.text)
                result["text_content"] = "\n".join(full_text)
                result["paragraph_count"] = len(doc.paragraphs)
                
                # Extract text from tables
                tables_text = []
                for table in doc.tables:
                    for row in table.rows:
                        row_text = [cell.text for cell in row.cells]
                        tables_text.append(" | ".join(row_text))
                if tables_text:
                    result["tables_text"] = tables_text[:20]  # Limit output
                    result["table_count"] = len(doc.tables)
            
            if extract_metadata and doc.core_properties:
                props = doc.core_properties
                result["metadata"] = {
                    "author": props.author,
                    "title": props.title,
                    "subject": props.subject,
                    "created": str(props.created) if props.created else None,
                    "modified": str(props.modified) if props.modified else None,
                    "last_modified_by": props.last_modified_by,
                    "revision": props.revision,
                    "category": props.category,
                    "comments": props.comments
                }
                
        except ImportError:
            # Fallback: manual XML extraction from docx (which is a zip)
            import zipfile
            import xml.etree.ElementTree as ET
            
            try:
                with zipfile.ZipFile(file_path, 'r') as z:
                    # Extract text from word/document.xml
                    if 'word/document.xml' in z.namelist():
                        xml_content = z.read('word/document.xml')
                        tree = ET.fromstring(xml_content)
                        
                        # WordprocessingML namespace
                        ns = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
                        
                        if extract_text:
                            texts = []
                            for elem in tree.iter():
                                if elem.tag.endswith('}t'):
                                    if elem.text:
                                        texts.append(elem.text)
                            result["text_content"] = " ".join(texts)
                        
                        # Try to get core properties
                        if extract_metadata and 'docProps/core.xml' in z.namelist():
                            core_xml = z.read('docProps/core.xml')
                            core_tree = ET.fromstring(core_xml)
                            cp_ns = {'cp': 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
                                     'dc': 'http://purl.org/dc/elements/1.1/'}
                            
                            result["metadata"] = {
                                "author": core_tree.findtext('.//dc:creator', namespaces=cp_ns),
                                "title": core_tree.findtext('.//dc:title', namespaces=cp_ns),
                                "subject": core_tree.findtext('.//dc:subject', namespaces=cp_ns),
                                "last_modified_by": core_tree.findtext('.//cp:lastModifiedBy', namespaces=cp_ns)
                            }
            except Exception as e:
                result["error"] = f"Fallback extraction failed: {str(e)}"
                
    else:
        result["note"] = ".doc format requires external tools. Convert to .docx or install antiword/pywin32."
    
    return result

def analyze_excel_file(file_path, extract_text, extract_metadata):
    """Extract text and metadata from Excel spreadsheets"""
    result = {}
    
    if file_path.suffix.lower() == '.xlsx':
        try:
            import openpyxl
            wb = openpyxl.load_workbook(str(file_path), data_only=True)
            
            # Basic workbook info
            result["sheet_names"] = wb.sheetnames
            result["sheet_count"] = len(wb.sheetnames)
            
            if extract_metadata and wb.properties:
                props = wb.properties
                result["metadata"] = {
                    "creator": props.creator,
                    "title": props.title,
                    "subject": props.subject,
                    "description": props.description,
                    "last_modified_by": props.lastModifiedBy,
                    "created": str(props.created) if props.created else None,
                    "modified": str(props.modified) if props.modified else None,
                    "category": props.category,
                    "keywords": props.keywords,
                    "company": props.company
                }
            
            if extract_text:
                # Extract content from each sheet in a single pass
                sheets_content = {}
                all_text = []
                for sheet_idx, sheet_name in enumerate(wb.sheetnames):
                    ws = wb[sheet_name]
                    sheet_data = {
                        "max_row": ws.max_row,
                        "max_column": ws.max_column,
                        "cell_count": ws.max_row * ws.max_column
                    }
                    
                    # Single pass: collect sample values, count formulas, and build text
                    values = []
                    formula_count = 0
                    row_texts = []
                    for row_idx, row in enumerate(ws.iter_rows(max_row=min(ws.max_row, 50))):
                        row_values = []
                        for cell in row:
                            if cell.value is not None:
                                val_str = str(cell.value)
                                if val_str.startswith('='):
                                    formula_count += 1
                                if len(values) < 50:
                                    values.append(val_str)
                                row_values.append(val_str)
                        if row_values and sheet_idx < 3:
                            row_texts.append(" | ".join(row_values))
                    
                    if values:
                        sheet_data["sample_values"] = values
                    if formula_count > 0:
                        sheet_data["formula_count_estimate"] = formula_count
                    
                    sheets_content[sheet_name] = sheet_data
                    all_text.extend(row_texts[:30])
                
                result["sheets"] = sheets_content
                result["text_content"] = "\n".join(all_text[:500])
                
        except ImportError:
            result["error"] = "openpyxl not available. Install with: pip install openpyxl"
        except Exception as e:
            result["error"] = f"Excel analysis failed: {str(e)}"
    else:
        result["note"] = ".xls format requires xlrd library. Convert to .xlsx for full support."
    
    return result

def analyze_powerpoint_file(file_path, extract_text, extract_metadata):
    """Extract text and metadata from PowerPoint presentations"""
    result = {}
    
    if file_path.suffix.lower() == '.pptx':
        try:
            from pptx import Presentation
            prs = Presentation(str(file_path))
            
            # Basic presentation info
            result["slide_count"] = len(prs.slides)
            result["slide_width"] = prs.slide_width
            result["slide_height"] = prs.slide_height
            
            if extract_metadata and prs.core_properties:
                props = prs.core_properties
                result["metadata"] = {
                    "author": props.author,
                    "title": props.title,
                    "subject": props.subject,
                    "created": str(props.created) if props.created else None,
                    "modified": str(props.modified) if props.modified else None,
                    "last_modified_by": props.last_modified_by,
                    "revision": props.revision,
                    "category": props.category,
                    "comments": props.comments,
                    "keywords": props.keywords
                }
            
            if extract_text:
                slides_content = []
                total_text_boxes = 0
                total_shapes = 0
                
                for idx, slide in enumerate(prs.slides[:20]):  # Limit to first 20 slides
                    slide_info = {
                        "slide_number": idx + 1,
                        "layout": slide.slide_layout.name if hasattr(slide.slide_layout, 'name') else "Unknown"
                    }
                    
                    slide_text = []
                    shape_count = 0
                    text_box_count = 0
                    
                    for shape in slide.shapes:
                        shape_count += 1
                        # Extract text from shapes with text frames
                        if hasattr(shape, "text_frame"):
                            text_box_count += 1
                            for paragraph in shape.text_frame.paragraphs:
                                if paragraph.text.strip():
                                    slide_text.append(paragraph.text.strip())
                        # Extract from tables
                        if shape.has_table:
                            table = shape.table
                            for row in table.rows:
                                row_text = [cell.text for cell in row.cells if cell.text.strip()]
                                if row_text:
                                    slide_text.append(" | ".join(row_text))
                    
                    total_shapes += shape_count
                    total_text_boxes += text_box_count
                    
                    if slide_text:
                        slide_info["content"] = slide_text[:30]  # Limit per slide
                        slide_info["text_items"] = len(slide_text)
                    
                    slides_content.append(slide_info)
                
                result["slides"] = slides_content
                result["total_shapes"] = total_shapes
                result["total_text_boxes"] = total_text_boxes
                
                # Extract all text as single string
                all_text = []
                for slide in slides_content:
                    if "content" in slide:
                        all_text.extend(slide["content"])
                result["text_content"] = "\n".join(all_text[:200])  # Limit output
                
        except ImportError:
            result["error"] = "python-pptx not available. Install with: pip install python-pptx"
        except Exception as e:
            result["error"] = f"PowerPoint analysis failed: {str(e)}"
    else:
        result["note"] = ".ppt format requires external conversion. Convert to .pptx for full support."
    
    return result

def analyze_image(file_path, extract_text, extract_metadata):
    """Extract metadata and basic info from images"""
    result = {}
    
    try:
        from PIL import Image, ExifTags
        
        with Image.open(file_path) as img:
            result["format"] = img.format
            result["mode"] = img.mode
            result["dimensions"] = {"width": img.width, "height": img.height}
            
            if extract_metadata:
                exif = {}
                if hasattr(img, '_getexif') and img._getexif():
                    exif_data = img._getexif()
                    for tag_id, value in exif_data.items():
                        tag = ExifTags.TAGS.get(tag_id, tag_id)
                        # Skip binary data
                        if isinstance(value, bytes):
                            value = f"<{len(value)} bytes>"
                        exif[tag] = value
                result["exif"] = exif
                
                # Additional image info
                info = img.info if hasattr(img, 'info') else {}
                result["additional_info"] = {
                    k: str(v)[:500] for k, v in info.items() 
                    if not isinstance(v, bytes)
                }
                
    except ImportError:
        # Basic fallback without PIL
        import imghdr
        result["detected_type"] = imghdr.what(file_path)
        result["note"] = "Install Pillow for full metadata extraction"
    
    return result

def analyze_text_file(file_path):
    """Analyze plain text files"""
    result = {}
    
    try:
        with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read()
            result["text_preview"] = content[:2000] + "..." if len(content) > 2000 else content
            result["char_count"] = len(content)
            result["line_count"] = content.count('\n') + 1
            result["word_count"] = len(content.split())
    except Exception as e:
        result["error"] = str(e)
    
    return result
