"""
Diff Checker Tool

This tool provides file and text comparison capabilities,
useful for code review and content analysis.
"""

import difflib
import os
from typing import Dict, Any, List, Optional, Tuple
from tools.tool_registry import BaseTool


class DiffCheckerTool(BaseTool):
    """Tool for comparing files and text content"""
    
    def __init__(self):
        super().__init__(
            name="diff_checker_tool",
            description="Compare files, text content, or code. Supports unified diff, side-by-side comparison, and change statistics."
        )
    
    def execute(self, query: str, context: Dict[str, Any]) -> Any:
        """
        Execute diff checking based on query
        
        Args:
            query: User query containing comparison instructions
            context: Task analysis and other context
            
        Returns:
            Comparison result with differences highlighted
        """
        # Parse the query to extract comparison targets
        comparison_data = self._parse_comparison_query(query)
        
        if not comparison_data:
            return {
                "success": False,
                "error": "Could not parse comparison targets from query",
                "message": "Please specify two files or text blocks to compare"
            }
        
        return self._perform_comparison(comparison_data, query)
    
    def _parse_comparison_query(self, query: str) -> Optional[Dict[str, Any]]:
        """Parse query to extract what to compare"""
        import re
        
        # Look for file paths
        file_pattern = r"['\"]?([^'\"]+\.[a-zA-Z0-9]+)['\"]?"
        files = re.findall(file_pattern, query)
        
        # Look for all quoted text blocks (single or double quotes, any length)
        quoted_texts = re.findall(r'["\']([^"\']+)["\']', query)
        
        if len(files) >= 2:
            return {
                "type": "files",
                "source1": files[0],
                "source2": files[1]
            }
        elif len(quoted_texts) >= 2:
            return {
                "type": "text",
                "source1": quoted_texts[0],
                "source2": quoted_texts[1]
            }
        elif len(files) == 1 and len(quoted_texts) >= 1:
            return {
                "type": "mixed",
                "source1": files[0],
                "source2": quoted_texts[0]
            }
        
        # Look for "compare X and Y" pattern
        compare_pattern = r'compare\s+(.+?)\s+(?:and|with)\s+(.+?)(?:\s|$)'
        match = re.search(compare_pattern, query, re.IGNORECASE)
        if match:
            return {
                "type": "general",
                "source1": match.group(1).strip(),
                "source2": match.group(2).strip()
            }
        
        return None
    
    def _perform_comparison(self, comparison_data: Dict[str, Any], query: str) -> Dict[str, Any]:
        """Perform the actual comparison"""
        try:
            # Get content for both sources
            content1 = self._get_content(comparison_data["source1"], comparison_data["type"])
            content2 = self._get_content(comparison_data["source2"], comparison_data["type"])
            
            if content1 is None or content2 is None:
                return {
                    "success": False,
                    "error": "Could not read one or both comparison sources",
                    "message": "Please check that files exist and are readable"
                }
            
            # Determine comparison format based on query
            if 'unified' in query.lower():
                diff_result = self._unified_diff(content1, content2, comparison_data)
            elif 'side' in query.lower() or 'html' in query.lower():
                diff_result = self._html_diff(content1, content2, comparison_data)
            else:
                # Default: unified diff with statistics
                diff_result = self._comprehensive_diff(content1, content2, comparison_data)
            
            return diff_result
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Error performing comparison: {str(e)}"
            }
    
    def _get_content(self, source: str, comparison_type: str) -> Optional[str]:
        """Get content from source (file or text)"""
        if comparison_type == "files" or (comparison_type in ["mixed", "general"] and os.path.exists(source)):
            # Try to read as file
            try:
                with open(source, 'r', encoding='utf-8', errors='ignore') as f:
                    return f.read()
            except Exception:
                return None
        else:
            # Treat as text content
            return source
    
    def _unified_diff(self, content1: str, content2: str, comparison_data: Dict[str, Any]) -> Dict[str, Any]:
        """Generate unified diff"""
        lines1 = content1.splitlines(keepends=True)
        lines2 = content2.splitlines(keepends=True)
        
        diff = list(difflib.unified_diff(
            lines1, 
            lines2,
            fromfile=comparison_data.get("source1", "Source 1"),
            tofile=comparison_data.get("source2", "Source 2"),
            lineterm=''
        ))
        
        return {
            "success": True,
            "comparison_type": "unified_diff",
            "source1": comparison_data["source1"],
            "source2": comparison_data["source2"],
            "diff": ''.join(diff),
            "has_differences": len(diff) > 0,
            "message": f"Generated unified diff between {comparison_data['source1']} and {comparison_data['source2']}"
        }
    
    def _html_diff(self, content1: str, content2: str, comparison_data: Dict[str, Any]) -> Dict[str, Any]:
        """Generate HTML side-by-side diff"""
        lines1 = content1.splitlines()
        lines2 = content2.splitlines()
        
        differ = difflib.HtmlDiff()
        html_diff = differ.make_file(
            lines1,
            lines2,
            fromdesc=comparison_data.get("source1", "Source 1"),
            todesc=comparison_data.get("source2", "Source 2")
        )
        
        return {
            "success": True,
            "comparison_type": "html_diff",
            "source1": comparison_data["source1"],
            "source2": comparison_data["source2"],
            "html_diff": html_diff,
            "has_differences": "No Differences Found" not in html_diff,
            "message": f"Generated HTML diff between {comparison_data['source1']} and {comparison_data['source2']}"
        }
    
    def _comprehensive_diff(self, content1: str, content2: str, comparison_data: Dict[str, Any]) -> Dict[str, Any]:
        """Generate comprehensive diff with statistics"""
        lines1 = content1.splitlines()
        lines2 = content2.splitlines()
        
        # Generate unified diff
        unified_diff = list(difflib.unified_diff(
            lines1,
            lines2,
            fromfile=comparison_data.get("source1", "Source 1"),
            tofile=comparison_data.get("source2", "Source 2"),
            lineterm=''
        ))
        
        # Calculate statistics
        stats = self._calculate_diff_stats(lines1, lines2, unified_diff)
        
        # Get context diff for better readability
        context_diff = list(difflib.context_diff(
            lines1,
            lines2,
            fromfile=comparison_data.get("source1", "Source 1"),
            tofile=comparison_data.get("source2", "Source 2"),
            lineterm=''
        ))
        
        # Find similar lines
        similarity_ratio = difflib.SequenceMatcher(None, content1, content2).ratio()
        
        return {
            "success": True,
            "comparison_type": "comprehensive",
            "source1": comparison_data["source1"],
            "source2": comparison_data["source2"],
            "unified_diff": '\n'.join(unified_diff),
            "context_diff": '\n'.join(context_diff),
            "statistics": stats,
            "similarity_ratio": similarity_ratio,
            "similarity_percentage": f"{similarity_ratio * 100:.2f}%",
            "has_differences": len(unified_diff) > 0,
            "message": f"Comprehensive comparison between {comparison_data['source1']} and {comparison_data['source2']}"
        }
    
    def _calculate_diff_stats(self, lines1: List[str], lines2: List[str], unified_diff: List[str]) -> Dict[str, int]:
        """Calculate diff statistics"""
        stats = {
            "lines_source1": len(lines1),
            "lines_source2": len(lines2),
            "lines_added": 0,
            "lines_removed": 0,
            "lines_modified": 0,
            "total_changes": 0
        }
        
        for line in unified_diff:
            if line.startswith('+') and not line.startswith('+++'):
                stats["lines_added"] += 1
            elif line.startswith('-') and not line.startswith('---'):
                stats["lines_removed"] += 1
        
        # Estimate modified lines (pairs of additions and deletions)
        stats["lines_modified"] = min(stats["lines_added"], stats["lines_removed"])
        stats["lines_added"] -= stats["lines_modified"]
        stats["lines_removed"] -= stats["lines_modified"]
        
        stats["total_changes"] = stats["lines_added"] + stats["lines_removed"] + stats["lines_modified"]
        
        return stats
    
    def compare_files(self, file1: str, file2: str, diff_type: str = "unified") -> Dict[str, Any]:
        """Direct method to compare two files"""
        comparison_data = {
            "type": "files",
            "source1": file1,
            "source2": file2
        }
        
        query = f"compare {file1} and {file2} using {diff_type} format"
        return self._perform_comparison(comparison_data, query)
    
    def compare_text(self, text1: str, text2: str, diff_type: str = "unified") -> Dict[str, Any]:
        """Direct method to compare two text strings"""
        comparison_data = {
            "type": "text",
            "source1": text1,
            "source2": text2
        }
        
        query = f"compare text blocks using {diff_type} format"
        return self._perform_comparison(comparison_data, query)
    
    def get_capabilities(self) -> List[str]:
        """Return capabilities of this tool"""
        return [
            "file_comparison",
            "text_comparison",
            "code_diff",
            "unified_diff",
            "html_diff",
            "change_statistics",
            "similarity_analysis"
        ]
    
    def validate_input(self, query: str, context: Dict[str, Any]) -> bool:
        """Validate input for diff operations"""
        diff_keywords = [
            'compare', 'diff', 'difference', 'changes', 'modified',
            'versus', 'vs', 'against', 'between'
        ]
        
        query_lower = query.lower()
        return any(keyword in query_lower for keyword in diff_keywords)
    
    def get_file_info(self, filepath: str) -> Optional[Dict[str, Any]]:
        """Get information about a file"""
        try:
            if not os.path.exists(filepath):
                return None
            
            stat = os.stat(filepath)
            with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
            
            return {
                "path": filepath,
                "size": stat.st_size,
                "modified": stat.st_mtime,
                "lines": len(content.splitlines()),
                "characters": len(content),
                "extension": os.path.splitext(filepath)[1]
            }
        except Exception:
            return None

