#!/usr/bin/env python3
"""
DecentraBrowser Decryption Tab Adder

This script adds a Decryption Arena tab to DecentraBrowser.
It makes minimal, focused changes to avoid syntax errors.

Usage:
    python add_decryption_tab.py
"""

import os
import re
import sys
import shutil

def backup_file(file_path):
    """Create a backup of a file before modifying it."""
    backup_path = file_path + '.decryption.bak'
    print(f"Creating backup: {backup_path}")
    shutil.copy2(file_path, backup_path)
    return backup_path

def add_imports(content):
    """Add any necessary imports that might be missing."""
    if "import base64" not in content:
        # Find the imports section
        imports_section = re.search(r'import.*?\n\n', content, re.DOTALL)
        if imports_section:
            imports_end = imports_section.end()
            # Add base64 import
            return content[:imports_end] + "import base64\n\n" + content[imports_end:]
    
    return content

def add_tab_declaration(content):
    """Add the decryption tab declaration."""
    if "self.tab_decryption" not in content:
        # Find the tab declarations
        tab_pattern = r'(self\.tab_certs = QWidget\(\)\s*)'
        match = re.search(tab_pattern, content)
        if match:
            tab_decl = match.group(1)
            new_decl = tab_decl + "        self.tab_decryption = QWidget()\n"
            return content.replace(tab_decl, new_decl)
    return content

def add_tab_to_tabwidget(content):
    """Add the decryption tab to the tab widget."""
    if 'self.tabs.addTab(self.tab_decryption, "Decryption Arena")' not in content:
        # Find the last tab addition line
        tab_add_pattern = r'(self\.tabs\.addTab\(self\.tab_certs, "Certificates"\)\s*)'
        match = re.search(tab_add_pattern, content)
        if match:
            last_tab = match.group(1)
            new_tabs = last_tab + '        self.tabs.addTab(self.tab_decryption, "Decryption Arena")\n'
            return content.replace(last_tab, new_tabs)
    return content

def add_setup_method_call(content):
    """Add the call to setup_decryption_tab method."""
    if "self.setup_decryption_tab()" not in content:
        # Find setup_certs_tab method call
        setup_pattern = r'(# Setup certificates tab\s*self\.setup_certs_tab\(\)\s*)'
        match = re.search(setup_pattern, content)
        if match:
            setup_call = match.group(1)
            new_setup = setup_call + "\n        # Setup decryption tab\n        self.setup_decryption_tab()\n"
            return content.replace(setup_call, new_setup)
    return content

def add_decryption_methods(content):
    """Add the decryption tab methods to the class."""
    # Check if methods are already present
    if "def setup_decryption_tab(self):" in content:
        return content
    
    # Find a good place to add our methods (before closeEvent)
    close_event_pattern = r'def closeEvent\(self, event\):'
    match = re.search(close_event_pattern, content)
    if not match:
        print("Could not find closeEvent method to insert before")
        return content
    
    # Prepare the methods to add
    methods_to_add = """
    def setup_decryption_tab(self):
        
        layout = QVBoxLayout()
        
        # Description
        description = QLabel("Decryption Arena - Decrypt files using encryption keys")
        description.setStyleSheet("font-size: 14px; font-weight: bold; margin: 10px;")
        layout.addWidget(description)
        
        # File selection
        file_group = QGroupBox("1. Select Encrypted File")
        file_layout = QVBoxLayout()
        
        file_path_layout = QHBoxLayout()
        self.txt_decrypt_file = QLineEdit()
        self.txt_decrypt_file.setReadOnly(True)
        self.txt_decrypt_file.setPlaceholderText("Select an encrypted file...")
        
        btn_browse_file = QPushButton("Browse")
        btn_browse_file.clicked.connect(self.browse_encrypted_file)
        
        file_path_layout.addWidget(self.txt_decrypt_file)
        file_path_layout.addWidget(btn_browse_file)
        
        file_layout.addLayout(file_path_layout)
        file_group.setLayout(file_layout)
        layout.addWidget(file_group)
        
        # Key selection
        key_group = QGroupBox("2. Provide Encryption Key")
        key_layout = QVBoxLayout()
        
        # Option 1: Load key from file
        key_file_radio = QRadioButton("Load key from file")
        key_file_radio.setChecked(True)
        
        key_file_layout = QHBoxLayout()
        self.txt_key_file = QLineEdit()
        self.txt_key_file.setReadOnly(True)
        self.txt_key_file.setPlaceholderText("Select a key file...")
        
        btn_browse_key = QPushButton("Browse")
        btn_browse_key.clicked.connect(self.browse_key_file)
        
        key_file_layout.addWidget(self.txt_key_file)
        key_file_layout.addWidget(btn_browse_key)
        
        # Option 2: Enter key manually
        key_manual_radio = QRadioButton("Enter key manually (base64 encoded)")
        self.txt_key_manual = QLineEdit()
        self.txt_key_manual.setPlaceholderText("Paste base64 encoded key here...")
        self.txt_key_manual.setEnabled(False)
        
        # Key option group
        self.key_option_group = QButtonGroup()
        self.key_option_group.addButton(key_file_radio, 1)
        self.key_option_group.addButton(key_manual_radio, 2)
        self.key_option_group.buttonClicked.connect(self.toggle_key_input)
        
        key_layout.addWidget(key_file_radio)
        key_layout.addLayout(key_file_layout)
        key_layout.addWidget(key_manual_radio)
        key_layout.addWidget(self.txt_key_manual)
        
        key_group.setLayout(key_layout)
        layout.addWidget(key_group)
        
        # Output selection
        output_group = QGroupBox("3. Select Output Location")
        output_layout = QVBoxLayout()
        
        output_path_layout = QHBoxLayout()
        self.txt_decrypt_output = QLineEdit()
        self.txt_decrypt_output.setReadOnly(True)
        self.txt_decrypt_output.setPlaceholderText("Select output location...")
        
        btn_browse_output = QPushButton("Browse")
        btn_browse_output.clicked.connect(self.browse_output_location)
        
        output_path_layout.addWidget(self.txt_decrypt_output)
        output_path_layout.addWidget(btn_browse_output)
        
        output_layout.addLayout(output_path_layout)
        output_group.setLayout(output_layout)
        layout.addWidget(output_group)
        
        # Decrypt button
        btn_layout = QHBoxLayout()
        btn_layout.addStretch()
        self.btn_decrypt = QPushButton("Decrypt File")
        self.btn_decrypt.setStyleSheet("font-size: 14px; padding: 8px 16px;")
        self.btn_decrypt.clicked.connect(self.decrypt_file)
        btn_layout.addWidget(self.btn_decrypt)
        layout.addLayout(btn_layout)
        
        # Status
        self.lbl_decrypt_status = QLabel("")
        self.lbl_decrypt_status.setStyleSheet("margin-top: 10px;")
        layout.addWidget(self.lbl_decrypt_status)
        
        # Add stretch to push everything to the top
        layout.addStretch()
        
        self.tab_decryption.setLayout(layout)
    
    def browse_encrypted_file(self):
       
        file_path, _ = QFileDialog.getOpenFileName(self, "Select Encrypted File", "", "All Files (*.*)")
        if file_path:
            self.txt_decrypt_file.setText(file_path)
            
            # Try to find a matching key file
            key_path = file_path + '.key'
            if os.path.exists(key_path):
                self.txt_key_file.setText(key_path)
                self.statusBar.showMessage(f"Found matching key file: {key_path}", 3000)
    
    def browse_key_file(self):
        
        file_path, _ = QFileDialog.getOpenFileName(self, "Select Key File", "", "Key Files (*.key);;All Files (*.*)")
        if file_path:
            self.txt_key_file.setText(file_path)
    
    def browse_output_location(self):
        
        dir_path = QFileDialog.getExistingDirectory(self, "Select Output Directory")
        if dir_path:
            self.txt_decrypt_output.setText(dir_path)
    
    def toggle_key_input(self, button):
        
        if button.text() == "Load key from file":
            self.txt_key_file.setEnabled(True)
            self.txt_key_manual.setEnabled(False)
        else:
            self.txt_key_file.setEnabled(False)
            self.txt_key_manual.setEnabled(True)
    
    def decrypt_file(self):
        
        # Get file path
        file_path = self.txt_decrypt_file.text()
        if not file_path:
            QMessageBox.warning(self, "Error", "Please select an encrypted file")
            return
        
        # Get key
        key = None
        if self.key_option_group.checkedId() == 1:
            # Load key from file
            key_path = self.txt_key_file.text()
            if not key_path:
                QMessageBox.warning(self, "Error", "Please select a key file")
                return
            
            try:
                with open(key_path, 'rb') as f:
                    key = f.read()
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Failed to read key file: {str(e)}")
                return
        else:
            # Load key from text input
            key_text = self.txt_key_manual.text()
            if not key_text:
                QMessageBox.warning(self, "Error", "Please enter a base64 encoded key")
                return
            
            try:
                key = base64.b64decode(key_text)
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Invalid base64 key: {str(e)}")
                return
        
        # Get output location
        output_dir = self.txt_decrypt_output.text()
        if not output_dir:
            QMessageBox.warning(self, "Error", "Please select an output location")
            return
        
        # Decrypt file
        try:
            # Read encrypted file
            with open(file_path, 'rb') as f:
                encrypted_data = f.read()
            
            # Decrypt data
            decrypted_data = self.security_manager.decrypt_with_aes(key, encrypted_data)
            
            # Determine output filename
            file_name = os.path.basename(file_path)
            if file_name.endswith('.enc'):
                file_name = file_name[:-4]  # Remove .enc extension
            
            output_path = os.path.join(output_dir, file_name)
            
            # Save decrypted file
            with open(output_path, 'wb') as f:
                f.write(decrypted_data)
            
            self.lbl_decrypt_status.setText(f"File successfully decrypted to: {output_path}")
            self.lbl_decrypt_status.setStyleSheet("color: green; margin-top: 10px;")
            
            # Ask if user wants to open the file
            reply = QMessageBox.question(self, "Decryption Complete", 
                                        f"File decrypted successfully to:\n{output_path}\n\nDo you want to open it?",
                                        QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            
            if reply == QMessageBox.Yes:
                # Open the file with default application
                import subprocess
                
                if sys.platform == 'win32':
                    os.startfile(output_path)
                elif sys.platform == 'darwin':  # macOS
                    subprocess.call(['open', output_path])
                else:  # Linux
                    subprocess.call(['xdg-open', output_path])
            
        except Exception as e:
            self.lbl_decrypt_status.setText(f"Error: {str(e)}")
            self.lbl_decrypt_status.setStyleSheet("color: red; margin-top: 10px;")
            QMessageBox.critical(self, "Decryption Error", str(e))
    """
    
    # Add the methods before closeEvent
    insert_pos = match.start()
    return content[:insert_pos] + methods_to_add + content[insert_pos:]

def add_decryption_tab(main_window_py):
    """Add the decryption tab to MainWindow."""
    # Create backup
    backup_file(main_window_py)
    
    # Read file
    with open(main_window_py, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Check if QButtonGroup is imported
    if 'QButtonGroup' not in content:
        # Add QButtonGroup to imports
        qwidgets_match = re.search(r'(from PyQt5\.QtWidgets import \(.*?\))', content, re.DOTALL)
        if qwidgets_match:
            qwidgets_import = qwidgets_match.group(1)
            if 'QButtonGroup' not in qwidgets_import:
                new_import = qwidgets_import.replace(')', ', QButtonGroup, QRadioButton)')
                content = content.replace(qwidgets_import, new_import)
    
    # Add imports if needed
    content = add_imports(content)
    
    # Add tab declaration
    content = add_tab_declaration(content)
    
    # Add tab to tab widget
    content = add_tab_to_tabwidget(content)
    
    # Add setup method call
    content = add_setup_method_call(content)
    
    # Add decryption methods
    content = add_decryption_methods(content)
    
    # Write updated content
    with open(main_window_py, 'w', encoding='utf-8') as f:
        f.write(content)
    
    print(f"Successfully added Decryption Arena tab to {main_window_py}")
    return True

def main():
    """Main function to add decryption tab to DecentraBrowser."""
    # Find DecentraBrowser installation directory
    base_dir = None
    possible_paths = [
        os.path.join(".", "decentrabrowser"),
        os.path.join("..", "decentrabrowser"),
        os.path.join(os.path.dirname(os.path.abspath(__file__)), "decentrabrowser")
    ]
    
    for path in possible_paths:
        if os.path.isdir(path):
            base_dir = path
            break
    
    if not base_dir:
        print("Error: Could not find DecentraBrowser directory.")
        print("Please run this script from the same directory as the 'decentrabrowser' folder.")
        return 1
    
    print(f"Found DecentraBrowser at: {base_dir}")
    
    # Target file
    main_window_py = os.path.join(base_dir, "client", "gui", "main_window.py")
    
    if not os.path.exists(main_window_py):
        print(f"Error: {main_window_py} not found.")
        return 1
    
    # Add decryption tab
    success = add_decryption_tab(main_window_py)
    
    if success:
        print("\nDecryption Arena tab added successfully!")
        print("Please restart DecentraBrowser to see the changes.")
    else:
        print("\nFailed to add Decryption Arena tab.")
        print("Please restore from a backup or reinstall DecentraBrowser.")
    
    return 0

if __name__ == "__main__":
    sys.exit(main())
