#!/usr/bin/env python3
"""
NEXUS OSINT Tool - Comprehensive Open Source Intelligence Framework
Inspired by Sherlock and other popular OSINT tools
"""

import argparse
import asyncio
import json
import sys
from colorama import Fore, Style, init
from modules.username_search import UsernameSearcher
from modules.web_scraper import WebScraper
from modules.email_investigator import EmailInvestigator
from modules.domain_analyzer import DomainAnalyzer
from modules.ip_analyzer import IPAnalyzer
from modules.web_interface import NEXUSWebInterface
from modules.config_validator import ConfigValidator
from modules.name_searcher import NameSearcher

# Initialize colorama for cross-platform colored output
init(autoreset=True)

def main():
    """Main CLI entry point"""
    return asyncio.run(async_main())

class NEXUSTool:
    """Main NEXUS OSINT tool class"""
    
    def __init__(self):
        # Initialize configuration validator
        self.config_validator = ConfigValidator()
        self.config = self.config_validator.load_and_validate_config()
        
        if not self.config:
            sys.exit(1)
        
        # Check API keys
        api_status = self.config_validator.check_api_keys()
        
        # Initialize OSINT modules
        self.username_searcher = UsernameSearcher()
        self.web_scraper = WebScraper()
        self.email_investigator = EmailInvestigator()
        self.domain_analyzer = DomainAnalyzer()
        self.ip_analyzer = IPAnalyzer()
        self.web_interface = NEXUSWebInterface()
        self.name_searcher = UsernameSearcher()
    
    def print_banner(self):
        """Print the enhanced tool banner"""
        banner = fr"""
{Fore.WHITE} _   _ _______  ___   _ ____     ___  ____ ___ _   _ _____ 
| \ | | ____\ \/ / | | / ___|   / _ \/ ___|_ _| \ | |_   _|
|  \| |  _|  \  /| | | \___ \  | | | \___ \| ||  \| | | |  
| |\  | |___ /  \| |_| |___) | | |_| |___) | || |\  | | |  
|_| \_|_____/_/\_\\___/|____/   \___/|____/___|_| \_| |_|  

{Fore.GREEN}API Configured: {sum(1 for k in self.config.get('api_keys', {}).values() if k)}/4{Style.RESET_ALL}

{Fore.GREEN}Configuration:{Style.RESET_ALL}
  - Config file: config.json
  - Output format: {self.config.get('output', {}).get('format', 'json')}
"""
        print(banner)
    
    async def search_usernames(self, usernames, output_file=None, verbose=False):
        """Search for usernames across social media platforms"""
        print(f"Searching for usernames: {', '.join(usernames)}")
        
        results = await self.username_searcher.search(usernames, verbose=verbose)
        
        if output_file:
            with open(output_file, 'w') as f:
                json.dump(results, f, indent=2)
            print(f"Results saved to {output_file}")
        
        # Enhanced summary output
        total_found = sum(result.get('total_found', 0) for result in results.values())
        total_checked = sum(result.get('total_checked', 0) for result in results.values())
        
        print(f"\n{Fore.CYAN}=== USERNAME SEARCH SUMMARY ==={Style.RESET_ALL}")
        print(f"{Fore.WHITE}Usernames checked: {len(usernames)}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Platforms searched: {total_checked}{Style.RESET_ALL}")
        print(f"{Fore.GREEN}Accounts found: {total_found}{Style.RESET_ALL}")
        
        if total_found > 0:
            print(f"\n{Fore.YELLOW}=== TOP FINDINGS ==={Style.RESET_ALL}")
            for username, result in results.items():
                if result.get('found_accounts'):
                    print(f"\n{Fore.CYAN}{username}:{Style.RESET_ALL}")
                    for account in result['found_accounts'][:3]:  # Show top 3
                        confidence = account.get('confidence', 0)
                        print(f"  {Fore.GREEN}* {account['site']}: {account['url']} (confidence: {confidence})")
        
        return results
    
    async def investigate_email(self, email, output_file=None, verbose=False):
        
        results = await self.email_investigator.investigate(email, verbose=verbose)
        
        if output_file:
            with open(output_file, 'w') as f:
                json.dump(results, f, indent=2)
        
        # Enhanced summary output
        summary = results.get('summary', {})
        print(f"\n{Fore.CYAN}=== EMAIL INVESTIGATION SUMMARY ==={Style.RESET_ALL}")
        print(f"{Fore.WHITE}Email: {summary.get('email', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Provider: {summary.get('provider', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Type: {summary.get('provider_type', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Verification Score: {summary.get('verification_score', 'N/A')}/100{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Disposable: {summary.get('is_disposable', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Breached: {summary.get('breached', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Risk Level: {Fore.RED}{summary.get('risk_level', 'N/A')}{Style.RESET_ALL}")
        
        if summary.get('breach_count', 0) > 0:
            print(f"\n{Fore.RED}[+] BREACH ALERT: Found in {summary.get('breach_count')} data breaches{Style.RESET_ALL}")
        
        if summary.get('social_associations', 0) > 0:
            print(f"{Fore.YELLOW}[+] Social associations found on {summary.get('social_associations')} platforms{Style.RESET_ALL}")
        
        return results
    
    async def analyze_domain(self, domain, output_file=None, verbose=False):
        """Analyze domain name"""
        print(f"Analyzing domain: {domain}")
        
        results = await self.domain_analyzer.analyze(domain, verbose=verbose)
        
        if output_file:
            with open(output_file, 'w') as f:
                json.dump(results, f, indent=2)
        
        # Enhanced summary output
        summary = results.get('summary', {})
        print(f"\n{Fore.CYAN}=== DOMAIN ANALYSIS SUMMARY ==={Style.RESET_ALL}")
        print(f"{Fore.WHITE}Domain: {summary.get('domain', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Registrar: {summary.get('registrar', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Domain Age: {summary.get('domain_age', 'N/A')} years{Style.RESET_ALL}")
        print(f"{Fore.WHITE}DNS Records: {summary.get('total_dns_records', 0)} across {summary.get('dns_record_types', 0)} types{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Subdomains Found: {summary.get('subdomains_found', 0)}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Technologies: {summary.get('technologies_detected', 0)} detected{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Security Score: {summary.get('security_score', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}SSL Valid: {summary.get('ssl_valid', 'N/A')}{Style.RESET_ALL}")
        
        # Show key technologies if found
        if results.get('analysis', {}).get('http', {}).get('https', {}).get('technologies'):
            techs = results['analysis']['http']['https']['technologies'][:5]
            if techs:
                print(f"\n{Fore.YELLOW}=== DETECTED TECHNOLOGIES ==={Style.RESET_ALL}")
                for tech in techs:
                    category = tech.get('category', 'Unknown')
                    name = tech.get('name', 'Unknown')
                    confidence = tech.get('confidence', 'Unknown')
                    print(f"  {Fore.GREEN}* {name} ({category}) - confidence: {confidence}")
        
        return results
    
    async def analyze_ip(self, ip_address, output_file=None, verbose=False):
        """Analyze IP address"""
        print(f"Analyzing IP: {ip_address}")
        
        results = await self.ip_analyzer.analyze(ip_address, verbose=verbose)
        
        if output_file:
            with open(output_file, 'w') as f:
                json.dump(results, f, indent=2)
        
        # Enhanced summary output
        summary = results.get('summary', {})
        validation = results.get('validation', {})
        print(f"\n{Fore.CYAN}=== IP ANALYSIS SUMMARY ==={Style.RESET_ALL}")
        print(f"{Fore.WHITE}IP Address: {summary.get('ip_address', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Type: {validation.get('type', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Private: {validation.get('is_private', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Location: {summary.get('city', 'N/A')}, {summary.get('country', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}ISP: {summary.get('isp', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Hostname: {summary.get('hostname', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Open Ports: {summary.get('open_ports_count', 0)}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Port Scan Risk: {summary.get('port_scan_risk', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}VPN/Proxy Risk: {summary.get('vpn_proxy_risk', 'N/A')}{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Abuse Confidence: {summary.get('abuse_confidence', 0)}%{Style.RESET_ALL}")
        print(f"{Fore.WHITE}Overall Risk: {Fore.RED}{summary.get('overall_risk', 'N/A')}{Style.RESET_ALL}")
        
        # Show open ports if found
        if results.get('analysis', {}).get('port_scan', {}).get('open_ports'):
            open_ports = results['analysis']['port_scan']['open_ports'][:10]
            if open_ports:
                print(f"\n{Fore.YELLOW}=== OPEN PORTS ==={Style.RESET_ALL}")
                for port_info in open_ports:
                    port = port_info.get('port', 'N/A')
                    service = port_info.get('service', 'N/A')
                    response_time = port_info.get('response_time', 0)
                    print(f"  {Fore.GREEN}* Port {port} ({service}) - {response_time}ms")
        
        # Show services if found
        services = summary.get('services', [])
        if services:
            print(f"\n{Fore.YELLOW}=== DETECTED SERVICES ==={Style.RESET_ALL}")
            for service in services:
                print(f"  {Fore.GREEN}* {service}")
        
        return results
    
    async def scrape_url(self, url, output_file=None, verbose=False):
        """Scrape URL and analyze content"""
        print(f"Scraping URL: {url}")
        
        # Check Ollama availability first
        self.web_scraper.ensure_ollama_setup()
        
        results = await self.web_scraper.scrape_url(url, verbose=verbose)
        
        if output_file:
            with open(output_file, 'w') as f:
                json.dump(results, f, indent=2)
            print(f"Results saved to {output_file}")
        
        # Display summary
        if "error" not in results:
            print(f"\n{Fore.CYAN}=== WEB SCRAPING SUMMARY ==={Style.RESET_ALL}")
            print(f"{Fore.WHITE}URL: {results.get('url', 'N/A')}{Style.RESET_ALL}")
            print(f"{Fore.WHITE}Title: {results.get('title', 'N/A')}{Style.RESET_ALL}")
            
            # AI Summary
            ai_summary = results.get('ai_summary', {})
            if ai_summary:
                if "error" not in ai_summary:
                    # Enhanced AI display
                    print(f"{Fore.GREEN}Main Topic: {ai_summary.get('main_topic', 'N/A')}{Style.RESET_ALL}")
                    print(f"{Fore.CYAN}Page Type: {ai_summary.get('page_type', 'N/A')}{Style.RESET_ALL}")
                    print(f"{Fore.WHITE}Content Quality: {ai_summary.get('content_quality', 'N/A')}{Style.RESET_ALL}")
                    print(f"{Fore.WHITE}Target Audience: {ai_summary.get('target_audience', 'N/A')}{Style.RESET_ALL}")
                    print(f"{Fore.YELLOW}Sentiment: {ai_summary.get('sentiment', 'N/A')}{Style.RESET_ALL}")
                    
                    # Enhanced entities display
                    entities = ai_summary.get('key_entities', [])
                    if entities:
                        print(f"{Fore.CYAN}Key Entities:{Style.RESET_ALL}")
                        for entity in entities[:5]:
                            if isinstance(entity, dict):
                                name = entity.get('name', 'Unknown')
                                entity_type = entity.get('type', 'unknown')
                                confidence = entity.get('confidence', 0)
                                print(f"  {Fore.GREEN}* {name} ({entity_type}) [confidence: {confidence}]{Style.RESET_ALL}")
                            else:
                                print(f"  {Fore.GREEN}* {str(entity)}{Style.RESET_ALL}")
                    
                    # Call to actions
                    ctas = ai_summary.get('call_to_actions', [])
                    if ctas:
                        print(f"{Fore.MAGENTA}Call to Actions:{Style.RESET_ALL}")
                        for cta in ctas[:3]:
                            print(f"  {Fore.GREEN}* {cta}{Style.RESET_ALL}")
                    
                    # Notable features
                    features = ai_summary.get('notable_features', [])
                    if features:
                        print(f"{Fore.BLUE}Notable Features:{Style.RESET_ALL}")
                        for feature in features[:3]:
                            print(f"  {Fore.GREEN}* {feature}{Style.RESET_ALL}")
                else:
                    # Use fallback summary if AI failed
                    fallback = ai_summary.get('fallback_summary', {})
                    if fallback:
                        print(f"{Fore.YELLOW}AI Analysis: {ai_summary.get('error', 'Failed')}{Style.RESET_ALL}")
                        print(f"{Fore.GREEN}Main Topic: {fallback.get('main_topic', 'N/A')}{Style.RESET_ALL}")
                        
                        entities = fallback.get('entities', [])
                        if entities:
                            # Handle both string and dict formats for fallback
                            entity_names = []
                            for entity in entities:
                                if isinstance(entity, dict):
                                    entity_names.append(entity.get('name', str(entity)))
                                else:
                                    entity_names.append(str(entity))
                            print(f"{Fore.WHITE}Entities: {', '.join(entity_names[:5])}{Style.RESET_ALL}")
                        
                        features = fallback.get('notable_features', [])
                        if features:
                            print(f"{Fore.WHITE}Features: {', '.join(features)}{Style.RESET_ALL}")
            else:
                print(f"{Fore.YELLOW}AI Analysis: Not available{Style.RESET_ALL}")
            
            # Content summary
            content = results.get('content', {})
            links_count = len(content.get('links', []))
            images_count = len(content.get('images', []))
            headings_count = len(content.get('headings', []))
            buttons_count = len(content.get('buttons', []))
            
            print(f"{Fore.WHITE}Links found: {links_count}{Style.RESET_ALL}")
            print(f"{Fore.WHITE}Images found: {images_count}{Style.RESET_ALL}")
            print(f"{Fore.WHITE}Headings: {headings_count}{Style.RESET_ALL}")
            print(f"{Fore.WHITE}Buttons/CTAs: {buttons_count}{Style.RESET_ALL}")
            
            # Show top links with better formatting
            if links_count > 0:
                print(f"\n{Fore.YELLOW}=== TOP LINKS ==={Style.RESET_ALL}")
                for link in content['links'][:5]:
                    text = link.get('text', 'No text')
                    url = link.get('url', '')
                    print(f"  {Fore.GREEN}* {text[:50]}{'...' if len(text) > 50 else ''}{Style.RESET_ALL}")
                    print(f"    {Fore.CYAN}→ {url}{Style.RESET_ALL}")
            
            # Show main headings
            if headings_count > 0:
                print(f"\n{Fore.YELLOW}=== PAGE STRUCTURE ==={Style.RESET_ALL}")
                for heading in content['headings'][:5]:
                    level = heading.get('level', 1)
                    text = heading.get('text', '')
                    indent = "  " * (level - 1)
                    print(f"  {Fore.GREEN}H{level}{indent}{text[:60]}{'...' if len(text) > 60 else ''}{Style.RESET_ALL}")
        
        return results
    
    def launch_web_interface(self):
        """Launch the web interface"""
        print(f"{Fore.GREEN}[+] Launching NEXUS Web Interface...{Style.RESET_ALL}")
        self.web_interface.run_server()

    def configure_settings(self):
        """Interactive configuration menu for API keys and settings"""
        print(f"\n{Fore.CYAN}=== NEXUS OSINT Configuration ==={Style.RESET_ALL}")
        print(f"{Fore.YELLOW}Configure your API keys and settings{Style.RESET_ALL}\n")
        
        try:
            while True:
                print(f"{Fore.WHITE}Configuration Options:{Style.RESET_ALL}")
                print(f"  {Fore.GREEN}1{Style.RESET_ALL}. Configure API Keys")
                print(f"  {Fore.GREEN}2{Style.RESET_ALL}. Configure Output Settings")
                print(f"  {Fore.GREEN}3{Style.RESET_ALL}. Configure Search Settings")
                print(f"  {Fore.GREEN}4{Style.RESET_ALL}. View Current Configuration")
                print(f"  {Fore.GREEN}5{Style.RESET_ALL}. Reset to Defaults")
                print(f"  {Fore.RED}0{Style.RESET_ALL}. Save and Exit")
                
                choice = input(f"\n{Fore.CYAN}Enter your choice (0-5): {Style.RESET_ALL}").strip()
                
                if choice == '0':
                    self.save_configuration()
                    break
                elif choice == '1':
                    self.configure_api_keys()
                elif choice == '2':
                    self.configure_output_settings()
                elif choice == '3':
                    self.configure_search_settings()
                elif choice == '4':
                    self.view_configuration()
                elif choice == '5':
                    self.reset_configuration()
                else:
                    print(f"{Fore.RED}Invalid choice. Please try again.{Style.RESET_ALL}")
                    
        except (EOFError, KeyboardInterrupt):
            print(f"\n{Fore.YELLOW}[!] Configuration cancelled{Style.RESET_ALL}")
            return

    def configure_api_keys(self):
        """Configure API keys"""
        print(f"\n{Fore.CYAN}=== API Key Configuration ==={Style.RESET_ALL}")
        print(f"{Fore.YELLOW}Enter your API keys (press Enter to skip):{Style.RESET_ALL}\n")
        
        try:
            api_keys = self.config.get('api_keys', {})
            
            # Shodan API Key
            current_shodan = api_keys.get('shodan', '')
            if current_shodan and 'HIDDEN' in current_shodan:
                current_shodan = '[HIDDEN]'
            new_shodan = input(f"Shodan API Key [{current_shodan}]: ").strip()
            if new_shodan:
                api_keys['shodan'] = new_shodan
            
            # AbuseIPDB API Key
            current_abuse = api_keys.get('abuseipdb', '')
            if current_abuse and 'HIDDEN' in current_abuse:
                current_abuse = '[HIDDEN]'
            new_abuse = input(f"AbuseIPDB API Key [{current_abuse}]: ").strip()
            if new_abuse:
                api_keys['abuseipdb'] = new_abuse
            
            # Hunter API Key
            current_hunter = api_keys.get('hunter', '')
            if current_hunter and 'HIDDEN' in current_hunter:
                current_hunter = '[HIDDEN]'
            new_hunter = input(f"Hunter API Key [{current_hunter}]: ").strip()
            if new_hunter:
                api_keys['hunter'] = new_hunter
            
            # HaveIBeenPwned API Key
            current_hibp = api_keys.get('haveibeenpwned', '')
            if current_hibp and 'HIDDEN' in current_hibp:
                current_hibp = '[HIDDEN]'
            new_hibp = input(f"HaveIBeenPwned API Key [{current_hibp}]: ").strip()
            if new_hibp:
                api_keys['haveibeenpwned'] = new_hibp
            
            self.config['api_keys'] = api_keys
            print(f"\n{Fore.GREEN}[+] API keys updated!{Style.RESET_ALL}")
            
        except (EOFError, KeyboardInterrupt):
            print(f"\n{Fore.YELLOW}[!] API key configuration cancelled{Style.RESET_ALL}")
            return

    def configure_output_settings(self):
        """Configure output settings"""
        print(f"\n{Fore.CYAN}=== Output Settings Configuration ==={Style.RESET_ALL}")
        
        try:
            output = self.config.get('output', {})
            
            # Output format
            current_format = output.get('format', 'json')
            new_format = input(f"Output format [{current_format}] (json/txt/csv): ").strip().lower()
            if new_format in ['json', 'txt', 'csv']:
                output['format'] = new_format
            
            # Verbose output
            current_verbose = output.get('verbose', True)
            verbose_str = 'yes' if current_verbose else 'no'
            new_verbose = input(f"Verbose output [{verbose_str}] (yes/no): ").strip().lower()
            if new_verbose in ['yes', 'no']:
                output['verbose'] = new_verbose == 'yes'
            
            # Save results
            current_save = output.get('save_results', True)
            save_str = 'yes' if current_save else 'no'
            new_save = input(f"Save results automatically [{save_str}] (yes/no): ").strip().lower()
            if new_save in ['yes', 'no']:
                output['save_results'] = new_save == 'yes'
            
            # Output directory
            current_dir = output.get('output_dir', 'results')
            new_dir = input(f"Output directory [{current_dir}]: ").strip()
            if new_dir:
                output['output_dir'] = new_dir
            
            self.config['output'] = output
            print(f"\n{Fore.GREEN}[+] Output settings updated!{Style.RESET_ALL}")
            
        except (EOFError, KeyboardInterrupt):
            print(f"\n{Fore.YELLOW}[!] Output settings configuration cancelled{Style.RESET_ALL}")
            return

    def configure_search_settings(self):
        """Configure search settings"""
        print(f"\n{Fore.CYAN}=== Search Settings Configuration ==={Style.RESET_ALL}")
        
        try:
            # Username search settings
            username = self.config.get('username_search', {})
            
            current_concurrent = username.get('max_concurrent', 20)
            new_concurrent = input(f"Max concurrent requests [{current_concurrent}] (1-50): ").strip()
            if new_concurrent.isdigit() and 1 <= int(new_concurrent) <= 50:
                username['max_concurrent'] = int(new_concurrent)
            
            current_timeout = username.get('timeout', 15)
            new_timeout = input(f"Request timeout (seconds) [{current_timeout}] (5-60): ").strip()
            if new_timeout.isdigit() and 5 <= int(new_timeout) <= 60:
                username['timeout'] = int(new_timeout)
            
            current_delay = username.get('request_delay', 0.5)
            new_delay = input(f"Request delay (seconds) [{current_delay}] (0.1-5.0): ").strip()
            try:
                delay_val = float(new_delay)
                if 0.1 <= delay_val <= 5.0:
                    username['request_delay'] = delay_val
            except ValueError:
                pass
            
            self.config['username_search'] = username
            print(f"\n{Fore.GREEN}[+] Search settings updated!{Style.RESET_ALL}")
            
        except (EOFError, KeyboardInterrupt):
            print(f"\n{Fore.YELLOW}[!] Configuration cancelled{Style.RESET_ALL}")
            return

    def view_configuration(self):
        """View current configuration"""
        print(f"\n{Fore.CYAN}=== Current Configuration ==={Style.RESET_ALL}")
        
        # API Keys
        api_keys = self.config.get('api_keys', {})
        print(f"\n{Fore.WHITE}API Keys:{Style.RESET_ALL}")
        for key, value in api_keys.items():
            if value and 'HIDDEN' not in value:
                display_value = value[:8] + "..." if len(value) > 8 else value
                print(f"  {Fore.GREEN}{key}{Style.RESET_ALL}: {display_value}")
            else:
                print(f"  {Fore.GREEN}{key}{Style.RESET_ALL}: [Not set]")
        
        # Output settings
        output = self.config.get('output', {})
        print(f"\n{Fore.WHITE}Output Settings:{Style.RESET_ALL}")
        for key, value in output.items():
            print(f"  {Fore.GREEN}{key}{Style.RESET_ALL}: {value}")
        
        # Search settings
        username = self.config.get('username_search', {})
        print(f"\n{Fore.WHITE}Username Search Settings:{Style.RESET_ALL}")
        for key, value in username.items():
            print(f"  {Fore.GREEN}{key}{Style.RESET_ALL}: {value}")

    def reset_configuration(self):
        """Reset configuration to defaults"""
        print(f"\n{Fore.YELLOW}=== Reset Configuration ==={Style.RESET_ALL}")
        confirm = input("Are you sure you want to reset all settings to defaults? (yes/no): ").strip().lower()
        
        if confirm == 'yes':
            self.config = self.config_validator.get_default_config()
            print(f"{Fore.GREEN}[+] Configuration reset to defaults!{Style.RESET_ALL}")
        else:
            print(f"{Fore.YELLOW}Reset cancelled.{Style.RESET_ALL}")

    def save_configuration(self):
        """Save configuration to file"""
        try:
            with open('config.json', 'w') as f:
                json.dump(self.config, f, indent=2)
            print(f"\n{Fore.GREEN}[+] Configuration saved to config.json{Style.RESET_ALL}")
            
            # Check API key status
            api_status = self.config_validator.check_api_keys()
            configured_count = sum(1 for k in self.config.get('api_keys', {}).values() if k and 'HIDDEN' not in k)
            print(f"{Fore.CYAN}[*] {configured_count}/4 API keys configured{Style.RESET_ALL}")
            
        except Exception as e:
            print(f"{Fore.RED}[-] Error saving configuration: {str(e)}{Style.RESET_ALL}")

async def async_main():
    """Main async function"""
    parser = argparse.ArgumentParser(
        description="NEXUS OSINT Tool - Comprehensive investigation tool",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  nexus --config
  nexus --username john_doe
  nexus --username user1 user2 --output results.json
  nexus --email example@domain.com
  nexus --domain example.com
  nexus --ip 192.168.1.1
  nexus --scrape https://example.com
  nexus --web
        """
    )
    
    parser.add_argument('--config', '-c', action='store_true', help='Configure API keys and settings')
    parser.add_argument('--username', '-u', nargs='+', help='Username(s) to search for')
    parser.add_argument('--email', '-e', help='Email address to investigate')
    parser.add_argument('--domain', '-d', help='Domain name to analyze')
    parser.add_argument('--ip', '-i', help='IP address to analyze')
    parser.add_argument('--scrape', '-s', help='URL to scrape and analyze with AI')
    parser.add_argument('--web', '-w', action='store_true', help='Launch web interface')
    parser.add_argument('--output', '-o', help='Output file for results (JSON format)')
    parser.add_argument('--verbose', '-v', action='store_true', help='Enable verbose output')
    parser.add_argument('--version', action='version', version='NEXUS OSINT Tool 2.0.0')
    
    args = parser.parse_args()
    
    # Initialize tool
    tool = NEXUSTool()
    tool.print_banner()
    
    # Perform investigations based on arguments
    if args.config:
        tool.configure_settings()
        return
    
    if not any([args.username, args.email, args.domain, args.ip, args.scrape, args.web]):
        print(f"{Fore.RED}[-] Error: No investigation target specified. Use --help for usage.{Style.RESET_ALL}")
        sys.exit(1)
    
    try:
        if args.username:
            await tool.search_usernames(args.username, args.output, args.verbose)
        
        if args.email:
            await tool.investigate_email(args.email, args.output, args.verbose)
        
        if args.domain:
            await tool.analyze_domain(args.domain, args.output, args.verbose)
        
        if args.ip:
            await tool.analyze_ip(args.ip, args.output, args.verbose)
        
        if args.scrape:
            await tool.scrape_url(args.scrape, args.output, args.verbose)
        
        if args.web:
            tool.launch_web_interface()
            return  # Don't print "Investigation completed" for web interface
        
                
        print(f"Investigation completed successfully!")
    
    except KeyboardInterrupt:
        print(f"\n{Fore.YELLOW}[!] Investigation interrupted by user{Style.RESET_ALL}")
        sys.exit(0)
    except Exception as e:
        print(f"{Fore.RED}[-] Error: {str(e)}{Style.RESET_ALL}")
        sys.exit(1)

if __name__ == "__main__":
    main()
