#!/usr/bin/env python3
"""
DecentraBrowser Direct File Download Utility

This standalone script allows downloading files from DecentraBrowser domains
without requiring the full client. It serves as a backup in case the main client's
download functionality isn't working properly.
"""

import os
import sys
import requests
import socket
import json
import base64
import logging
import time
from pathlib import Path

# Set up logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger("DecentraDownload")

# Constants
CENTRAL_SERVER = "http://jcmc.serveminecraft.net/cent.php"
DEFAULT_DOWNLOAD_DIR = os.path.join(os.path.expanduser("~"), "DecentraDownloads")


def resolve_domain(domain_name):
    """Resolve a domain to IP and port."""
    try:
        # Query the central server
        check_url = f"{CENTRAL_SERVER}?check={domain_name}"
        logger.info(f"Resolving domain: {domain_name}")
        logger.info(f"Check URL: {check_url}")
        
        response = requests.get(check_url, timeout=10)
        
        if response.status_code != 200:
            return False, f"Central server error: HTTP {response.status_code}"
        
        # Parse the response
        try:
            data = response.json()
            if not data.get('success'):
                return False, data.get('error', 'Unknown error')
            
            domain_info = data.get('domain')
            if not domain_info:
                return False, "No domain information returned"
            
            # Extract IP and port
            ip = domain_info.get('ip')
            port = domain_info.get('port')
            
            if not ip or not port:
                return False, "Domain record missing IP or port"
            
            return True, (ip, int(port))
        
        except json.JSONDecodeError:
            return False, "Invalid JSON response from central server"
    
    except Exception as e:
        logger.error(f"Error resolving domain: {str(e)}")
        return False, f"Error: {str(e)}"


def download_file(domain_name, file_name, download_dir=None):
    """Download a file from a domain."""
    try:
        if download_dir is None:
            download_dir = DEFAULT_DOWNLOAD_DIR
        
        # Create download directory if it doesn't exist
        os.makedirs(download_dir, exist_ok=True)
        
        # Resolve domain to get IP and port
        success, result = resolve_domain(domain_name)
        if not success:
            logger.error(f"Failed to resolve domain: {result}")
            return False, result
        
        ip, port = result
        logger.info(f"Resolved {domain_name} to {ip}:{port}")
        
        # Construct URL for file download
        url = f"http://{ip}:{port}/file/{file_name}"
        logger.info(f"Downloading from URL: {url}")
        
        # Download the file
        try:
            response = requests.get(url, stream=True, timeout=30)
            
            if response.status_code == 200:
                # Save the file
                file_path = os.path.join(download_dir, file_name)
                with open(file_path, 'wb') as f:
                    for chunk in response.iter_content(chunk_size=8192):
                        if chunk:
                            f.write(chunk)
                
                logger.info(f"Downloaded file saved to: {file_path}")
                return True, file_path
            else:
                logger.error(f"Failed to download file: HTTP {response.status_code}")
                return False, f"HTTP Error: {response.status_code}"
        
        except requests.exceptions.RequestException as e:
            logger.error(f"Request error: {str(e)}")
            return False, f"Connection error: {str(e)}"
    
    except Exception as e:
        logger.error(f"Error downloading file: {str(e)}")
        return False, f"Error: {str(e)}"


def list_domain_files(domain_name):
    """List files available on a domain."""
    try:
        # Resolve domain to get IP and port
        success, result = resolve_domain(domain_name)
        if not success:
            logger.error(f"Failed to resolve domain: {result}")
            return False, result
        
        ip, port = result
        
        # Construct URL for domain info
        url = f"http://{ip}:{port}/info"
        logger.info(f"Getting info from URL: {url}")
        
        # Get domain info
        response = requests.get(url, timeout=10)
        
        if response.status_code == 200:
            try:
                data = response.json()
                files = data.get('files', [])
                
                if not files:
                    logger.info("No files found on domain")
                    return True, []
                
                logger.info(f"Found {len(files)} files on domain")
                return True, files
            
            except json.JSONDecodeError:
                logger.error("Invalid JSON response from domain server")
                return False, "Invalid response from domain server"
        else:
            logger.error(f"Failed to get domain info: HTTP {response.status_code}")
            return False, f"HTTP Error: {response.status_code}"
    
    except Exception as e:
        logger.error(f"Error listing domain files: {str(e)}")
        return False, f"Error: {str(e)}"


def list_all_domains():
    """List all registered domains."""
    try:
        # Query the central server
        list_url = f"{CENTRAL_SERVER}?list=1"
        logger.info("Retrieving domain list from central server")
        
        response = requests.get(list_url, timeout=10)
        
        if response.status_code != 200:
            return False, f"Central server error: HTTP {response.status_code}"
        
        # Parse the response
        try:
            data = response.json()
            if not data.get('success'):
                return False, data.get('error', 'Unknown error')
            
            domains = data.get('domains', [])
            logger.info(f"Retrieved {len(domains)} domains")
            return True, domains
        
        except json.JSONDecodeError:
            return False, "Invalid JSON response from central server"
    
    except Exception as e:
        logger.error(f"Error listing domains: {str(e)}")
        return False, f"Error: {str(e)}"


def main():
    """Main function."""
    print("DecentraBrowser Direct File Download Utility")
    print("===========================================")
    
    # Check arguments
    if len(sys.argv) > 1:
        command = sys.argv[1]
        
        if command == "download" and len(sys.argv) >= 4:
            domain_name = sys.argv[2]
            file_name = sys.argv[3]
            
            download_dir = DEFAULT_DOWNLOAD_DIR
            if len(sys.argv) >= 5:
                download_dir = sys.argv[4]
            
            print(f"Downloading {file_name} from {domain_name}...")
            success, result = download_file(domain_name, file_name, download_dir)
            
            if success:
                print(f"Download successful: {result}")
                return 0
            else:
                print(f"Download failed: {result}")
                return 1
        
        elif command == "list" and len(sys.argv) >= 3:
            domain_name = sys.argv[2]
            print(f"Listing files on domain {domain_name}...")
            success, result = list_domain_files(domain_name)
            
            if success:
                if not result:
                    print("No files found on domain")
                else:
                    print(f"Found {len(result)} files:")
                    for i, file in enumerate(result, 1):
                        name = file.get('name', 'Unknown')
                        size = file.get('size', 0)
                        file_type = file.get('type', 'unknown')
                        print(f"{i}. {name} ({size} bytes, {file_type})")
                return 0
            else:
                print(f"Failed to list files: {result}")
                return 1
        
        elif command == "domains":
            print("Listing all available domains...")
            success, result = list_all_domains()
            
            if success:
                if not result:
                    print("No domains found")
                else:
                    print(f"Found {len(result)} domains:")
                    for i, domain in enumerate(result, 1):
                        name = domain.get('name', 'Unknown')
                        title = domain.get('title', name)
                        print(f"{i}. {name} - {title}")
                return 0
            else:
                print(f"Failed to list domains: {result}")
                return 1
        
        else:
            print("Invalid command or missing arguments")
    
    # Show usage
    print("
Usage:")
    print("  python decentraload.py download <domain_name> <file_name> [download_dir]")
    print("  python decentraload.py list <domain_name>")
    print("  python decentraload.py domains")
    print("
Examples:")
    print("  python decentraload.py download example.domain file.txt")
    print("  python decentraload.py download example.domain image.jpg ~/Downloads")
    print("  python decentraload.py list example.domain")
    print("  python decentraload.py domains")
    
    return 1


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