"""
JSEye Pipeline - Main execution pipeline
"""

from pathlib import Path
from typing import Dict, Any
from rich.console import Console
from rich.table import Table

from .utils.fs import load_lines, ensure_dir, save_json
from .utils.logger import log_progress
from .modules.harvest import URLHarvester
from .modules.js_filter import JSFilter
from .modules.js_download import JSDownloader
from .modules.analyze_regex import RegexAnalyzer
from .modules.analyze_ast import ASTAnalyzer
from .modules.linkfinder import LinkFinderIntegration
from .modules.secrets import SecretsDetector
from .modules.sinks import SinkDetector
from .modules.correlate import CorrelationEngine

console = Console()

class JSEyePipeline:
    """Main JSEye execution pipeline"""
    
    def __init__(self, input_file: str, output_dir: str, args):
        self.input_file = Path(input_file)
        self.output_dir = Path(output_dir)
        self.args = args
        
        # Ensure output directory exists
        ensure_dir(self.output_dir)
        
        # Initialize modules
        self.harvester = URLHarvester(self.output_dir)
        self.js_filter = JSFilter(self.output_dir)
        self.js_downloader = JSDownloader(self.output_dir)
        self.regex_analyzer = RegexAnalyzer(self.output_dir)
        self.ast_analyzer = ASTAnalyzer(self.output_dir)
        self.linkfinder = LinkFinderIntegration(self.output_dir)
        self.secrets_detector = SecretsDetector(self.output_dir)
        self.sink_detector = SinkDetector(self.output_dir)
        self.correlation_engine = CorrelationEngine(self.output_dir)
        
        # Results storage
        self.results = {
            'domains_count': 0,
            'urls_harvested': 0,
            'js_files_found': 0,
            'js_files_analyzed': 0,
            'endpoints_found': 0,
            'secrets_found': 0,
            'sinks_found': 0,
            'high_confidence': 0
        }
    
    def load_domains(self) -> list:
        """Load domains from input file"""
        log_progress(f"Loading domains from {self.input_file}")
        
        domains = load_lines(self.input_file)
        if not domains:
            raise ValueError(f"No domains found in {self.input_file}")
        
        self.results['domains_count'] = len(domains)
        log_progress(f"Loaded {len(domains)} domains")
        
        return domains
    
    def run_harvest_phase(self, domains: list) -> list:
        """Run URL harvesting phase"""
        urls = self.harvester.harvest_urls(domains)
        self.results['urls_harvested'] = len(urls)
        return urls
    
    def run_js_filter_phase(self, urls: list) -> dict:
        """Run JavaScript filtering phase"""
        js_results = self.js_filter.filter_javascript_urls(urls)
        self.results['js_files_found'] = len(js_results['all_js'])
        return js_results
    
    def run_js_download_phase(self, js_urls: list) -> list:
        """Run JavaScript download phase"""
        if self.args.js_only:
            log_progress("Stopping after JS discovery (--js-only flag)")
            return []
        
        log_progress("Downloading JavaScript files...")
        downloaded_files = self.js_downloader.download_js_files(js_urls, max_files=100)
        
        successful_downloads = [f for f in downloaded_files if f['status'] == 'success']
        log_progress(f"Downloaded {len(successful_downloads)} JavaScript files")
        
        return successful_downloads
    
    def run_analysis_phase(self, js_files: list) -> dict:
        """Run analysis phase"""
        analysis_results = {
            'endpoints': [],
            'secrets': [],
            'sinks': [],
            'functions': []
        }
        
        # Regex analysis (always run unless regex-only specified)
        regex_results = self.regex_analyzer.analyze_files(js_files)
        analysis_results['endpoints'].extend(regex_results.get('endpoints', []))
        analysis_results['secrets'].extend(regex_results.get('secrets', []))
        analysis_results['sinks'].extend(regex_results.get('sinks', []))
        
        # AST analysis (unless skipped or regex-only)
        if not self.args.skip_ast and not self.args.regex_only:
            ast_results = self.ast_analyzer.analyze_files(js_files)
            analysis_results['endpoints'].extend(ast_results.get('endpoints', []))
            analysis_results['sinks'].extend(ast_results.get('sinks', []))
            analysis_results['functions'].extend(ast_results.get('functions', []))
        
        # Save combined analysis results
        save_json(analysis_results, self.output_dir / "combined_analysis.json")
        
        return analysis_results
    
    def run_secrets_phase(self, js_files: list) -> list:
        """Run secrets detection phase"""
        if self.args.no_secrets:
            log_progress("Skipping secrets detection (--no-secrets flag)")
            return []
        
        secrets = self.secrets_detector.run_mantra(js_files)
        return secrets
    
    def run_sinks_phase(self, js_files: list) -> list:
        """Run sink detection phase"""
        if self.args.no_sinks:
            log_progress("Skipping sink detection (--no-sinks flag)")
            return []
        
        sinks = self.sink_detector.detect_sinks(js_files)
        return sinks
    
    def run_linkfinder_phase(self, js_files: list) -> list:
        """Run LinkFinder phase"""
        endpoints = self.linkfinder.run_linkfinder(js_files)
        return endpoints
    
    def run_correlation_phase(self, analysis_results: dict) -> dict:
        """Run correlation phase"""
        if self.args.no_correlate:
            log_progress("Skipping correlation (--no-correlate flag)")
            return analysis_results
        
        correlated_results = self.correlation_engine.correlate_findings(analysis_results)
        return correlated_results
    
    def run(self) -> Dict[str, Any]:
        """Run the complete JSEye pipeline"""
        try:
            # Phase 1: Load domains
            domains = self.load_domains()
            
            # Phase 2: Harvest URLs
            urls = self.run_harvest_phase(domains)
            
            # Phase 3: Filter JavaScript files
            js_results = self.run_js_filter_phase(urls)
            
            # Early exit for --js-only
            if self.args.js_only:
                return self.results
            
            # Phase 4: Download JavaScript files
            js_files = self.run_js_download_phase(js_results['high_priority'] + js_results['medium_priority'])
            
            # Phase 5: Analysis
            analysis_results = self.run_analysis_phase(js_files)
            
            # Phase 6: LinkFinder
            linkfinder_endpoints = self.run_linkfinder_phase(js_files)
            analysis_results['endpoints'].extend(linkfinder_endpoints)
            
            # Phase 7: Secrets detection
            secrets = self.run_secrets_phase(js_files)
            analysis_results['secrets'] = secrets
            
            # Phase 8: Sink detection  
            sinks = self.run_sinks_phase(js_files)
            analysis_results['sinks'] = sinks
            
            # Phase 9: Correlation
            final_results = self.run_correlation_phase(analysis_results)
            
            # Update results
            self.results.update({
                'js_files_analyzed': len(js_files),
                'endpoints_found': len(analysis_results.get('endpoints', [])),
                'secrets_found': len(secrets),
                'sinks_found': len(sinks),
                'high_confidence': len(final_results.get('high_confidence_endpoints', []))
            })
            
            return self.results
            
        except Exception as e:
            console.print(f"[red]Pipeline error: {e}[/red]")
            raise
    
    def show_summary(self, results: Dict[str, Any]):
        """Show final summary"""
        console.print("\n" + "─" * 40)
        console.print("[bold cyan]JSEye Summary[/bold cyan]", justify="center")
        console.print("─" * 40)
        
        table = Table(show_header=False, box=None)
        table.add_column("Metric", style="cyan")
        table.add_column("Count", style="green bold")
        
        table.add_row("Domains Processed", str(results['domains_count']))
        table.add_row("URLs Harvested", str(results['urls_harvested']))
        table.add_row("JS Files Found", str(results['js_files_found']))
        table.add_row("JS Files Analyzed", str(results['js_files_analyzed']))
        table.add_row("Endpoints Found", str(results['endpoints_found']))
        table.add_row("Secrets Found", str(results['secrets_found']))
        table.add_row("Sinks Found", str(results['sinks_found']))
        table.add_row("High Confidence", str(results['high_confidence']))
        table.add_row("Output Directory", str(self.output_dir))
        
        console.print(table)
        console.print("─" * 40)
        console.print()