#!/usr/bin/env python3
"""
DecentraBrowser Domain Unregistration Feature

This script adds domain unregistration functionality to DecentraBrowser:
1. Adds an "Unregister" button to domain listings in the UI
2. Implements unregistration with the central server at jcmc.serveminecraft.net
3. Adds proper domain removal from the local DDNS

Usage:
    python domain_unregister.py
"""

import os
import sys
import shutil
import re

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

def add_unregister_method(client_py):
    """Add unregister_domain method to NetworkClient class."""
    with open(client_py, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Check if method already exists
    if "def unregister_domain" in content and "cent.php?unregister" in content:
        print("unregister_domain method already exists with central server support, skipping...")
        return True
    
    # Find a good place to add our method - after register_domain
    register_pattern = r'def register_domain\(self, domain\):.*?(?=\n    def|\Z)'
    match = re.search(register_pattern, content, re.DOTALL)
    
    if not match:
        print("Could not find register_domain method")
        return False
    
    register_method = match.group(0)
    insert_pos = content.find(register_method) + len(register_method)
    
    # Create unregister method to add
    unregister_method = """
    def unregister_domain(self, domain_name):
        
        try:
            logger.info(f"Attempting to unregister domain: {domain_name}")
            
            # First unregister from central server
            unregister_success = False
            
            try:
                # Direct unregistration with central server
                unregister_url = f"http://jcmc.serveminecraft.net/cent.php?unregister={domain_name}"
                
                # Log the URL
                logger.info(f"Unregistration URL: {unregister_url}")
                
                # Send request
                response = requests.get(unregister_url, timeout=15)
                
                # Log the response
                logger.info(f"Central server response code: {response.status_code}")
                logger.info(f"Central server response text: {response.text[:200]}")
                
                if response.status_code == 200:
                    try:
                        data = response.json()
                        unregister_success = data.get('success', False)
                        if unregister_success:
                            logger.info(f"Domain {domain_name} unregistered successfully from central server")
                        else:
                            logger.warning(f"Could not unregister from central server: {data.get('error', 'Unknown error')}")
                    except:
                        # Fallback for text response
                        if "success" in response.text.lower():
                            unregister_success = True
                            logger.info(f"Domain {domain_name} unregistered successfully (text response)")
                        else:
                            logger.warning(f"Could not unregister from central server: {response.text}")
                else:
                    logger.warning(f"Could not unregister from central server: HTTP {response.status_code}")
            except Exception as e:
                logger.warning(f"Error communicating with central server: {str(e)}")
            
            # Always try to remove from local DDNS regardless of central server response
            local_result = self.ddns.remove_entry(domain_name)
            
            if local_result[0]:
                logger.info(f"Domain {domain_name} removed from local DDNS")
                return True, "Domain unregistered successfully"
            else:
                if unregister_success:
                    return True, "Domain unregistered from central server but could not be removed locally"
                else:
                    return False, "Could not unregister domain completely"
                
        except Exception as e:
            logger.error(f"Unexpected error unregistering domain: {str(e)}")
            return False, f"Error: {str(e)}"
    """
    
    # Insert our method
    updated_content = content[:insert_pos] + unregister_method + content[insert_pos:]
    
    # Write the updated content
    with open(client_py, 'w', encoding='utf-8') as f:
        f.write(updated_content)
    
    print(f"Added unregister_domain method to NetworkClient in {client_py}")
    return True

def update_domains_table(main_window_py):
    """Update the domains table to add Unregister button."""
    with open(main_window_py, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Check if unregister button already exists
    if "btn_unregister" in content and "unregister_domain" in content:
        print("Unregister button already exists in domains table, skipping...")
        return True
    
    # Find the update_domains_table method
    method_pattern = r'def update_domains_table\(self, success, result\):.*?(?=\n    def|\Z)'
    match = re.search(method_pattern, content, re.DOTALL)
    
    if not match:
        print("Could not find update_domains_table method")
        return False
    
    method_code = match.group(0)
    
    # First add the unregister_domain method to the MainWindow class
    # Find a good place to add it
    file_selected_pattern = r'def file_selected\(self\):.*?(?=\n    def|\Z)'
    match = re.search(file_selected_pattern, content, re.DOTALL)
    
    if not match:
        print("Could not find file_selected method to add unregister_domain after it")
        return False
    
    file_selected_method = match.group(0)
    insert_pos = content.find(file_selected_method) + len(file_selected_method)
    
    # Create unregister_domain method to add
    unregister_method = """
    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}")
    """
    
    # Insert unregister method
    updated_content = content[:insert_pos] + unregister_method + content[insert_pos:]
    
    # Now modify update_domains_table method to add Unregister button
    # Look for the Actions cell code in the method
    actions_pattern = r'# Actions cell.*?actions_widget = QWidget\(\).*?actions_layout = QHBoxLayout\(actions_widget\).*?actions_layout\.setContentsMargins\(2, 2, 2, 2\)'
    match = re.search(actions_pattern, updated_content, re.DOTALL)
    
    if not match:
        print("Could not find Actions cell code in update_domains_table")
        return False
    
    actions_code = match.group(0)
    
    # Now find the part where buttons are added to the Actions cell
    # We'll need to add the Unregister button to both branches (in_ddns and not in_ddns)
    
    # Find the "in DDNS" condition and its actions layout
    in_ddns_pattern = r'if in_ddns:.*?btn_connect = QPushButton\("Connect"\).*?btn_p2p = QPushButton\("P2P"\).*?actions_layout\.addWidget\(btn_connect\).*?actions_layout\.addWidget\(btn_p2p\)'
    match = re.search(in_ddns_pattern, updated_content, re.DOTALL)
    
    if match:
        in_ddns_code = match.group(0)
        
        # Add Unregister button to in_ddns branch
        new_in_ddns_code = in_ddns_code + """
                    btn_unregister = QPushButton("Unregister")
                    btn_unregister.setProperty("domain", domain.full_name)
                    btn_unregister.clicked.connect(self.unregister_domain)
                    
                    actions_layout.addWidget(btn_unregister)"""
        
        updated_content = updated_content.replace(in_ddns_code, new_in_ddns_code)
    else:
        print("Could not find in_ddns condition in update_domains_table")
    
    # Find the "not in_ddns" condition (else branch)
    else_branch_pattern = r'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\)'
    match = re.search(else_branch_pattern, updated_content, re.DOTALL)
    
    if match:
        else_code = match.group(0)
        
        # No need to add Unregister button to domains not in DDNS
        # But we'll make sure the formatting is consistent
        pass
    else:
        print("Could not find else branch in update_domains_table")
    
    # Write the updated content
    with open(main_window_py, 'w', encoding='utf-8') as f:
        f.write(updated_content)
    
    print(f"Updated domains table with Unregister button in {main_window_py}")
    return True

def update_central_server_communication(ddns_py):
    """Add direct central server unregistration to DDNS class."""
    with open(ddns_py, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Check if method already exists
    if "unregister_with_central" in content:
        print("unregister_with_central method already exists in DDNS, skipping...")
        return True
    
    # Find a good place to add our method - after remove_entry
    remove_pattern = r'def remove_entry\(self, domain\):.*?(?=\n    def|\Z)'
    match = re.search(remove_pattern, content, re.DOTALL)
    
    if not match:
        print("Could not find remove_entry method in DDNS")
        return False
    
    remove_method = match.group(0)
    insert_pos = content.find(remove_method) + len(remove_method)
    
    # Create unregister method to add
    unregister_method = """
    def unregister_with_central(self, domain):
        
        try:
            import requests
            
            # Build unregistration URL
            unregister_url = f"http://jcmc.serveminecraft.net/cent.php?unregister={domain}"
            
            # Send request
            response = requests.get(unregister_url, timeout=15)
            
            if response.status_code == 200:
                try:
                    data = response.json()
                    if data.get('success'):
                        return True, "Domain unregistered from central server"
                    else:
                        return False, data.get('error', 'Unregistration failed')
                except:
                    if "success" in response.text.lower():
                        return True, "Domain unregistered from central server"
                    else:
                        return False, f"Unregistration failed: {response.text}"
            else:
                return False, f"HTTP error: {response.status_code}"
        except Exception as e:
            return False, f"Error: {str(e)}"
    """
    
    # Insert our method
    updated_content = content[:insert_pos] + unregister_method + content[insert_pos:]
    
    # Also update the remove_entry method to try unregistering with central server
    updated_remove_entry = remove_method.replace(
        'self.save()',
        """self.save()
        
        # Try to unregister with central server
        self.unregister_with_central(domain)"""
    )
    
    updated_content = updated_content.replace(remove_method, updated_remove_entry)
    
    # Write the updated content
    with open(ddns_py, 'w', encoding='utf-8') as f:
        f.write(updated_content)
    
    print(f"Added central server unregistration to DDNS in {ddns_py}")
    return True

def main():
    """Main function to add domain unregistration feature."""
    # Find DecentraBrowser installation directory
    base_dir = None
    possible_paths = [
        os.path.join(".", "decentrabrowser"),
        os.path.join("..", "decentrabrowser"),
        os.path.join(os.path.dirname(os.path.abspath(__file__)), "decentrabrowser")
    ]
    
    for path in possible_paths:
        if os.path.isdir(path):
            base_dir = path
            break
    
    if not base_dir:
        print("Error: Could not find DecentraBrowser directory.")
        print("Please run this script from the same directory as the 'decentrabrowser' folder.")
        return 1
    
    print(f"Found DecentraBrowser at: {base_dir}")
    
    # Target files
    client_py = os.path.join(base_dir, "client", "network", "client.py")
    main_window_py = os.path.join(base_dir, "client", "gui", "main_window.py")
    ddns_py = os.path.join(base_dir, "shared", "ddns.py")
    
    if not all(os.path.exists(f) for f in [client_py, main_window_py, ddns_py]):
        print("Error: Required files not found.")
        return 1
    
    # Create backups
    backup_file(client_py)
    backup_file(main_window_py)
    backup_file(ddns_py)
    
    # Add unregister_domain method to NetworkClient
    add_unregister_method(client_py)
    
    # Update domains table to add Unregister button
    update_domains_table(main_window_py)
    
    # Add central server unregistration to DDNS
    update_central_server_communication(ddns_py)
    
    print("\nDomain unregistration feature added successfully!")
    print("\nThis feature allows you to:")
    print("1. Unregister domains from both the central server and local DDNS")
    print("2. Remove your own active domain with confirmation")
    print("3. Keep your domain list clean and organized")
    
    print("\nPlease restart DecentraBrowser to use the new feature.")
    
    return 0

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