"""
Main GUI window for the DecentraBrowser client.
"""
import os
import sys
import time
from datetime import datetime
import threading
import mimetypes
import base64
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QPushButton, QLineEdit, QTabWidget, QTableWidget,
    QTableWidgetItem, QHeaderView, QFileDialog, QTextEdit, QSplitter,
    QStackedWidget, QListWidget, QListWidgetItem, QToolBar, QAction,
    QStatusBar, QDialog, QFormLayout, QSpinBox, QComboBox, QCheckBox,
    QProgressBar, QMenu, QMessageBox, QFrame, QInputDialog, QGroupBox
, QButtonGroup, QRadioButton)
from PyQt5.QtGui import QIcon, QPixmap, QFont, QColor, QPalette, QTextCursor
from PyQt5.QtCore import Qt, QSize, QThread, pyqtSignal, QTimer, QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView

from ...shared.utils import setup_logging, ensure_directory_exists, get_local_ip, get_data_dir
from ...shared.constants import GUI_TITLE, GUI_WIDTH, GUI_HEIGHT
from ...shared.constants import (
    CMD_SOURCES, CMD_DOWNLOAD, CMD_P2P, CMD_VISIT, CMD_HELP
)
from ..network.client import NetworkClient
from ..network.http_server import DomainServer
from ...shared.domain import Domain
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes

# Setup logger
logger = setup_logging('main_window')

class FilesAggregator(QThread):
    """Background thread for aggregating files from domains."""
    aggregation_complete = pyqtSignal(list)
    progress_update = pyqtSignal(str, int)
    
    def __init__(self, network_client):
        super().__init__()
        self.network_client = network_client
        self.is_running = False
        self.mode = "active"  # Default to active domains only
    
    def run(self):
        print("FilesAggregator thread started")
        self.is_running = True
        all_files = []
        
        try:
            # Start with a simple operation that won't block
            self.progress_update.emit("Initializing file aggregation...", 0)
            
            # Create a minimal sample file list
            sample_files = [
                {'name': 'example1.txt', 'domain': 'sample.test.file.domain', 'size': 1024, 'type': 'text/plain'},
                {'name': 'example2.jpg', 'domain': 'sample.test.file.domain', 'size': 2048, 'type': 'image/jpeg'}
            ]
            
            # Emit sample files to check if UI updates correctly
            self.progress_update.emit("Testing UI responsiveness...", 50)
            self.aggregation_complete.emit(sample_files)
            
            # Short sleep to ensure UI has time to respond
            import time
            time.sleep(0.5)
            
            # If we're still running, try to get actual domains
            if self.is_running:
                self.progress_update.emit("Getting domain list...", 70)
                success, result = self.network_client.get_sources(force_refresh=False)
                
                if success and result:
                    # Just get files from a single domain as a test
                    domains = list(result.items())[:1]  # Just the first domain
                    if domains:
                        domain_name, domain = domains[0]
                        
                        self.progress_update.emit(f"Checking domain {domain_name}...", 90)
                        try:
                            success, domain_info = self.network_client.get_domain_info(domain_name)
                            
                            if success and 'files' in domain_info and domain_info['files']:
                                # Add domain information to each file
                                for file in domain_info['files']:
                                    file['domain'] = domain_name
                                    all_files.append(file)
                        except Exception as e:
                            print(f"Error getting files from domain: {str(e)}")
            
            # Send final result, even if it's just the sample files
            self.progress_update.emit("Completing file aggregation...", 100)
            final_files = all_files if all_files else sample_files
            self.aggregation_complete.emit(final_files)
            
        except Exception as e:
            print(f"Error in FilesAggregator thread: {str(e)}")
            # Make sure we emit something even on error
            self.aggregation_complete.emit(sample_files)
        
        print("FilesAggregator thread finished")
        self.is_running = False
class RefreshDomainsThread(QThread):
    """Background thread for refreshing domains."""
    domains_refreshed = pyqtSignal(bool, object)
    
    def __init__(self, network_client):
        """Initialize the thread."""
        super().__init__()
        self.network_client = network_client
        self.is_running = False
        self.mode = "active"  # Default to active domains only
    
    def run(self):
        """Run the thread."""
        success, result = self.network_client.get_sources(force_refresh=True)
        self.domains_refreshed.emit(success, result)


class MainWindow(QMainWindow):
    """Main window for the DecentraBrowser client."""
    def safe_aggregate_files(self):
        """Safely aggregate files with error handling."""
        try:
            # Check if necessary UI components exist
            if not hasattr(self, 'tbl_files'):
                print("Files table doesn't exist yet, skipping aggregation")
                return
                
            self.aggregate_all_files()
        except Exception as e:
            logger.error(f"Error aggregating files: {str(e)}")
            print(f"Error aggregating files: {str(e)}")  # Console debug
            try:
                self.statusBar().showMessage(f"Error loading files: {str(e)}", 5000)
            except:
                pass  # If even showing the message fails, just continue
    def __init__(self, network_client, domain_server, security_manager, ddns, content_dir):
        """Initialize the main window."""
        super().__init__()
        
        self.network_client = network_client
        self.domain_server = domain_server
        self.security_manager = security_manager
        self.ddns = ddns
        self.content_dir = content_dir
        self.aggregate_all_files()
        # Windows state
        self.active_downloads = {}
        self.my_domain = None
        self.current_domain = None
        
        self.init_ui()
        self.connect_signals()
        self.files_aggregator = FilesAggregator(network_client)
        self.files_aggregator.aggregation_complete.connect(self.handle_aggregation_complete)
        self.files_aggregator.progress_update.connect(self.handle_aggregation_progress)
        self.file_refresh_timer = QTimer()
        self.file_refresh_timer.timeout.connect(self.aggregate_all_files)
        self.file_refresh_timer.start(60000)  # 60 seconds
        # Start domain refresh timer
        self.refresh_timer = QTimer()
        self.refresh_timer.timeout.connect(self.refresh_domains)
        
        
        # Start download status timer
        self.download_timer = QTimer()
        self.download_timer.timeout.connect(self.update_download_status)
        self.download_timer.start(1000)  # 1 second
       
        # Initial domain refresh
        self.refresh_domains()
        # Schedule file aggregation after GUI is shown
        
    def start_file_aggregation(self):
        """Start the file aggregation process in response to user click."""
        if hasattr(self, 'files_aggregator') and not self.files_aggregator.isRunning():
            # Get the scan mode
            mode = self.file_mode_combo.currentData()
            
            # Update UI
            self.statusBar().showMessage(f"Starting file aggregation in {mode} mode...", 2000)
            self.files_progress_bar.setVisible(True)
            self.files_progress_bar.setValue(0)
            self.btn_refresh_files.setEnabled(False)
            
            # Clear helper message from table if it exists
            if self.tbl_files.rowCount() == 1 and self.tbl_files.columnSpan(0, 0) > 1:
                self.tbl_files.setRowCount(0)
            
            # Pass the mode to the thread
            self.files_aggregator.mode = mode
            self.files_aggregator.start()
        
    def handle_aggregation_progress(self, message, progress):
        """Handle progress updates from the aggregator thread."""
        self.statusBar().showMessage(message, 2000)
        self.files_progress_bar.setValue(progress)
        
    def handle_aggregation_complete(self, files):
        """Handle completion of file aggregation."""
        # Update the Files tab with all files
        self.update_files_table(files, None)
        
        # Update status
        self.statusBar().showMessage(f"Found {len(files)} files from domains", 3000)
        self.lbl_files_count.setText(f"Files: {len(files)}")
        
        # Hide progress bar
        self.files_progress_bar.setVisible(False)
        self.btn_refresh_files.setEnabled(True)
        
        # If no files found, show message
        if len(files) == 0:
            self.tbl_files.setRowCount(1)
            message_item = QTableWidgetItem("No files found. Try changing scan mode or try again later.")
            message_item.setTextAlignment(Qt.AlignCenter)
            # Span all columns
            self.tbl_files.setSpan(0, 0, 1, 6)
            self.tbl_files.setItem(0, 0, message_item)
    def init_certificates_tab(self):
        """Initialize the certificates tab."""
        # Current implementation (if any)...
        
        # Add layout for certificate management
        cert_layout = QVBoxLayout()
        self.tab_certificates.setLayout(cert_layout)
        
        # Certificate info
        cert_info = QLabel("Manage certificates for secure communication.")
        cert_layout.addWidget(cert_info)
        
        # Current certificate status
        self.cert_status = QLabel("Certificate status: Unknown")
        cert_layout.addWidget(self.cert_status)
        
        # Button for creating certificates
        btn_layout = QHBoxLayout()
        cert_layout.addLayout(btn_layout)
        
        btn_create_cert = QPushButton("Create New Certificate")
        btn_create_cert.clicked.connect(self.create_certificate)
        btn_layout.addWidget(btn_create_cert)
        
        btn_view_cert = QPushButton("View Certificate")
        btn_view_cert.clicked.connect(self.view_certificate)
        btn_layout.addWidget(btn_view_cert)
        
        # Certificate details
        cert_details_layout = QVBoxLayout()
        cert_layout.addLayout(cert_details_layout)
        
        cert_details_label = QLabel("Certificate Details:")
        cert_details_layout.addWidget(cert_details_label)
        
        self.cert_details = QTextEdit()
        self.cert_details.setReadOnly(True)
        cert_details_layout.addWidget(self.cert_details)
        
        # Update certificate status
        self.update_certificate_status()
    def aggregate_all_files(self):
        """Query all domains and aggregate their files into the Files tab."""
        try:
            # Make sure UI components exist
            if not hasattr(self, 'tbl_files') or not hasattr(self, 'lbl_files_count'):
                print("Required UI components not ready")
                return
                
            self.statusBar().showMessage("Aggregating files from all domains...", 2000)
            
            # Get all domains
            success, result = self.network_client.get_sources(force_refresh=False)  # Don't force refresh
            if not success:
                self.statusBar().showMessage(f"Error refreshing domains: {result}", 5000)
                return
            
            domains = result
            all_files = []
            
            # For each domain, query its files
            for domain_name, domain in domains.items():
                # Skip domains with no IP or port
                if not domain.ip or not domain.port:
                    continue
                    
                # Get domain info (which includes files)
                try:
                    success, domain_info = self.network_client.get_domain_info(domain_name)
                    
                    if success and 'files' in domain_info and domain_info['files']:
                        # Add domain information to each file
                        for file in domain_info['files']:
                            file['domain'] = domain_name
                            all_files.append(file)
                except Exception as e:
                    logger.error(f"Error getting files from {domain_name}: {str(e)}")
                    # Continue with other domains even if one fails
                    continue
            
            # Update the Files tab with all files
            self.update_files_table(all_files, None)  # Pass None as domain_name to indicate multiple domains
            
            # Update status
            self.statusBar().showMessage(f"Found {len(all_files)} files from {len(domains)} domains", 3000)
            self.lbl_files_count.setText(f"Files: {len(all_files)}")
        except Exception as e:
            logger.error(f"Error in file aggregation: {str(e)}")
            print(f"Error in file aggregation: {str(e)}")  # Console debug
            self.statusBar().showMessage("Error loading files list", 5000)
    def create_certificate(self):
        """Create a new certificate for this domain."""
        try:
            if not self.my_domain:
                QMessageBox.warning(self, "Error", "You must have an active domain to create a certificate")
                return
            
            reply = QMessageBox.question(
                self, 
                "Create Certificate", 
                f"This will create a new certificate for {self.my_domain.full_name}.\nContinue?",
                QMessageBox.Yes | QMessageBox.No, 
                QMessageBox.Yes
            )
            
            if reply == QMessageBox.Yes:
                # Generate key pair
                private_key, public_key = self.security_manager.generate_rsa_keypair()
                
                # Save private key
                self.security_manager.save_private_key(private_key, "private_key.pem")
                
                # Save public key
                self.security_manager.save_public_key(public_key, "public_key.pem")
                
                # Generate certificate
                cert_path = self.security_manager.generate_certificate(
                    private_key, 
                    self.my_domain.full_name
                )
                
                # Update status
                self.update_certificate_status()
                
                QMessageBox.information(
                    self, 
                    "Certificate Created", 
                    f"Certificate for {self.my_domain.full_name} created successfully.\nSaved to: {cert_path}"
                )
        except Exception as e:
            logger.error(f"Error creating certificate: {str(e)}")
            QMessageBox.critical(self, "Error", f"Failed to create certificate: {str(e)}")
    def view_certificate(self):
        """View the current certificate details."""
        try:
            # Check if certificate exists
            if not self.my_domain:
                QMessageBox.warning(self, "Error", "You must have an active domain to view its certificate")
                return
            
            cert_path = os.path.join(self.security_manager.certs_dir, f"{self.my_domain.full_name}.cert")
            
            if not os.path.exists(cert_path):
                QMessageBox.warning(self, "Error", "No certificate found for this domain")
                return
            
            # Get certificate details
            fingerprint = self.security_manager.get_certificate_fingerprint(cert_path)
            
            # Show certificate details
            with open(cert_path, 'r') as f:
                cert_content = f.read()
            
            self.cert_details.setText(cert_content)
            
            # Show dialog with fingerprint
            QMessageBox.information(
                self, 
                "Certificate Fingerprint", 
                f"Certificate Fingerprint (SHA-256):\n{fingerprint}"
            )
        except Exception as e:
            logger.error(f"Error viewing certificate: {str(e)}")
            QMessageBox.critical(self, "Error", f"Failed to view certificate: {str(e)}")

    def update_certificate_status(self):
        """Update the certificate status display."""
        try:
            if not self.my_domain:
                self.cert_status.setText("Certificate status: No active domain")
                return
            
            cert_path = os.path.join(self.security_manager.certs_dir, f"{self.my_domain.full_name}.cert")
            
            if os.path.exists(cert_path):
                valid, message = self.security_manager.verify_certificate(cert_path, self.my_domain.full_name)
                
                if valid:
                    self.cert_status.setText(f"Certificate status: Valid for {self.my_domain.full_name}")
                    self.cert_status.setStyleSheet("color: green;")
                else:
                    self.cert_status.setText(f"Certificate status: Invalid - {message}")
                    self.cert_status.setStyleSheet("color: red;")
            else:
                self.cert_status.setText(f"Certificate status: No certificate for {self.my_domain.full_name}")
                self.cert_status.setStyleSheet("color: orange;")
        except Exception as e:
            logger.error(f"Error updating certificate status: {str(e)}")
            self.cert_status.setText(f"Certificate status: Error - {str(e)}")
            self.cert_status.setStyleSheet("color: red;")
    def decrypt_file(self, file_path, output_path=None):
        """Decrypt a file using its associated encryption key."""
        try:
            if not output_path:
                # Remove .enc extension for output path
                output_path = file_path[:-4] if file_path.endswith('.enc') else file_path + '.decrypted'
            
            # Get the key for this file
            success, key_or_error = self.security_manager.keychain_manager.get_key_for_file(os.path.basename(file_path))
            
            if not success:
                # Check if we can get the key from the domain that owns the file
                domain_name = self.current_domain_name
                if domain_name:
                    # Request key from the domain owner
                    key_success, key_result = self.network_client.request_file_key(domain_name, os.path.basename(file_path))
                    if key_success:
                        key_or_error = key_result
                        # Store the key for future use
                        self.security_manager.keychain_manager.receive_encrypted_key(
                            key_result, domain_name, os.path.basename(file_path)
                        )
                    else:
                        return False, f"Couldn't get decryption key: {key_result}"
                else:
                    return False, f"No key found for file: {key_or_error}"
            
            # Now try to decrypt
            with open(file_path, 'rb') as f:
                encrypted_data = f.read()
            
            # Decrypt the file
            decrypted_data = self.security_manager.decrypt_with_aes(key_or_error, encrypted_data)
            
            # Save decrypted file
            with open(output_path, 'wb') as f:
                f.write(decrypted_data)
            
            return True, output_path
        except Exception as e:
            logger.error(f"Error decrypting file: {str(e)}")
            return False, f"Decryption error: {str(e)}"
    def init_ui(self):
        """Initialize the user interface."""
        self.setWindowTitle(GUI_TITLE)
        self.setMinimumSize(GUI_WIDTH, GUI_HEIGHT)
        
        # Setup tabs
        self.tabs = QTabWidget()
        self.tab_domains = QWidget()
        self.tab_files = QWidget()
        self.tab_command = QWidget()
        self.tab_certs = QWidget()
        self.tab_decryption = QWidget()
        self.tab_browser = QWidget()
        
        self.tabs.addTab(self.tab_domains, "Domains")
        self.tabs.addTab(self.tab_files, "Files")
        self.tabs.addTab(self.tab_command, "Command")
        self.tabs.addTab(self.tab_certs, "Certificates")
        self.tabs.addTab(self.tab_decryption, "Decryption Arena")
        self.tab_keychain = QWidget()
        self.tabs.addTab(self.tab_keychain, "Keychain")
        self.tabs.addTab(self.tab_browser, "Browser")
        
        self.setCentralWidget(self.tabs)
        
        # Setup domains tab
        self.setup_domains_tab()
        
        # Setup files tab
        self.setup_files_tab()
        
        # Setup command tab
        self.setup_command_tab()
        
        # Setup certificates tab
        self.setup_certs_tab()
        
        
        # Setup decryption tab
        self.setup_decryption_tab()

        # Setup keychain tab
        self.setup_keychain_tab()
# Setup browser tab
        self.setup_browser_tab()
        
        # Setup toolbar
        self.setup_toolbar()
        
        # Setup status bar
        self.setup_status_bar()
        if self.domain_server:
            self.domain_server.content_dir = self.content_dir
        # Show the window
        self.show()
        self.heartbeat_timer = QTimer(self)
        self.heartbeat_counter = 0
        self.heartbeat_timer.timeout.connect(self.heartbeat)
        self.heartbeat_timer.start(1000)  # 1 second interval
    def heartbeat(self):
        """UI thread heartbeat to verify responsiveness."""
        self.heartbeat_counter += 1
        if self.heartbeat_counter % 5 == 0:  # Print every 5 seconds
            print(f"UI heartbeat: {self.heartbeat_counter} seconds")
    def setup_toolbar(self):
        """Setup the toolbar."""
        self.toolbar = QToolBar("Main Toolbar")
        self.toolbar.setIconSize(QSize(24, 24))
        self.addToolBar(self.toolbar)
        
        # Add actions
        self.action_refresh = QAction("Refresh", self)
        self.action_refresh.triggered.connect(self.refresh_domains)
        self.toolbar.addAction(self.action_refresh)
        
        self.action_create_domain = QAction("Create Domain", self)
        self.action_create_domain.triggered.connect(self.create_domain_dialog)
        self.toolbar.addAction(self.action_create_domain)
        
        self.action_create_file = QAction("Create File", self)
        self.action_create_file.triggered.connect(self.create_new_file)
        self.toolbar.addAction(self.action_create_file)
        
        self.action_settings = QAction("Settings", self)
        self.action_settings.triggered.connect(self.settings_dialog)
        self.toolbar.addAction(self.action_settings)
    
    def setup_status_bar(self):
        """Setup the status bar."""
        status_bar = self.statusBar()  # Get the QStatusBar from QMainWindow
        
        # Status indicators
        self.lbl_server_status = QLabel("Server: Offline")
        status_bar.addPermanentWidget(self.lbl_server_status)
        
        self.lbl_domains_count = QLabel("Domains: 0")
        status_bar.addPermanentWidget(self.lbl_domains_count)
        
        self.lbl_files_count = QLabel("Files: 0")
        status_bar.addPermanentWidget(self.lbl_files_count)
        
        # Update server status
        self.update_server_status()
    def manual_refresh_domains(self):
        """Manually refresh domains when button is clicked."""
        self.statusBar().showMessage("Manually refreshing domains...", 2000)
        
        # Create a non-blocking thread
        self.refresh_thread = RefreshDomainsThread(self.network_client)
        self.refresh_thread.domains_refreshed.connect(self.update_domains_table)
        self.refresh_thread.start()
    def setup_domains_tab(self):
        """Setup the domains tab."""
        layout = QVBoxLayout()
            # Add manual refresh button at the top
        refresh_layout = QHBoxLayout()
        refresh_btn = QPushButton("Refresh Domains")
        refresh_btn.clicked.connect(self.manual_refresh_domains)
        refresh_layout.addStretch()
        refresh_layout.addWidget(refresh_btn)
        layout.addLayout(refresh_layout)
        # Search and refresh bar
        search_layout = QHBoxLayout()
        self.txt_domain_search = QLineEdit()
        self.txt_domain_search.setPlaceholderText("Search domains...")
        self.btn_domain_search = QPushButton("Search")
        self.btn_domain_refresh = QPushButton("Refresh")
        
        search_layout.addWidget(self.txt_domain_search)
        search_layout.addWidget(self.btn_domain_search)
        search_layout.addWidget(self.btn_domain_refresh)
        
        layout.addLayout(search_layout)
        
        # Domains table
        self.tbl_domains = QTableWidget()
        self.tbl_domains.setColumnCount(7)
        self.tbl_domains.setHorizontalHeaderLabels([
            "Domain", "Title", "IP", "Port", "Status", "Files", "Actions"
        ])
        self.tbl_domains.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        
        layout.addWidget(self.tbl_domains)
        
        # Domain details
        details_layout = QVBoxLayout()
        
        self.lbl_domain_details = QLabel("No domain selected")
        details_layout.addWidget(self.lbl_domain_details)
        
        self.domain_details_widget = QWidget()
        self.domain_details_widget.setLayout(details_layout)
        self.domain_details_widget.setMaximumHeight(200)
        
        layout.addWidget(self.domain_details_widget)
        
        self.tab_domains.setLayout(layout)
    def simple_file_display(self):
        """Simple file display without network calls - for testing."""
        self.statusBar().showMessage("Loading sample files...", 2000)
        
        # Clear table
        self.tbl_files.setRowCount(0)
        
        # Add some sample files
        sample_files = [
            {"name": "example1.txt", "domain": "test.doc.file.domain", "size": 1024, "type": "Text"},
            {"name": "example2.jpg", "domain": "test.img.file.domain", "size": 2048, "type": "Image"}
        ]
        
        # Fill table
        for i, file in enumerate(sample_files):
            self.tbl_files.insertRow(i)
            
            name_item = QTableWidgetItem(file["name"])
            domain_item = QTableWidgetItem(file["domain"])
            size_item = QTableWidgetItem(f"{file['size']} bytes")
            type_item = QTableWidgetItem(file["type"])
            
            self.tbl_files.setItem(i, 0, name_item)
            self.tbl_files.setItem(i, 1, domain_item)
            self.tbl_files.setItem(i, 2, size_item)
            self.tbl_files.setItem(i, 3, type_item)
            
            # Actions cell
            actions_widget = QWidget()
            actions_layout = QHBoxLayout(actions_widget)
            actions_layout.setContentsMargins(2, 2, 2, 2)
            
            btn_download = QPushButton("Download")
            actions_layout.addWidget(btn_download)
            
            self.tbl_files.setCellWidget(i, 4, actions_widget)
        
        self.statusBar().showMessage("Sample files loaded", 3000) 
    def setup_files_tab(self):
        """Setup the files tab."""
        layout = QVBoxLayout()
        
        # Controls for file aggregation
        controls_layout = QHBoxLayout()
        
        self.file_mode_combo = QComboBox()
        self.file_mode_combo.addItem("Scan Active Domains Only", "active")
        self.file_mode_combo.addItem("Scan All Domains", "all")
        self.file_mode_combo.setCurrentIndex(0)  # Default to active domains
        
        self.btn_refresh_files = QPushButton("Refresh Files")
        self.btn_refresh_files.clicked.connect(self.start_file_aggregation)
        
        controls_layout.addWidget(QLabel("Scan Mode:"))
        controls_layout.addWidget(self.file_mode_combo)
        controls_layout.addStretch()
        controls_layout.addWidget(self.btn_refresh_files)
        
        layout.addLayout(controls_layout)
        
        # Add a progress bar for file aggregation
        self.files_progress_bar = QProgressBar()
        self.files_progress_bar.setVisible(False)
        layout.addWidget(self.files_progress_bar)
        
        # Files table
        self.tbl_files = QTableWidget()
        self.tbl_files.setColumnCount(6)
        self.tbl_files.setHorizontalHeaderLabels([
            "Name", "Domain", "Size", "Type", "Status", "Actions"
        ])
        self.tbl_files.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        
        layout.addWidget(self.tbl_files)
        
        # Download progress
        progress_layout = QHBoxLayout()
        
        self.lbl_download_status = QLabel("No active downloads")
        self.progress_download = QProgressBar()
        self.progress_download.setVisible(False)
        
        progress_layout.addWidget(self.lbl_download_status)
        progress_layout.addWidget(self.progress_download)
        
        layout.addLayout(progress_layout)
        
        # At startup, show a message instead of empty table
        self.tbl_files.setRowCount(1)
        message_item = QTableWidgetItem("Click 'Refresh Files' to load files from available domains")
        message_item.setTextAlignment(Qt.AlignCenter)
        # Span all columns
        self.tbl_files.setSpan(0, 0, 1, 6)
        self.tbl_files.setItem(0, 0, message_item)
        
        self.tab_files.setLayout(layout)
    
    def setup_command_tab(self):
        """Setup the command tab."""
        layout = QVBoxLayout()
        
        # Command output
        self.txt_command_output = QTextEdit()
        self.txt_command_output.setReadOnly(True)
        self.txt_command_output.setStyleSheet("background-color: #000; color: #0f0; font-family: monospace;")
        layout.addWidget(self.txt_command_output)
        
        # Command input
        input_layout = QHBoxLayout()
        self.lbl_command_prompt = QLabel(">")
        self.txt_command_input = QLineEdit()
        self.txt_command_input.setStyleSheet("font-family: monospace;")
        self.btn_command_send = QPushButton("Send")
        
        input_layout.addWidget(self.lbl_command_prompt)
        input_layout.addWidget(self.txt_command_input)
        input_layout.addWidget(self.btn_command_send)
        
        layout.addLayout(input_layout)
        
        self.tab_command.setLayout(layout)
    
    def setup_browser_tab(self):
        """Setup the browser tab."""
        layout = QVBoxLayout()
        
        # Address bar
        address_layout = QHBoxLayout()
        self.txt_browser_address = QLineEdit()
        self.txt_browser_address.setPlaceholderText("Enter domain name or command...")
        self.btn_browser_go = QPushButton("Go")
        
        address_layout.addWidget(self.txt_browser_address)
        address_layout.addWidget(self.btn_browser_go)
        
        layout.addLayout(address_layout)
        
        # Web view
        self.web_view = QWebEngineView()
        self.web_view.setHtml("<html><body><h1>DecentraBrowser</h1><p>Enter a domain name to browse.</p></body></html>")
        self.web_view.titleChanged.connect(self.handle_web_title_change)
        layout.addWidget(self.web_view)
        
        self.tab_browser.setLayout(layout)
    
    def setup_certs_tab(self):
        """Setup the certificates tab."""
        layout = QVBoxLayout()
        
        # Certificate management
        cert_layout = QHBoxLayout()
        
        # Left side - list of certificates
        cert_list_layout = QVBoxLayout()
        self.lst_certificates = QListWidget()
        
        cert_list_buttons = QHBoxLayout()
        self.btn_cert_import = QPushButton("Import")
        self.btn_cert_export = QPushButton("Export")
        cert_list_buttons.addWidget(self.btn_cert_import)
        cert_list_buttons.addWidget(self.btn_cert_export)
        
        cert_list_layout.addWidget(QLabel("Certificates"))
        cert_list_layout.addWidget(self.lst_certificates)
        cert_list_layout.addLayout(cert_list_buttons)
        
        # Right side - certificate details
        cert_details_layout = QVBoxLayout()
        self.txt_cert_details = QTextEdit()
        self.txt_cert_details.setReadOnly(True)
        
        cert_details_buttons = QHBoxLayout()
        self.btn_cert_verify = QPushButton("Verify")
        self.btn_cert_delete = QPushButton("Delete")
        cert_details_buttons.addWidget(self.btn_cert_verify)
        cert_details_buttons.addWidget(self.btn_cert_delete)
        
        cert_details_layout.addWidget(QLabel("Certificate Details"))
        cert_details_layout.addWidget(self.txt_cert_details)
        cert_details_layout.addLayout(cert_details_buttons)
        
        # Add to cert layout
        cert_layout.addLayout(cert_list_layout, 1)
        cert_layout.addLayout(cert_details_layout, 2)
        
        layout.addLayout(cert_layout)
        
        self.tab_certs.setLayout(layout)
        
        # Refresh certificate list
        self.refresh_certificates()
    
    def connect_signals(self):
        """Connect UI signals to slots."""
        # Domains tab
        self.btn_domain_search.clicked.connect(self.search_domains)
        self.btn_domain_refresh.clicked.connect(self.refresh_domains)
        self.tbl_domains.itemSelectionChanged.connect(self.domain_selected)
        
        # Files tab
        self.tbl_files.itemSelectionChanged.connect(self.file_selected)
        
        # Command tab
        self.btn_command_send.clicked.connect(self.send_command)
        self.txt_command_input.returnPressed.connect(self.send_command)
        
        # Browser tab
        self.btn_browser_go.clicked.connect(self.browser_go)
        self.txt_browser_address.returnPressed.connect(self.browser_go)
        
        # Certificates tab
        self.lst_certificates.itemSelectionChanged.connect(self.cert_selected)
        self.btn_cert_import.clicked.connect(self.import_certificate)
        self.btn_cert_export.clicked.connect(self.export_certificate)
        self.btn_cert_verify.clicked.connect(self.verify_certificate)
        self.btn_cert_delete.clicked.connect(self.delete_certificate)
    
    def browser_go(self):
        """Handle browser Go button."""
        address = self.txt_browser_address.text().strip()
        
        # Check if command
        if address.startswith('/'):
            self.process_url_command(address)
            return
        
        # Treat as domain
        self.navigate_to_domain(address)
    # Then add this method to the MainWindow class
    def handle_web_title_change(self, title):
        """Handle title changes in the embedded web browser."""
        if title.startswith("download://"):
            # Parse the download URL
            parts = title[11:].split('/')
            if len(parts) >= 2:
                domain_name = parts[0]
                file_name = '/'.join(parts[1:])
                
                # Download the file
                download_dir = os.path.expanduser("~/Downloads")
                success, result = self.network_client.download_file(
                    domain_name, file_name, download_dir
                )
                
                if success:
                    self.statusBar().showMessage(f"Downloaded {file_name} to {result}", 5000)
                else:
                    self.statusBar().showMessage(f"Download failed: {result}", 5000)
        else:
            # Update window title with page title
            self.setWindowTitle(f"DecentraBrowser - {title}")
    def process_url_command(self, command):
        """Process a command from the URL bar."""
        parts = command.strip().split()
        cmd = parts[0].lower()
        
        # Handle help command
        if cmd == '/help':
            # Process help command
            success, result = self.network_client.process_command(command)
            if success and isinstance(result, dict) and result.get('command') == '/help':
                self.show_help_dialog(result.get('help', {}))
            return
        
        # Handle visit command
        if cmd == '/visit' and len(parts) >= 2:
            domain_name = parts[1]
            # Optional time parameter
            visit_seconds = 0
            if len(parts) >= 3:
                try:
                    visit_seconds = int(parts[2])
                except ValueError:
                    pass
            
            # Visit the domain
            self.navigate_to_domain(domain_name)
            
            # If timer is set, schedule return to previous domain
            if visit_seconds > 0:
                prev_domain = self.current_domain
                QTimer.singleShot(visit_seconds * 1000, lambda: self.navigate_to_domain(prev_domain))
                
                # Show message about timer
                self.statusBar().showMessage(f"Visiting {domain_name} for {visit_seconds} seconds", 3000)
            
            return
        
        # Forward other commands to the command processor
        success, result = self.network_client.process_command(command)
        
        # Show result in status bar
        if success:
            if isinstance(result, dict):
                message = f"Command {cmd} executed successfully"
            else:
                message = str(result)
            self.statusBar().showMessage(message, 5000)
        else:
            self.statusBar().showMessage(f"Error: {result}", 5000)
        
        # Switch to command tab to show full result
        self.tabs.setCurrentIndex(2)  # Command tab
        
        # Add command to history
        self.txt_command_output.append(f"> {command}")
        
        # Format and add result to output
        if success:
            if isinstance(result, dict):
                if result.get('command') == '/sources':
                    self.txt_command_output.append(f"Found {result['count']} domains")
                    for domain in result['domains'][:5]:  # Show first 5
                        self.txt_command_output.append(f"  {domain['full_name']} - {domain.get('title', '')}")
                    if result['count'] > 5:
                        self.txt_command_output.append(f"  ...and {result['count'] - 5} more")
                
                elif result.get('command') == '/download':
                    self.txt_command_output.append(f"Downloading {result['file']} from {result['domain']}")
                    self.txt_command_output.append(f"Download ID: {result['download_id']}")
                
                elif result.get('command') == '/p2p':
                    self.txt_command_output.append(f"Message sent to {result['domain']}")
                    self.txt_command_output.append(f"Message: {result['message']}")
                    self.txt_command_output.append(f"Timer: {result['timer']} seconds")
            else:
                self.txt_command_output.append(str(result))
        else:
            self.txt_command_output.append(f"Error: {result}")
        
        # Scroll to bottom
        self.txt_command_output.moveCursor(QTextCursor.End)
    
    def navigate_to_domain(self, domain_name):
        """Navigate to a domain in the browser."""
        if not domain_name:
            return
        
        # Store current domain
        self.current_domain = domain_name
        
        # Update address bar
        self.txt_browser_address.setText(domain_name)
        
        # Resolve domain
        success, result = self.network_client.get_domain_info(domain_name)
        
        if success:
            domain_info = result
            
            # Create HTML content
            # Create HTML content
            html = f"""
                <html>
                <head>
                    <title>{domain_info.get('title', domain_name)}</title>
                    <style>
                        body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; }}
                        h1 {{ color: #333; }}
                        .domain-info {{ background-color: #f5f5f5; padding: 10px; border-radius: 5px; margin-bottom: 20px; }}
                        .files {{ display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; }}
                        .file-card {{ background-color: #fff; border: 1px solid #ddd; border-radius: 5px; padding: 10px; }}
                        .file-name {{ font-weight: bold; margin-bottom: 5px; }}
                        .file-size, .file-type {{ color: #666; font-size: 0.9em; }}
                        .download-btn {{ display: inline-block; background-color: #4CAF50; color: white; padding: 5px 10px; 
                                        text-decoration: none; border-radius: 3px; margin-top: 10px; cursor: pointer; }}
                    </style>
                    <script>
                        function downloadFile(fileName, domainName) {{
                            document.title = "DOWNLOAD:" + fileName + ":" + domainName;
                            setTimeout(() => {{ 
                                alert("Download requested: " + fileName + "\\nThe file will be downloaded in the background."); 
                            }}, 100);
                        }}
                    </script>
                </head>
                <body>
                """
            
            if 'files' in domain_info and domain_info['files']:
                html += '<h2>Available Files</h2><div class="files">'
                
                for file in domain_info['files']:
                    file_name = file['name']
                    file_size = file['size']
                    file_type = file.get('type', 'Unknown')
                    
                    html += f"""
                        <div class="file-card">
                            <div class="file-name">{file_name}</div>
                            <div class="file-size">Size: {file_size} bytes</div>
                            <div class="file-type">Type: {file_type}</div>
                            <button class="download-btn" 
                                    onclick="downloadFile('{file_name}', '{domain_name}')">Download</button>
                        </div>
                        """
                
                html += '</div>'
            else:
                html += '<p>No files available on this domain.</p>'
            
            html += """
            <script>
                // Handle links that start with /
                document.addEventListener('click', function(e) {
                    if (e.target.tagName === 'A' && e.target.getAttribute('href') && 
                        e.target.getAttribute('href').startsWith('/')) {
                        e.preventDefault();
                        window.location.href = e.target.getAttribute('href');
                    }
                });
            </script>
            </body>
            </html>
            """
            
            # Load HTML
            self.web_view.setHtml(html)
            
            # Switch to browser tab
            self.tabs.setCurrentIndex(4)  # Browser tab
            
            # Update status bar
            self.statusBar().showMessage(f"Connected to {domain_name}", 3000)
        else:
            error_html = f"""
            <html>
            <head>
                <title>Error</title>
                <style>
                    body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; }}
                    h1 {{ color: #d9534f; }}
                    .error {{ background-color: #f2dede; color: #a94442; padding: 15px; border-radius: 5px; }}
                </style>
            </head>
            <body>
                <h1>Connection Error</h1>
                <div class="error">
                    <p>Could not connect to domain: {domain_name}</p>
                    <p>Error: {result}</p>
                </div>
            </body>
            </html>
            """
            
            # Load error HTML
            self.web_view.setHtml(error_html)
            
            # Switch to browser tab
            self.tabs.setCurrentIndex(4)  # Browser tab
            
            # Update status bar
            self.statusBar().showMessage(f"Error connecting to {domain_name}: {result}", 5000)
    
    def show_help_dialog(self, help_data):
        """Show help dialog with command information."""
        dialog = QDialog(self)
        dialog.setWindowTitle("DecentraBrowser Commands")
        dialog.setMinimumSize(500, 300)
        
        layout = QVBoxLayout(dialog)
        
        # Add heading
        heading = QLabel("Available Commands")
        heading.setStyleSheet("font-size: 16px; font-weight: bold; margin-bottom: 10px;")
        layout.addWidget(heading)
        
        # Create scrollable text area
        help_text = QTextEdit()
        help_text.setReadOnly(True)
        
        # Format help text
        formatted_text = ""
        for cmd, description in help_data.items():
            formatted_text += f"<p><b>{cmd}</b>: {description}</p>"
        
        help_text.setHtml(formatted_text)
        layout.addWidget(help_text)
        
        # Add close button
        button_box = QHBoxLayout()
        close_button = QPushButton("Close")
        close_button.clicked.connect(dialog.accept)
        button_box.addStretch()
        button_box.addWidget(close_button)
        layout.addLayout(button_box)
        
        # Show dialog
        dialog.exec_()
    
    def create_new_file(self):
        """Create a new file in the content directory."""
        if not self.domain_server or not self.domain_server.is_running():
            QMessageBox.warning(self, "Error", "You must have an active domain to create files")
            return
            
        # Get filename
        filename, ok = QInputDialog.getText(self, "Create File", "Enter filename:")
        if not ok or not filename:
            return
        
        # Ensure filename has extension
        if '.' not in filename:
            filename += '.txt'
        
        # Create text editor dialog
        dialog = QDialog(self)
        dialog.setWindowTitle(f"Create File: {filename}")
        dialog.setMinimumSize(700, 500)
        
        layout = QVBoxLayout(dialog)
        
        # Text editor
        editor = QTextEdit()
        editor.setPlaceholderText("Enter file content here...")
        layout.addWidget(editor)
        
        # Buttons
        buttons = QHBoxLayout()
        save_btn = QPushButton("Save")
        cancel_btn = QPushButton("Cancel")
        
        buttons.addStretch()
        buttons.addWidget(save_btn)
        buttons.addWidget(cancel_btn)
        layout.addLayout(buttons)
        
        # Connect signals
        cancel_btn.clicked.connect(dialog.reject)
        
        def save_file():
            content = editor.toPlainText()
            if not content:
                QMessageBox.warning(dialog, "Error", "File content cannot be empty")
                return
                
            try:
                # Get full path in content directory
                file_path = os.path.join(self.content_dir, filename)
                
                # Create directory if needed
                os.makedirs(os.path.dirname(file_path), exist_ok=True)
                
                # Write content to file first as plain text
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
                    
                # Then encrypt the file
                with open(file_path, 'rb') as f:
                    plaintext = f.read()
                    
                # Generate AES key
                aes_key = self.security_manager.generate_aes_key()
                
                # Encrypt the file
                encrypted_data = self.security_manager.encrypt_with_aes(aes_key, plaintext)
                
                # Save encrypted file
                encrypted_path = file_path + '.enc'
                with open(encrypted_path, 'wb') as f:
                    f.write(encrypted_data)
                    
                # Remove original plain text file
                os.remove(file_path)
                
                # Update domain file count
                if self.my_domain:
                    self.my_domain.file_count = sum(1 for f in os.listdir(self.content_dir) if f.endswith('.enc'))
                    self.network_client.update_domain(self.my_domain.full_name, file_count=self.my_domain.file_count)
                
                QMessageBox.information(dialog, "Success", f"File {filename} created and encrypted")
                dialog.accept()
                
                # IMPORTANT FIX: Update files display immediately after creating a file
                # If this is our own domain, show the files
                if self.my_domain:
                    files = []
                    for file in os.listdir(self.content_dir):
                        if file.endswith('.enc'):
                            file_path = os.path.join(self.content_dir, file)
                            file_size = os.path.getsize(file_path)
                            file_name = file[:-4] if file.endswith('.enc') else file
                            file_type = mimetypes.guess_type(file_name)[0] or 'application/octet-stream'
                            
                            files.append({
                                'name': file_name,
                                'size': file_size,
                                'type': file_type
                            })
                            
                    self.update_files_table(files, self.my_domain.full_name)
                    
                # Also refresh domains to update file count
                self.refresh_domains()
                
            except Exception as e:
                QMessageBox.critical(dialog, "Error", f"Failed to create file: {str(e)}")
        
        save_btn.clicked.connect(save_file)
        dialog.exec_()
    
    def refresh_domains(self):
        """Refresh the domains list."""
        self.refresh_thread = RefreshDomainsThread(self.network_client)
        self.refresh_thread.domains_refreshed.connect(self.update_domains_table)
        self.refresh_thread.start()
        
        self.statusBar().showMessage("Refreshing domains...", 2000)
        self.aggregate_all_files()
    
    def update_domains_table(self, success, result):
        """Update the domains table with refreshed data."""
        if success:
            domains = result
            
            # Clear table
            self.tbl_domains.setRowCount(0)
            
            # Fill table
            for i, domain in enumerate(domains.values()):
                self.tbl_domains.insertRow(i)
                
                domain_item = QTableWidgetItem(domain.full_name)
                title_item = QTableWidgetItem(domain.title or "")
                ip_item = QTableWidgetItem(domain.ip or "")
                port_item = QTableWidgetItem(str(domain.port) if domain.port else "")
                
                # Determine status
                in_ddns = self.ddns.has_domain(domain.full_name)
                status_text = "In DDNS" if in_ddns else "Available"
                status_item = QTableWidgetItem(status_text)
                
                files_item = QTableWidgetItem(str(domain.file_count))
                
                # Add to table
                self.tbl_domains.setItem(i, 0, domain_item)
                self.tbl_domains.setItem(i, 1, title_item)
                self.tbl_domains.setItem(i, 2, ip_item)
                self.tbl_domains.setItem(i, 3, port_item)
                self.tbl_domains.setItem(i, 4, status_item)
                self.tbl_domains.setItem(i, 5, files_item)
                
                # Actions cell
                actions_widget = QWidget()
                actions_layout = QHBoxLayout(actions_widget)
                actions_layout.setContentsMargins(2, 2, 2, 2)
                
                if in_ddns:
                    btn_connect = QPushButton("Connect")
                    btn_connect.setProperty("domain", domain.full_name)
                    btn_connect.clicked.connect(self.connect_to_domain)
                    
                    btn_p2p = QPushButton("P2P")
                    btn_p2p.setProperty("domain", domain.full_name)
                    btn_p2p.clicked.connect(self.p2p_message_dialog)
                    
                    actions_layout.addWidget(btn_connect)
                    actions_layout.addWidget(btn_p2p)
                    btn_unregister = QPushButton("Unregister")
                    btn_unregister.setProperty("domain", domain.full_name)
                    btn_unregister.clicked.connect(self.unregister_domain)
                    
                    actions_layout.addWidget(btn_unregister)
                else:
                    btn_add = QPushButton("Add to DDNS")
                    btn_add.setProperty("domain", domain.full_name)
                    btn_add.clicked.connect(self.add_to_ddns)
                    
                    actions_layout.addWidget(btn_add)
                
                self.tbl_domains.setCellWidget(i, 6, actions_widget)
            
            # Update status bar
            self.lbl_domains_count.setText(f"Domains: {len(domains)}")
            
            # Update DDNS with new domains
            updated = self.ddns.update_from_registry(domains.values())
            if updated:
                self.statusBar().showMessage(f"Added {updated} new domains to DDNS", 3000)
        else:
            error = result
            self.statusBar().showMessage(f"Error refreshing domains: {error}", 5000)
    
    def search_domains(self):
        """Search domains by name or title."""
        search_text = self.txt_domain_search.text().lower()
        
        for i in range(self.tbl_domains.rowCount()):
            domain_name = self.tbl_domains.item(i, 0).text().lower()
            domain_title = self.tbl_domains.item(i, 1).text().lower()
            
            if search_text in domain_name or search_text in domain_title:
                self.tbl_domains.setRowHidden(i, False)
            else:
                self.tbl_domains.setRowHidden(i, True)
    
    def domain_selected(self):
        """Handle domain selection in the table."""
        selected_rows = self.tbl_domains.selectedItems()
        if not selected_rows:
            self.lbl_domain_details.setText("No domain selected")
            return
        
        row = selected_rows[0].row()
        domain_name = self.tbl_domains.item(row, 0).text()
        
        # IMPORTANT FIX: First check if this is our own domain
        if self.my_domain and self.my_domain.full_name == domain_name:
            # For our own domain, we can list files directly without network
            domain_info = self.my_domain.to_dict()
            files = []
            
            if os.path.exists(self.content_dir):
                for file in os.listdir(self.content_dir):
                    if file.endswith('.enc'):
                        file_path = os.path.join(self.content_dir, file)
                        file_size = os.path.getsize(file_path)
                        file_name = file[:-4] if file.endswith('.enc') else file
                        file_type = mimetypes.guess_type(file_name)[0] or 'application/octet-stream'
                        
                        files.append({
                            'name': file_name,
                            'size': file_size,
                            'type': file_type
                        })
            
            domain_info['files'] = files
            domain_info['file_count'] = len(files)
            
            # Update details label
            details_text = f"<h3>{domain_info.get('title', domain_name)} (Your Domain)</h3>"
            details_text += f"<p><b>Domain:</b> {domain_name}</p>"
            details_text += f"<p><b>Files:</b> {domain_info.get('file_count', 0)}</p>"
            
            if files:
                details_text += "<p><b>Available files:</b></p>"
                details_text += "<ul>"
                for file in files[:5]:  # Show first 5 files
                    details_text += f"<li>{file['name']} ({file['size']} bytes)</li>"
                if len(files) > 5:
                    details_text += f"<li>...and {len(files) - 5} more</li>"
                details_text += "</ul>"
            
            self.lbl_domain_details.setText(details_text)
            
            # Update files table
            self.update_files_table(files, domain_name)
            return
        
        # For other domains, proceed with network request
        success, result = self.network_client.get_domain_info(domain_name)
        if success:
            domain_info = result
            
            # Update details label
            details_text = f"<h3>{domain_info.get('title', domain_name)}</h3>"
            details_text += f"<p><b>Domain:</b> {domain_name}</p>"
            details_text += f"<p><b>Files:</b> {domain_info.get('file_count', 0)}</p>"
            
            if 'files' in domain_info:
                details_text += "<p><b>Available files:</b></p>"
                details_text += "<ul>"
                for file in domain_info['files'][:5]:  # Show first 5 files
                    details_text += f"<li>{file['name']} ({file['size']} bytes)</li>"
                if len(domain_info['files']) > 5:
                    details_text += f"<li>...and {len(domain_info['files']) - 5} more</li>"
                details_text += "</ul>"
            
            self.lbl_domain_details.setText(details_text)
            
            # Update files table if this domain has files
            self.update_files_table(domain_info.get('files', []), domain_name)
        else:
            self.lbl_domain_details.setText(f"Error getting domain details: {result}")
    
    def add_to_ddns(self):
        """Add a domain to the local DDNS."""
        sender = self.sender()
        domain_name = sender.property("domain")
        
        # Find domain in table
        for i in range(self.tbl_domains.rowCount()):
            if self.tbl_domains.item(i, 0).text() == domain_name:
                ip = self.tbl_domains.item(i, 2).text()
                port = self.tbl_domains.item(i, 3).text()
                
                # Add to DDNS
                success, message = self.ddns.add_entry(domain_name, ip, port)
                
                if success:
                    self.statusBar().showMessage(f"Added {domain_name} to DDNS", 3000)
                    
                    # Update row in table
                    status_item = QTableWidgetItem("In DDNS")
                    self.tbl_domains.setItem(i, 4, status_item)
                    
                    # Update actions cell
                    actions_widget = QWidget()
                    actions_layout = QHBoxLayout(actions_widget)
                    actions_layout.setContentsMargins(2, 2, 2, 2)
                    
                    btn_connect = QPushButton("Connect")
                    btn_connect.setProperty("domain", domain_name)
                    btn_connect.clicked.connect(self.connect_to_domain)
                    
                    btn_p2p = QPushButton("P2P")
                    btn_p2p.setProperty("domain", domain_name)
                    btn_p2p.clicked.connect(self.p2p_message_dialog)
                    
                    actions_layout.addWidget(btn_connect)
                    actions_layout.addWidget(btn_p2p)
                    
                    self.tbl_domains.setCellWidget(i, 6, actions_widget)
                else:
                    self.statusBar().showMessage(f"Error adding domain to DDNS: {message}", 5000)
                
                break
    
    def connect_to_domain(self):
        """Connect to a domain."""
        sender = self.sender()
        domain_name = sender.property("domain")
        
        # Initiate PFS session
        self.statusBar().showMessage(f"Connecting to {domain_name}...", 2000)
        
        success, result = self.network_client.pfs_initiate(domain_name)
        if success:
            self.statusBar().showMessage(f"Connected to {domain_name}", 3000)
            
            # Navigate to domain in browser
            self.navigate_to_domain(domain_name)
            
            # Get domain info to update files table
            success, domain_info = self.network_client.get_domain_info(domain_name)
            if success and 'files' in domain_info:
                self.update_files_table(domain_info['files'], domain_name)
        else:
            self.statusBar().showMessage(f"Error connecting to {domain_name}: {result}", 5000)
    
    def update_files_table(self, files, domain_name=None):
        """Update the files table with files from a domain or multiple domains."""
        # Clear table
        self.tbl_files.setRowCount(0)
        
        # Fill table
        for i, file in enumerate(files):
            self.tbl_files.insertRow(i)
            
            name_item = QTableWidgetItem(file['name'])
            
            # Get domain from file if domain_name is None (aggregated view)
            file_domain = domain_name if domain_name else file.get('domain', 'Unknown')
            domain_item = QTableWidgetItem(file_domain)
            
            size_item = QTableWidgetItem(str(file['size']) + " bytes")
            
            # Determine file type
            file_name = file['name']
            file_ext = os.path.splitext(file_name)[1]
            file_type = file.get('type', "Unknown")
            type_item = QTableWidgetItem(file_type)
            
            status_item = QTableWidgetItem("Available")
            
            # Add to table
            self.tbl_files.setItem(i, 0, name_item)
            self.tbl_files.setItem(i, 1, domain_item)
            self.tbl_files.setItem(i, 2, size_item)
            self.tbl_files.setItem(i, 3, type_item)
            self.tbl_files.setItem(i, 4, status_item)
            
            # Actions cell
            actions_widget = QWidget()
            actions_layout = QHBoxLayout(actions_widget)
            actions_layout.setContentsMargins(2, 2, 2, 2)
            
            btn_download = QPushButton("Download")
            # Use the domain from the file for the button
            actual_domain = file_domain
            actual_file = file['name']
            btn_download.clicked.connect(lambda checked, f=actual_file, d=actual_domain: self.download_file(d, f))
            
            actions_layout.addWidget(btn_download)
            
            self.tbl_files.setCellWidget(i, 5, actions_widget)
        
        # Update status bar
        self.lbl_files_count.setText(f"Files: {len(files)}")
    
    def file_selected(self):
        """Handle file selection in the table."""
        selected_rows = self.tbl_files.selectedItems()
        if not selected_rows:
            return
        
        row = selected_rows[0].row()
        file_name = self.tbl_files.item(row, 0).text()
        domain_name = self.tbl_files.item(row, 1).text()
        
        # Update status bar
        self.statusBar().showMessage(f"Selected {file_name} from {domain_name}", 3000)
    
    def unregister_domain(self):
        
        # Get domain from sender button
        sender = self.sender()
        domain_name = sender.property("domain")
        
        if not domain_name:
            self.statusBar().showMessage("No domain selected for unregistration", 3000)
            return
        
        # Confirm unregistration
        reply = QMessageBox.question(
            self, "Confirm Unregistration",
            f"Are you sure you want to unregister the domain '{domain_name}'?\n\n"
            "This will remove it from both the central server and your local DDNS.",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )
        
        if reply != QMessageBox.Yes:
            return
        
        # Handle special case if this is our own domain
        if self.my_domain and self.my_domain.full_name == domain_name:
            # Confirm again for own domain
            reply = QMessageBox.warning(
                self, "Unregister Own Domain",
                f"'{domain_name}' is your own active domain!\n\n"
                "Unregistering it will stop your domain server.\n"
                "Are you absolutely sure?",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No
            )
            
            if reply != QMessageBox.Yes:
                return
            
            # Stop domain server if running
            if self.domain_server.is_running():
                self.domain_server.stop()
            
            # Clear my_domain
            self.my_domain = None
            
            # Update status
            self.update_server_status()
        
        # Unregister domain
        self.statusBar().showMessage(f"Unregistering domain {domain_name}...", 2000)
        
        success, message = self.network_client.unregister_domain(domain_name)
        
        if success:
            self.statusBar().showMessage(f"Domain {domain_name} unregistered successfully", 3000)
            
            # Refresh domains table
            self.refresh_domains()
        else:
            self.statusBar().showMessage(f"Error unregistering domain: {message}", 5000)
            
            # Show error dialog
            QMessageBox.warning(self, "Unregistration Error", f"Error unregistering domain:\n{message}")

    def download_file(self, domain_name, file_name=None):
        """
        Download a file from a domain and optionally decrypt it.
        
        Args:
            domain_name (str): The domain name to download from
            file_name (str, optional): The file name to download. If None, will use selected file.
        """
        try:
            # If file_name is not provided, get it from the selected file in the table
            if file_name is None:
                selected_items = self.tbl_files.selectedItems()
                if not selected_items:
                    QMessageBox.warning(self, "Error", "No file selected for download")
                    return
                
                row = selected_items[0].row()
                file_name = self.tbl_files.item(row, 0).text()
                
                if not file_name:
                    QMessageBox.warning(self, "Error", "Invalid file selected")
                    return
            
            # Store the current domain for future reference (e.g., key requests)
            self.current_domain_name = domain_name
            
            # Show downloading status
            self.statusBar().showMessage(f"Downloading {file_name} from {domain_name}...", 5000)
            
            # Create downloads directory if it doesn't exist
            downloads_dir = os.path.join(os.path.expanduser("~"), ".decentrabrowser", 'downloads')
            os.makedirs(downloads_dir, exist_ok=True)
            
            # Download the file
            success, result = self.network_client.download_file(domain_name, file_name)
            
            if success:
                encrypted_file_path = result
                logger.info(f"File downloaded to: {encrypted_file_path}")
                
                # Ask if user wants to decrypt the file
                reply = QMessageBox.question(
                    self, 
                    "File Downloaded", 
                    f"The file {file_name} has been downloaded. Do you want to decrypt it now?",
                    QMessageBox.Yes | QMessageBox.No, 
                    QMessageBox.Yes
                )
                
                if reply == QMessageBox.Yes:
                    # Ask for the save location for the decrypted file
                    save_dir = os.path.join(os.path.expanduser("~"), "Downloads")
                    os.makedirs(save_dir, exist_ok=True)
                    
                    # Generate the save path with original filename (without .enc)
                    base_name = os.path.basename(file_name)
                    if base_name.endswith('.enc'):
                        base_name = base_name[:-4]
                    
                    save_path, _ = QFileDialog.getSaveFileName(
                        self, 
                        "Save Decrypted File", 
                        os.path.join(save_dir, base_name), 
                        "All Files (*.*)"
                    )
                    
                    if save_path:
                        # Show decryption status
                        self.statusBar().showMessage(f"Decrypting {file_name}...", 3000)
                        
                        # Decrypt the file
                        decrypt_success, decrypt_result = self.decrypt_file(encrypted_file_path, save_path)
                        
                        if decrypt_success:
                            self.statusBar().showMessage(f"File decrypted and saved to: {decrypt_result}", 5000)
                            
                            # Ask if user wants to open the file
                            open_reply = QMessageBox.question(
                                self, 
                                "Decryption Complete", 
                                "Do you want to open the decrypted file?",
                                QMessageBox.Yes | QMessageBox.No, 
                                QMessageBox.Yes
                            )
                            
                            if open_reply == QMessageBox.Yes:
                                import subprocess
                                # Open file with default application for the file type
                                try:
                                    if sys.platform == 'win32':
                                        os.startfile(decrypt_result)
                                    elif sys.platform == 'darwin':
                                        subprocess.call(['open', decrypt_result])
                                    else:
                                        subprocess.call(['xdg-open', decrypt_result])
                                except Exception as e:
                                    logger.error(f"Error opening file: {str(e)}")
                                    QMessageBox.warning(self, "Error", f"Could not open file: {str(e)}")
                        else:
                            QMessageBox.warning(self, "Decryption Failed", decrypt_result)
                            self.statusBar().showMessage("File downloaded but not decrypted", 5000)
                    else:
                        self.statusBar().showMessage("File downloaded but not decrypted (save cancelled)", 5000)
                else:
                    self.statusBar().showMessage(f"File downloaded to: {encrypted_file_path}", 5000)
                    
                    # Show the file location
                    QMessageBox.information(
                        self,
                        "Download Complete",
                        f"The encrypted file has been downloaded to:\n{encrypted_file_path}"
                    )
            else:
                QMessageBox.warning(self, "Download Failed", str(result))
                self.statusBar().showMessage("Download failed", 5000)
        except Exception as e:
            logger.error(f"Error downloading file: {str(e)}")
            QMessageBox.warning(self, "Error", f"Error downloading file: {str(e)}")
            self.statusBar().showMessage("Download failed", 5000)
        
    def update_download_status(self):
        """Update the status of active downloads."""
        if not self.active_downloads:
            self.progress_download.setVisible(False)
            self.lbl_download_status.setText("No active downloads")
            return
        
        # Check each download
        completed = []
        for download_id, download in self.active_downloads.items():
            success, status = self.network_client.get_download_status(download_id)
            if success:
                # Update progress
                progress = status.get('progress', 0)
                self.progress_download.setValue(int(progress))
                
                # Check if completed
                if status.get('status') == 'completed':
                    completed.append(download_id)
                    self.statusBar().showMessage(f"Download of {download['file']} completed", 3000)
                
                # Update label
                self.lbl_download_status.setText(
                    f"Downloading {download['file']}: {int(progress)}%"
                )
        
        # Remove completed downloads
        for download_id in completed:
            del self.active_downloads[download_id]
    
    def send_command(self):
        """Send a command to the network client."""
        command = self.txt_command_input.text()
        if not command:
            return
        
        # Add to output
        self.txt_command_output.append(f"> {command}")
        
        # Process command
        success, result = self.network_client.process_command(command)
        
        if success:
            # Format and add result to output
            if isinstance(result, dict):
                if result.get('command') == '/sources':
                    self.txt_command_output.append(f"Found {result['count']} domains")
                    for domain in result['domains'][:5]:  # Show first 5
                        self.txt_command_output.append(f"  {domain['full_name']} - {domain.get('title', '')}")
                    if result['count'] > 5:
                        self.txt_command_output.append(f"  ...and {result['count'] - 5} more")
                
                elif result.get('command') == '/download':
                    self.txt_command_output.append(f"Downloading {result['file']} from {result['domain']}")
                    self.txt_command_output.append(f"Download ID: {result['download_id']}")
                
                elif result.get('command') == '/p2p':
                    self.txt_command_output.append(f"Message sent to {result['domain']}")
                    self.txt_command_output.append(f"Message: {result['message']}")
                    self.txt_command_output.append(f"Timer: {result['timer']} seconds")
                    
                elif result.get('command') == '/help':
                    self.txt_command_output.append("Available commands:")
                    for cmd, desc in result.get('help', {}).items():
                        self.txt_command_output.append(f"  {cmd}: {desc}")
                        
                elif result.get('command') == '/visit':
                    self.txt_command_output.append(f"Visiting domain: {result['domain']}")
                    if result.get('seconds', 0) > 0:
                        self.txt_command_output.append(f"Will visit for {result['seconds']} seconds")
                    # Actually navigate to the domain
                    self.navigate_to_domain(result['domain'])
            else:
                self.txt_command_output.append(str(result))
        else:
            self.txt_command_output.append(f"Error: {result}")
        
        # Clear input
        self.txt_command_input.clear()
        
        # Scroll to bottom
        self.txt_command_output.moveCursor(QTextCursor.End)
    
    def p2p_message_dialog(self):
        """Open dialog for sending P2P messages."""
        sender = self.sender()
        domain_name = sender.property("domain")
        
        # Create dialog
        dialog = QDialog(self)
        dialog.setWindowTitle(f"P2P Message - {domain_name}")
        dialog.setMinimumSize(400, 300)
        
        layout = QVBoxLayout()
        
        # Message history
        history_label = QLabel(f"Message History with {domain_name}")
        message_history = self.network_client.get_message_history(domain_name)
        
        history_text = QTextEdit()
        history_text.setReadOnly(True)
        
        if message_history:
            for msg in message_history:
                sender_text = "You" if msg.get('sent', False) else domain_name
                timestamp = datetime.fromtimestamp(msg.get('timestamp', 0)).strftime('%H:%M:%S')
                history_text.append(f"[{timestamp}] {sender_text}: {msg.get('message', '')}")
        else:
            history_text.append("No message history")
        
        # Message input
        input_layout = QHBoxLayout()
        
        message_input = QTextEdit()
        message_input.setPlaceholderText("Type your message here...")
        message_input.setMaximumHeight(100)
        
        # Timer input
        timer_layout = QHBoxLayout()
        timer_label = QLabel("Timer (seconds):")
        timer_spin = QSpinBox()
        timer_spin.setMinimum(10)
        timer_spin.setMaximum(3600)
        timer_spin.setValue(300)
        
        timer_layout.addWidget(timer_label)
        timer_layout.addWidget(timer_spin)
        
        # Send button
        send_button = QPushButton("Send")
        
    def send_message():
        message = message_input.toPlainText()
        timer = timer_spin.value()
            
        if not message:
            return
            
            # Send message
        success, result = self.network_client.p2p_send_message(domain_name, message, timer)
            
        if success:
                # Add to history
            timestamp = datetime.now().strftime('%H:%M:%S')
            history_text.append(f"[{timestamp}] You: {message}")
                
                # Clear input
            message_input.clear()
                
            self.statusBar().showMessage(f"Message sent to {domain_name}", 3000)
        else:
            QMessageBox.warning(dialog, "Error", f"Failed to send message: {result}")
        
        send_button.clicked.connect(send_message)
        
        # Add widgets to layout
        layout.addWidget(history_label)
        layout.addWidget(history_text)
        layout.addWidget(QLabel("New Message:"))
        layout.addWidget(message_input)
        layout.addLayout(timer_layout)
        layout.addWidget(send_button)
        
        dialog.setLayout(layout)
        dialog.exec_()
    
    def create_domain_dialog(self):
        
        dialog = QDialog(self)
        dialog.setWindowTitle("Create Domain")
        dialog.setMinimumSize(400, 350)
        
        layout = QVBoxLayout()
        
        # Domain name inputs
        name_layout = QFormLayout()
        
        prefix_input = QLineEdit()
        main_input = QLineEdit()
        suffix_input = QLineEdit()
        
        name_layout.addRow("Prefix:", prefix_input)
        name_layout.addRow("Main:", main_input)
        name_layout.addRow("Suffix:", suffix_input)
        
        # Domain title
        title_input = QLineEdit()
        name_layout.addRow("Title:", title_input)
        
        # Port
        port_spin = QSpinBox()
        port_spin.setMinimum(1024)
        port_spin.setMaximum(65535)
        port_spin.setValue(8844)
        name_layout.addRow("Port:", port_spin)
        
        # Status indicator
        status_label = QLabel("")
        status_label.setStyleSheet("color: gray;")
        
        # Create buttons
        button_layout = QHBoxLayout()
        check_button = QPushButton("Check Availability")
        create_button = QPushButton("Create Domain")
        create_button.setEnabled(False)  # Disabled until checked
        
        button_layout.addWidget(check_button)
        button_layout.addWidget(create_button)
        
        def check_availability():
            prefix = prefix_input.text()
            main = main_input.text()
            suffix = suffix_input.text()
            
            if not prefix or not main or not suffix:
                QMessageBox.warning(dialog, "Error", "All domain name parts are required")
                return
            
            # Create a temporary domain
            temp_domain = Domain(
                prefix=prefix,
                main=main,
                suffix=suffix,
                ip=get_local_ip(),
                port=port_spin.value()
            )
            
            # Show checking status
            status_label.setText("Checking domain availability...")
            status_label.setStyleSheet("color: blue;")
            dialog.repaint()  # Force UI update
            
            # Check availability with central server
            try:
                # Direct check with central server
                import requests
                check_url = f"http://jcmc.serveminecraft.net/cent.php?check={temp_domain.full_name}"
                response = requests.get(check_url, timeout=10)
                
                if response.status_code == 200:
                    try:
                        data = response.json()
                        if data.get('available') is True:
                            # Domain is available
                            status_label.setText("✓ Domain is available!")
                            status_label.setStyleSheet("color: green; font-weight: bold;")
                            create_button.setEnabled(True)
                        else:
                            # Domain not available
                            reason = data.get('reason', 'Domain is already taken')
                            status_label.setText(f"✗ Not available: {reason}")
                            status_label.setStyleSheet("color: red;")
                            create_button.setEnabled(False)
                    except:
                        # Fallback for non-JSON response
                        if "available" in response.text.lower():
                            status_label.setText("✓ Domain is available!")
                            status_label.setStyleSheet("color: green; font-weight: bold;")
                            create_button.setEnabled(True)
                        else:
                            status_label.setText("✗ Domain is not available")
                            status_label.setStyleSheet("color: red;")
                            create_button.setEnabled(False)
                else:
                    # HTTP error
                    status_label.setText(f"⚠ Server error: HTTP {response.status_code}")
                    status_label.setStyleSheet("color: orange;")
                    create_button.setEnabled(False)
            except Exception as e:
                # Network error
                status_label.setText(f"⚠ Connection error: {str(e)}")
                status_label.setStyleSheet("color: orange;")
                create_button.setEnabled(False)
        
        check_button.clicked.connect(check_availability)
        
        def create_domain():
            prefix = prefix_input.text()
            main = main_input.text()
            suffix = suffix_input.text()
            title = title_input.text()
            port = port_spin.value()
            
            if not prefix or not main or not suffix:
                QMessageBox.warning(dialog, "Error", "All domain name parts are required")
                return
            
            # Create domain
            domain = Domain(
                prefix=prefix,
                main=main,
                suffix=suffix,
                ip=get_local_ip(),
                port=port
            )
            domain.title = title
            
            # Show registering status
            status_label.setText("Registering domain...")
            status_label.setStyleSheet("color: blue;")
            dialog.repaint()  # Force UI update
            
            # Register with central server directly
            try:
                import requests
                register_url = f"http://jcmc.serveminecraft.net/cent.php?register={domain.full_name}&ip={domain.ip}&port={port}"
                if title:
                    register_url += f"&title={title}"
                
                response = requests.get(register_url, timeout=10)
                
                if response.status_code == 200:
                    try:
                        data = response.json()
                        if data.get('success') is True:
                            # Successfully registered with central server
                            # Now register locally
                            
                            # Add to DDNS
                            self.ddns.add_entry(domain.full_name, domain.ip, domain.port)
                            
                            # Store as my domain
                            self.my_domain = domain
                            
                            # Start domain server if not running
                            if not self.domain_server.is_running():
                                self.domain_server.domain = domain
                                self.domain_server.port = port
                                self.domain_server.start()
                                
                                # Update status
                                self.update_server_status()
                            
                            self.statusBar().showMessage(f"Domain {domain.full_name} created and registered", 3000)
                            dialog.accept()
                            
                            # Refresh domains
                            self.refresh_domains()
                        else:
                            # Registration failed
                            error = data.get('error', 'Unknown error from central server')
                            QMessageBox.warning(dialog, "Error", f"Failed to register domain: {error}")
                    except:
                        # Fallback for non-JSON response
                        if "success" in response.text.lower():
                            # Assume success if the word appears in response
                            
                            # Add to DDNS
                            self.ddns.add_entry(domain.full_name, domain.ip, domain.port)
                            
                            # Store as my domain
                            self.my_domain = domain
                            
                            # Start domain server if not running
                            if not self.domain_server.is_running():
                                self.domain_server.domain = domain
                                self.domain_server.port = port
                                self.domain_server.start()
                                
                                # Update status
                                self.update_server_status()
                            self.add_domain_to_table(domain)
                            self.statusBar().showMessage(f"Domain {domain.full_name} created and registered", 3000)
                            dialog.accept()
                            
                            # Refresh domains
                            self.refresh_domains()
                        else:
                            QMessageBox.warning(dialog, "Error", f"Failed to register domain: {response.text}")
                else:
                    # HTTP error
                    QMessageBox.warning(dialog, "Error", f"Failed to register domain: HTTP {response.status_code}")
            except Exception as e:
                # Network error
                QMessageBox.warning(dialog, "Error", f"Network error registering domain: {str(e)}")
        
        create_button.clicked.connect(create_domain)
        
        # Add widgets to layout
        layout.addLayout(name_layout)
        layout.addWidget(status_label)
        layout.addLayout(button_layout)
        
        dialog.setLayout(layout)
        dialog.exec_()
        # New helper method
    def add_domain_to_table(self, domain):
        """Add a single domain to the domains table."""
        row = self.tbl_domains.rowCount()
        self.tbl_domains.insertRow(row)
        
        domain_item = QTableWidgetItem(domain.full_name)
        title_item = QTableWidgetItem(domain.title or "")
        ip_item = QTableWidgetItem(domain.ip or "")
        port_item = QTableWidgetItem(str(domain.port) if domain.port else "")
        
        # Determine status
        in_ddns = self.ddns.has_domain(domain.full_name)
        is_my_domain = (self.my_domain and self.my_domain.full_name == domain.full_name)
        
        if is_my_domain:
            status_text = "My Domain"
        elif in_ddns:
            status_text = "In DDNS"
        else:
            status_text = "Available"
            
        status_item = QTableWidgetItem(status_text)
        
        files_item = QTableWidgetItem(str(domain.file_count))
        
        # Add to table
        self.tbl_domains.setItem(row, 0, domain_item)
        self.tbl_domains.setItem(row, 1, title_item)
        self.tbl_domains.setItem(row, 2, ip_item)
        self.tbl_domains.setItem(row, 3, port_item)
        self.tbl_domains.setItem(row, 4, status_item)
        self.tbl_domains.setItem(row, 5, files_item)
        
        # Actions cell
        actions_widget = QWidget()
        actions_layout = QHBoxLayout(actions_widget)
        actions_layout.setContentsMargins(2, 2, 2, 2)
        
        if is_my_domain or in_ddns:
            btn_connect = QPushButton("Connect")
            btn_connect.setProperty("domain", domain.full_name)
            btn_connect.clicked.connect(self.connect_to_domain)
            
            btn_p2p = QPushButton("P2P")
            btn_p2p.setProperty("domain", domain.full_name)
            btn_p2p.clicked.connect(self.p2p_message_dialog)
            
            actions_layout.addWidget(btn_connect)
            actions_layout.addWidget(btn_p2p)
            
            if is_my_domain:
                btn_unregister = QPushButton("Unregister")
                btn_unregister.setProperty("domain", domain.full_name)
                btn_unregister.clicked.connect(self.unregister_domain)
                actions_layout.addWidget(btn_unregister)
        else:
            btn_add = QPushButton("Add to DDNS")
            btn_add.setProperty("domain", domain.full_name)
            btn_add.clicked.connect(self.add_to_ddns)
            
            actions_layout.addWidget(btn_add)
        
        self.tbl_domains.setCellWidget(row, 6, actions_widget)
        
        # Select this row to highlight the new domain
        self.tbl_domains.selectRow(row)
    def check_availability():
        prefix = prefix_input.text()
        main = main_input.text()
        suffix = suffix_input.text()
                
        if not prefix or not main or not suffix:
            QMessageBox.warning(dialog, "Error", "All domain name parts are required")
            return
                
                # Create a temporary domain to check
        temp_domain = Domain(
            prefix=prefix,
            main=main,
            suffix=suffix,
            ip="0.0.0.0",  # Temporary IP
            port=0         # Temporary port
        )
                
                # Check domain availability
        self.statusBar().showMessage(f"Checking if {temp_domain.full_name} is available...", 2000)
        vailability, message = self.network_client.check_domain_availability(temp_domain)
                
        if availability:
            QMessageBox.information(dialog, "Domain Available", 
                                        f"The domain {temp_domain.full_name} is available!")
        else:
            QMessageBox.warning(dialog, "Domain Not Available", f"{message}")
            
        check_button.clicked.connect(check_availability)            
    def create_domain():
        prefix = prefix_input.text()
        main = main_input.text()
        suffix = suffix_input.text()
        title = title_input.text()
        port = port_spin.value()
            
        if not prefix or not main or not suffix:
            QMessageBox.warning(dialog, "Error", "All domain name parts are required")
            return
            
            # Create a temporary domain to check availability
        temp_domain = Domain(
            prefix=prefix,
            main=main,
            suffix=suffix,
            ip="0.0.0.0",  # Temporary IP
            port=0         # Temporary port
        )
            
            # Check domain availability
        self.statusBar().showMessage(f"Checking if {temp_domain.full_name} is available...", 2000)
        availability, message = self.network_client.check_domain_availability(temp_domain)
            
        if not availability:
            QMessageBox.warning(dialog, "Domain Not Available", f"{message}")
            return
            
            # Create domain
        domain = Domain(
            prefix=prefix,
            main=main,
            suffix=suffix,
            ip=get_local_ip(),
            port=port
        )
        domain.title = title
            
            # Register domain
        success, message = self.network_client.register_domain(domain)
            
        if success:
                # Add to DDNS
            self.ddns.add_entry(domain.full_name, domain.ip, domain.port)
                
                # Store as my domain
            self.my_domain = domain
                
                # Start domain server if not running
            if not self.domain_server.is_running():
                self.domain_server.domain = domain
                self.domain_server.port = port
                self.domain_server.start()
                    
                    # Update status
                self.update_server_status()
                
                self.statusBar().showMessage(f"Domain {domain.full_name} created and registered", 3000)
                dialog.accept()
                
                # Refresh domains
                self.refresh_domains()
            else:
                QMessageBox.warning(dialog, "Error", f"Failed to register domain: {message}")
        
        create_button.clicked.connect(create_domain)
        
        # Add widgets to layout
        layout.addLayout(name_layout)
        layout.addLayout(buttons_layout)
        dialog.setLayout(layout)
        dialog.exec_()
    
    def settings_dialog(self):
        """Open settings dialog."""
        dialog = QDialog(self)
        dialog.setWindowTitle("Settings")
        dialog.setMinimumSize(400, 300)
        
        layout = QVBoxLayout()
        
        # Server settings
        server_box = QGroupBox("Server Settings")
        server_layout = QFormLayout()
        
        port_spin = QSpinBox()
        port_spin.setMinimum(1024)
        port_spin.setMaximum(65535)
        port_spin.setValue(self.domain_server.port if self.domain_server else 8844)
        
        server_enabled = QCheckBox("Enable Server")
        server_enabled.setChecked(self.domain_server.is_running() if self.domain_server else False)
        
        server_layout.addRow("Port:", port_spin)
        server_layout.addRow(server_enabled)
        
        server_box.setLayout(server_layout)
        
        # Content settings
        content_box = QGroupBox("Content Settings")
        content_layout = QFormLayout()
        
        content_dir_input = QLineEdit(self.content_dir)
        content_dir_input.setReadOnly(True)
        
        browse_button = QPushButton("Browse")
        
        def browse_content_dir():
            dir_path = QFileDialog.getExistingDirectory(dialog, "Select Content Directory")
            if dir_path:
                content_dir_input.setText(dir_path)
        
        browse_button.clicked.connect(browse_content_dir)
        
        dir_layout = QHBoxLayout()
        dir_layout.addWidget(content_dir_input)
        dir_layout.addWidget(browse_button)
        
        content_layout.addRow("Content Directory:", dir_layout)
        
        content_box.setLayout(content_layout)
        
        # Save button
        save_button = QPushButton("Save Settings")
        
        def save_settings():
            # Update port
            new_port = port_spin.value()
            
            # Update server status
            if server_enabled.isChecked():
                if self.domain_server and not self.domain_server.is_running():
                    # Start server
                    self.domain_server.port = new_port
                    self.domain_server.start()
            else:
                if self.domain_server and self.domain_server.is_running():
                    # Stop server
                    self.domain_server.stop()
            
            # Update content directory
            new_content_dir = content_dir_input.text()
            if new_content_dir != self.content_dir:
                self.content_dir = new_content_dir
                if self.domain_server:
                    self.domain_server.content_dir = new_content_dir
            
            # Update status
            self.update_server_status()
            
            self.statusBar().showMessage("Settings saved", 3000)
            dialog.accept()
        
        save_button.clicked.connect(save_settings)
        
        # Add widgets to layout
        layout.addWidget(server_box)
        layout.addWidget(content_box)
        layout.addWidget(save_button)
        
        dialog.setLayout(layout)
        dialog.exec_()
    
    def update_server_status(self):
        """Update the server status indicator."""
        if self.domain_server and self.domain_server.is_running():
            self.lbl_server_status.setText(f"Server: Online (Port {self.domain_server.port})")
            if self.my_domain:
                self.lbl_server_status.setText(
                    f"Server: Online - {self.my_domain.full_name} (Port {self.domain_server.port})"
                )
        else:
            self.lbl_server_status.setText("Server: Offline")
    
    def cert_selected(self):
        """Handle certificate selection in the list."""
        selected_items = self.lst_certificates.selectedItems()
        if not selected_items:
            self.txt_cert_details.clear()
            return
        
        cert_name = selected_items[0].text()
        cert_path = os.path.join(self.security_manager.certs_dir, cert_name)
        
        try:
            # Get certificate details
            with open(cert_path, 'r') as f:
                cert_data = f.read()
            
            # Get fingerprint
            fingerprint = self.security_manager.get_certificate_fingerprint(cert_path)
            
            # Show details
            self.txt_cert_details.setText(f"Certificate: {cert_name}\n\nFingerprint: {fingerprint}\n\n{cert_data}")
            
        except Exception as e:
            self.txt_cert_details.setText(f"Error reading certificate: {str(e)}")
    
    def import_certificate(self):
        """Import a certificate."""
        file_path, _ = QFileDialog.getOpenFileName(self, "Import Certificate", "", "Certificates (*.cert *.pem)")
        if not file_path:
            return
        
        try:
            # Copy certificate to certs directory
            cert_name = os.path.basename(file_path)
            dest_path = os.path.join(self.security_manager.certs_dir, cert_name)
            
            with open(file_path, 'rb') as src_file:
                cert_data = src_file.read()
            
            with open(dest_path, 'wb') as dest_file:
                dest_file.write(cert_data)
            
            # Refresh certificate list
            self.refresh_certificates()
            
            self.statusBar().showMessage(f"Certificate {cert_name} imported", 3000)
            
        except Exception as e:
            QMessageBox.warning(self, "Error", f"Failed to import certificate: {str(e)}")
    
    def export_certificate(self):
        """Export a certificate."""
        selected_items = self.lst_certificates.selectedItems()
        if not selected_items:
            QMessageBox.warning(self, "Error", "No certificate selected")
            return
        
        cert_name = selected_items[0].text()
        cert_path = os.path.join(self.security_manager.certs_dir, cert_name)
        
        save_path, _ = QFileDialog.getSaveFileName(self, "Export Certificate", cert_name, "Certificates (*.cert *.pem)")
        if not save_path:
            return
        
        try:
            # Copy certificate to destination
            with open(cert_path, 'rb') as src_file:
                cert_data = src_file.read()
            
            with open(save_path, 'wb') as dest_file:
                dest_file.write(cert_data)
            
            self.statusBar().showMessage(f"Certificate exported to {save_path}", 3000)
            
        except Exception as e:
            QMessageBox.warning(self, "Error", f"Failed to export certificate: {str(e)}")
    
    def verify_certificate(self):
        """Verify a certificate."""
        selected_items = self.lst_certificates.selectedItems()
        if not selected_items:
            QMessageBox.warning(self, "Error", "No certificate selected")
            return
        
        cert_name = selected_items[0].text()
        cert_path = os.path.join(self.security_manager.certs_dir, cert_name)
        
        # Extract domain name from certificate name
        domain_name = cert_name.replace('.cert', '')
        
        try:
            # Verify certificate
            valid, message = self.security_manager.verify_certificate(cert_path, domain_name)
            
            if valid:
                QMessageBox.information(self, "Certificate Valid", f"Certificate for {domain_name} is valid.")
            else:
                QMessageBox.warning(self, "Certificate Invalid", f"Certificate validation failed: {message}")
            
        except Exception as e:
            QMessageBox.warning(self, "Error", f"Failed to verify certificate: {str(e)}")
    
    def delete_certificate(self):
        """Delete a certificate."""
        selected_items = self.lst_certificates.selectedItems()
        if not selected_items:
            QMessageBox.warning(self, "Error", "No certificate selected")
            return
        
        cert_name = selected_items[0].text()
        cert_path = os.path.join(self.security_manager.certs_dir, cert_name)
        
        # Confirm deletion
        confirm = QMessageBox.question(
            self, "Confirm Deletion",
            f"Are you sure you want to delete the certificate {cert_name}?",
            QMessageBox.Yes | QMessageBox.No
        )
        
        if confirm == QMessageBox.Yes:
            try:
                # Delete certificate
                os.remove(cert_path)
                
                # Refresh certificate list
                self.refresh_certificates()
                
                self.statusBar().showMessage(f"Certificate {cert_name} deleted", 3000)
                
            except Exception as e:
                QMessageBox.warning(self, "Error", f"Failed to delete certificate: {str(e)}")
    
    def refresh_certificates(self):
        """Refresh the certificate list."""
        self.lst_certificates.clear()
        
        try:
            # List certificates in directory
            cert_dir = self.security_manager.certs_dir
            if os.path.exists(cert_dir):
                cert_files = [f for f in os.listdir(cert_dir) if f.endswith('.cert')]
                
                for cert_file in cert_files:
                    self.lst_certificates.addItem(cert_file)
            
        except Exception as e:
            self.statusBar().showMessage(f"Error refreshing certificates: {str(e)}", 5000)
    
    
    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 setup_keychain_tab(self):
       
        layout = QVBoxLayout()
        
        # Description
        description = QLabel("Keychain Manager - Manage encryption keys and trusted servers")
        description.setStyleSheet("font-size: 14px; font-weight: bold; margin: 10px;")
        layout.addWidget(description)
        
        # Tabs for different sections
        keychain_tabs = QTabWidget()
        
        # Create tabs
        tab_shared_keys = QWidget()
        tab_received_keys = QWidget()
        tab_trusted_servers = QWidget()
        
        keychain_tabs.addTab(tab_shared_keys, "Shared Keys")
        keychain_tabs.addTab(tab_received_keys, "Received Keys")
        keychain_tabs.addTab(tab_trusted_servers, "Trusted Servers")
        
        # Setup shared keys tab
        shared_layout = QVBoxLayout()
        
        self.tbl_shared_keys = QTableWidget()
        self.tbl_shared_keys.setColumnCount(4)
        self.tbl_shared_keys.setHorizontalHeaderLabels([
            "Key ID", "File", "Created", "Actions"
        ])
        self.tbl_shared_keys.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        
        shared_buttons = QHBoxLayout()
        btn_refresh_shared = QPushButton("Refresh")
        btn_refresh_shared.clicked.connect(self.refresh_shared_keys)
        
        btn_export_key = QPushButton("Export Key")
        btn_export_key.clicked.connect(self.export_shared_key)
        
        btn_delete_shared = QPushButton("Delete Key")
        btn_delete_shared.clicked.connect(self.delete_shared_key)
        
        shared_buttons.addWidget(btn_refresh_shared)
        shared_buttons.addWidget(btn_export_key)
        shared_buttons.addWidget(btn_delete_shared)
        
        shared_layout.addWidget(self.tbl_shared_keys)
        shared_layout.addLayout(shared_buttons)
        tab_shared_keys.setLayout(shared_layout)
        
        # Setup received keys tab
        received_layout = QVBoxLayout()
        
        self.tbl_received_keys = QTableWidget()
        self.tbl_received_keys.setColumnCount(4)
        self.tbl_received_keys.setHorizontalHeaderLabels([
            "Key ID", "File", "From", "Actions"
        ])
        self.tbl_received_keys.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        
        received_buttons = QHBoxLayout()
        btn_refresh_received = QPushButton("Refresh")
        btn_refresh_received.clicked.connect(self.refresh_received_keys)
        
        btn_delete_received = QPushButton("Delete Key")
        btn_delete_received.clicked.connect(self.delete_received_key)
        
        received_buttons.addWidget(btn_refresh_received)
        received_buttons.addWidget(btn_delete_received)
        
        received_layout.addWidget(self.tbl_received_keys)
        received_layout.addLayout(received_buttons)
        tab_received_keys.setLayout(received_layout)
        
        # Setup trusted servers tab
        trusted_layout = QVBoxLayout()
        
        self.lst_trusted_servers = QListWidget()
        
        trusted_buttons = QHBoxLayout()
        btn_refresh_servers = QPushButton("Refresh")
        btn_refresh_servers.clicked.connect(self.refresh_trusted_servers)
        
        btn_add_server = QPushButton("Add Server")
        btn_add_server.clicked.connect(self.add_trusted_server)
        
        btn_remove_server = QPushButton("Remove Server")
        btn_remove_server.clicked.connect(self.remove_trusted_server)
        
        trusted_buttons.addWidget(btn_refresh_servers)
        trusted_buttons.addWidget(btn_add_server)
        trusted_buttons.addWidget(btn_remove_server)
        
        trusted_layout.addWidget(self.lst_trusted_servers)
        trusted_layout.addLayout(trusted_buttons)
        tab_trusted_servers.setLayout(trusted_layout)
        
        # Add tabs to layout
        layout.addWidget(keychain_tabs)
        
        # Initial data load
        self.refresh_shared_keys()
        self.refresh_received_keys()
        self.refresh_trusted_servers()
        
        self.tab_keychain.setLayout(layout)
    
    def refresh_shared_keys(self):
        
        try:
            # Get shared keys
            shared_keys = self.security_manager.keychain_manager.list_keys(received=False)
            
            # Clear table
            self.tbl_shared_keys.setRowCount(0)
            
            # Fill table
            for i, key_data in enumerate(shared_keys):
                self.tbl_shared_keys.insertRow(i)
                
                key_id = key_data.get('key_id', '')
                file_path = key_data.get('file_path', '')
                created = key_data.get('created', '')
                
                # Format date if it's ISO format
                if created and 'T' in created:
                    try:
                        dt = datetime.datetime.fromisoformat(created)
                        created = dt.strftime('%Y-%m-%d %H:%M:%S')
                    except:
                        pass
                
                self.tbl_shared_keys.setItem(i, 0, QTableWidgetItem(key_id))
                self.tbl_shared_keys.setItem(i, 1, QTableWidgetItem(file_path))
                self.tbl_shared_keys.setItem(i, 2, QTableWidgetItem(created))
                
                # Actions cell
                actions_widget = QWidget()
                actions_layout = QHBoxLayout(actions_widget)
                actions_layout.setContentsMargins(2, 2, 2, 2)
                
                btn_view = QPushButton("View")
                btn_view.setProperty("key_id", key_id)
                btn_view.clicked.connect(self.view_shared_key_details)
                
                actions_layout.addWidget(btn_view)
                
                self.tbl_shared_keys.setCellWidget(i, 3, actions_widget)
        except Exception as e:
            self.statusBar().showMessage(f"Error refreshing shared keys: {str(e)}", 5000)
    
    def refresh_received_keys(self):
        
        try:
            # Get received keys
            received_keys = self.security_manager.keychain_manager.list_keys(received=True)
            
            # Clear table
            self.tbl_received_keys.setRowCount(0)
            
            # Fill table
            for i, key_data in enumerate(received_keys):
                self.tbl_received_keys.insertRow(i)
                
                key_id = key_data.get('key_id', '')
                file_path = key_data.get('file_path', '')
                sender = key_data.get('received_from', '')
                
                self.tbl_received_keys.setItem(i, 0, QTableWidgetItem(key_id))
                self.tbl_received_keys.setItem(i, 1, QTableWidgetItem(file_path))
                self.tbl_received_keys.setItem(i, 2, QTableWidgetItem(sender))
                
                # Actions cell
                actions_widget = QWidget()
                actions_layout = QHBoxLayout(actions_widget)
                actions_layout.setContentsMargins(2, 2, 2, 2)
                
                btn_view = QPushButton("View")
                btn_view.setProperty("key_id", key_id)
                btn_view.clicked.connect(self.view_received_key_details)
                
                actions_layout.addWidget(btn_view)
                
                self.tbl_received_keys.setCellWidget(i, 3, actions_widget)
        except Exception as e:
            self.statusBar().showMessage(f"Error refreshing received keys: {str(e)}", 5000)
    
    def refresh_trusted_servers(self):
        
        try:
            # Get trusted servers
            trusted_servers = self.security_manager.keychain_manager.list_trusted_servers()
            
            # Clear list
            self.lst_trusted_servers.clear()
            
            # Fill list
            for server in trusted_servers:
                self.lst_trusted_servers.addItem(server)
        except Exception as e:
            self.statusBar().showMessage(f"Error refreshing trusted servers: {str(e)}", 5000)
    
    def view_shared_key_details(self):
        
        sender = self.sender()
        key_id = sender.property("key_id")
        
        # Get shared keys
        shared_keys = self.security_manager.keychain_manager.list_keys(received=False)
        
        # Find the key
        key_data = None
        for key in shared_keys:
            if key.get('key_id') == key_id:
                key_data = key
                break
        
        if not key_data:
            self.statusBar().showMessage(f"Key {key_id} not found", 5000)
            return
        
        # Display details
        details = f"Key ID: {key_id}\n"
        details += f"File: {key_data.get('file_path', '')}\n"
        details += f"Created: {key_data.get('created', '')}\n"
        details += f"Recipients: {', '.join(key_data.get('recipients', []))}\n"
        
        QMessageBox.information(self, "Key Details", details)
    
    def view_received_key_details(self):
        
        sender = self.sender()
        key_id = sender.property("key_id")
        
        # Get received keys
        received_keys = self.security_manager.keychain_manager.list_keys(received=True)
        
        # Find the key
        key_data = None
        for key in received_keys:
            if key.get('key_id') == key_id:
                key_data = key
                break
        
        if not key_data:
            self.statusBar().showMessage(f"Key {key_id} not found", 5000)
            return
        
        # Display details
        details = f"Key ID: {key_id}\n"
        details += f"File: {key_data.get('file_path', '')}\n"
        details += f"Received from: {key_data.get('received_from', '')}\n"
        details += f"Received: {key_data.get('received', '')}\n"
        
        QMessageBox.information(self, "Key Details", details)
    
    def export_shared_key(self):
        
        selected_items = self.tbl_shared_keys.selectedItems()
        if not selected_items:
            self.statusBar().showMessage("No key selected", 5000)
            return
        
        row = selected_items[0].row()
        key_id = self.tbl_shared_keys.item(row, 0).text()
        
        # Get list of trusted servers
        trusted_servers = self.security_manager.keychain_manager.list_trusted_servers()
        if not trusted_servers:
            QMessageBox.warning(self, "Export Key", "No trusted servers available. Add a server first.")
            return
        
        # Ask user to select a server
        server, ok = QInputDialog.getItem(
            self, "Select Recipient", "Export key to server:", trusted_servers, 0, False
        )
        
        if not ok or not server:
            return
        
        # Export the key
        success, result = self.security_manager.keychain_manager.export_encrypted_key(key_id, server)
        
        if success:
            # Save to file
            file_path, _ = QFileDialog.getSaveFileName(
                self, "Save Encrypted Key", "", "Encrypted Keys (*.ekey);;All Files (*.*)"
            )
            
            if file_path:
                with open(file_path, 'w') as f:
                    f.write(result)
                
                self.statusBar().showMessage(f"Key exported to {file_path}", 5000)
        else:
            QMessageBox.warning(self, "Export Error", result)
    
    def delete_shared_key(self):
        
        selected_items = self.tbl_shared_keys.selectedItems()
        if not selected_items:
            self.statusBar().showMessage("No key selected", 5000)
            return
        
        row = selected_items[0].row()
        key_id = self.tbl_shared_keys.item(row, 0).text()
        
        # Confirm deletion
        reply = QMessageBox.question(
            self, "Confirm Deletion",
            f"Are you sure you want to delete key {key_id}?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )
        
        if reply != QMessageBox.Yes:
            return
        
        # Delete the key
        success, message = self.security_manager.keychain_manager.delete_key(key_id, received=False)
        
        if success:
            self.statusBar().showMessage("Key deleted successfully", 5000)
            self.refresh_shared_keys()
        else:
            QMessageBox.warning(self, "Delete Error", message)
    
    def delete_received_key(self):
        
        selected_items = self.tbl_received_keys.selectedItems()
        if not selected_items:
            self.statusBar().showMessage("No key selected", 5000)
            return
        
        row = selected_items[0].row()
        key_id = self.tbl_received_keys.item(row, 0).text()
        
        # Confirm deletion
        reply = QMessageBox.question(
            self, "Confirm Deletion",
            f"Are you sure you want to delete key {key_id}?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )
        
        if reply != QMessageBox.Yes:
            return
        
        # Delete the key
        success, message = self.security_manager.keychain_manager.delete_key(key_id, received=True)
        
        if success:
            self.statusBar().showMessage("Key deleted successfully", 5000)
            self.refresh_received_keys()
        else:
            QMessageBox.warning(self, "Delete Error", message)
    
    def add_trusted_server(self):
        
        # Get server name
        name, ok = QInputDialog.getText(self, "Add Trusted Server", "Server name:")
        if not ok or not name:
            return
        
        # Get public key file
        file_path, _ = QFileDialog.getOpenFileName(
            self, "Select Public Key", "", "Public Keys (*.pub);;All Files (*.*)"
        )
        
        if not file_path:
            return
        
        try:
            # Read public key
            with open(file_path, 'rb') as f:
                public_key_pem = f.read()
            
            # Add to trusted servers
            success, message = self.security_manager.keychain_manager.add_trusted_server(name, public_key_pem)
            
            if success:
                self.statusBar().showMessage(f"Added {name} to trusted servers", 5000)
                self.refresh_trusted_servers()
            else:
                QMessageBox.warning(self, "Add Server Error", message)
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Failed to add server: {str(e)}")
    
    def remove_trusted_server(self):
        
        selected_items = self.lst_trusted_servers.selectedItems()
        if not selected_items:
            self.statusBar().showMessage("No server selected", 5000)
            return
        
        server_name = selected_items[0].text()
        
        # Confirm removal
        reply = QMessageBox.question(
            self, "Confirm Removal",
            f"Are you sure you want to remove {server_name} from trusted servers?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )
        
        if reply != QMessageBox.Yes:
            return
        
        # Remove the server
        success, message = self.security_manager.keychain_manager.remove_trusted_server(server_name)
        
        if success:
            self.statusBar().showMessage(f"Removed {server_name} from trusted servers", 5000)
            self.refresh_trusted_servers()
        else:
            QMessageBox.warning(self, "Remove Server Error", message)

    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:{output_path} Do 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))
    def closeEvent(self, event):
        """Handle window close event."""
    # Stop aggregator thread if running
        if hasattr(self, 'files_aggregator') and self.files_aggregator.isRunning():
            self.files_aggregator.stop()
            self.files_aggregator.wait()
        if self.domain_server and self.domain_server.is_running():
            self.domain_server.stop()
        
        # Unregister domain if registered
        if self.my_domain:
            self.network_client.unregister_domain(self.my_domain.full_name)
        
        # Accept close event
        event.accept()