"""Local file storage tool implementation"""

import os
from typing import Optional, Tuple
from diona.project.storage.storage import get_storage_instance
from diona.project.shell.shell import DefaultShellCommander


class LocalFileStorage:
    """Local file storage tool class"""
    
    def __init__(self):
        """Initialize LocalFileStorage"""
        self.storage = get_storage_instance()
        # Create shell commander with appropriate encoding for Windows
        from diona.project.shell.shell import DefaultShellCommander
        
        self.shell = DefaultShellCommander()
    
    def write_diona_file(self, relative_path: str, content: str, module_name: str = "agent", storage_type: str = "project") -> bool:
        """Write file to specified storage type directory (diona storage)
        
        Args:
            relative_path: Relative path under the specified storage type directory
            content: Content to write to file
            module_name: Module name (default: "agent")
            storage_type: Storage type (default: "project")
            
        Returns:
            bool: True if write successful, False otherwise
        """
        return self.storage.write(module_name, relative_path, content, storage_type=storage_type)
    
    def write_file(self, path: str, content: str) -> bool:
        """Write file to any directory (unrestricted)
        
        Args:
            path: Full path to the file
            content: Content to write to file
            
        Returns:
            bool: True if write successful, False otherwise
        """
        try:
            dir_path = os.path.dirname(path)
            if dir_path:
                os.makedirs(dir_path, exist_ok=True)
            with open(path, 'w', encoding='utf-8') as f:
                f.write(content)
            return True
        except Exception:
            return False
    
    def edit_file(self, path: str, start_line: int, end_line: int, original_content: str, new_content: str) -> tuple[bool, str]:
        """Edit file by line range with original content verification
        
        Args:
            path: Full path to the file
            start_line: Start line number (1-based)
            end_line: End line number (1-based)
            original_content: Original content that should match the lines
            new_content: New content to replace with
            
        Returns:
            tuple[bool, str]: (success, message)
        """
        try:
            if not os.path.exists(path):
                return False, f"File not found: {path}"
            
            with open(path, 'r', encoding='utf-8') as f:
                lines = f.readlines()
            
            if start_line < 1 or start_line > len(lines):
                return False, f"Invalid start line: {start_line}"
            if end_line < start_line or end_line > len(lines):
                return False, f"Invalid end line: {end_line}"
            
            actual_content = ''.join(lines[start_line - 1:end_line])
            if actual_content != original_content:
                return False, f"Original content does not match. Expected:\n{original_content}\n\nActual:\n{actual_content}"
            
            lines = lines[:start_line - 1] + [new_content] + lines[end_line:]
            
            with open(path, 'w', encoding='utf-8') as f:
                f.writelines(lines)
            
            return True, f"Successfully modified lines {start_line}-{end_line}"
        except Exception as e:
            return False, f"Error: {str(e)}"
    
    def read_file(self, path: str) -> Optional[str]:
        """Read file content directly
        
        Args:
            path: Path to read
            
        Returns:
            Optional[str]: File content if successful, None otherwise
        """
        try:
            with open(path, 'r', encoding='utf-8') as f:
                return f.read()
        except Exception:
            return None
    
    def list_directory(self, path: str) -> Optional[str]:
        """List directory contents directly
        
        Args:
            path: Directory path to list
            
        Returns:
            Optional[str]: Directory listing if successful, None otherwise
        """
        try:
            entries = os.listdir(path)
            lines = []
            for entry in entries:
                full_path = os.path.join(path, entry)
                if os.path.isdir(full_path):
                    lines.append(f"{entry}/")
                else:
                    lines.append(entry)
            return "\n".join(sorted(lines))
        except Exception:
            return None
    
    def read_lines(self, path: str, n: int = 10) -> Optional[str]:
        """Read first N lines of a file
        
        Args:
            path: File path to read
            n: Number of lines to read (default: 10)
            
        Returns:
            Optional[str]: First N lines if successful, None otherwise
        """
        try:
            with open(path, 'r', encoding='utf-8') as f:
                lines = []
                for i, line in enumerate(f):
                    if i >= n:
                        break
                    lines.append(line.rstrip('\n'))
                return "\n".join(lines)
        except Exception:
            return None
    
    def get_full_path(self, relative_path: str, module_name: str = "agent", storage_type: str = "project") -> str:
        """Get full path for a given relative path
        
        Args:
            relative_path: Relative path under the specified storage type directory
            module_name: Module name (default: "agent")
            storage_type: Storage type (default: "project")
            
        Returns:
            str: Full path
        """
        return self.storage.get_path(module_name, relative_path, storage_type=storage_type)
    
    def file_exists(self, relative_path: str, module_name: str = "agent", storage_type: str = "project") -> bool:
        """Check if file exists
        
        Args:
            relative_path: Relative path under the specified storage type directory
            module_name: Module name (default: "agent")
            storage_type: Storage type (default: "project")
            
        Returns:
            bool: True if file exists, False otherwise
        """
        return self.storage.exists(module_name, relative_path, storage_type=storage_type)
