"""
Headless GUI module for testing without tkinter display.
Provides mock classes for GUI testing in environments without X server.
"""

from typing import List, Dict, Any, Optional
from pathlib import Path
import json
import datetime
import os
from ..model import ScanRequest, ScanResult
from ..scanner import SentinelScanner
from ..reporting import HistoryStore, ReportEngine
from ..subscription import SubscriptionManager, SubscriptionTier
from ..subscription.validator import LicenseError, LicenseValidator


class MockVar:
    """Mock variable for tkinter variables."""
    def __init__(self, value=None):
        self._value = value
    
    def get(self):
        return self._value
    
    def set(self, value):
        self._value = value


class HeadlessWebSentinelGUI:
    """
    Headless version of WebSentinelGUI for testing without tkinter.
    Provides the same interface but without actual GUI components.
    """
    
    def __init__(self, subscription_tier: str | SubscriptionTier | None = None):
        # Initialize variables without tkinter
        self.domains_var = MockVar("")
        self.allow_invasive_var = MockVar(False)
        self.timeout_var = MockVar(5.0)
        self.current_scan_thread = None
        self.scan_results: List[ScanResult] = []
        self.is_scanning = False
        
        # Module variables
        self.module_vars = {
            'tls': MockVar(True),
            'headers': MockVar(True),
            'static-analysis': MockVar(True),
            'injection': MockVar(True),
            'third-party': MockVar(False)
        }
        
        # Configuration
        self.config_file = Path.home() / ".web-sentinel" / "gui-config.json"
        self.config = {}
        self.load_config()
        
        # Scanner and storage
        self.scanner = SentinelScanner()
        history_path = self.config_file.parent / "history.json"
        self.history_store = HistoryStore(history_path)
        self.report_engine = ReportEngine()

        tier = subscription_tier or os.getenv("WS_SUBSCRIPTION_TIER")
        self.subscription_manager = SubscriptionManager(user_id="headless")
        if tier:
            self.subscription_manager.set_tier(tier)
        self.license_validator = LicenseValidator(self.subscription_manager)
        
        print("[HEADLESS] HeadlessWebSentinelGUI initialized (no GUI display)")
    
    def load_config(self):
        """Load configuration from file."""
        try:
            if self.config_file.exists():
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    self.config = json.load(f)
        except Exception:
            self.config = {}
    
    def save_config(self):
        """Save configuration to file."""
        try:
            self.config_file.parent.mkdir(parents=True, exist_ok=True)
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, indent=2)
        except Exception:
            pass
    
    def get_domains(self) -> List[str]:
        """Get list of domains from input."""
        domains_text = self.domains_var.get() or ""
        return [d.strip() for d in domains_text.split('\n') if d.strip()]
    
    def set_domains(self, domains: List[str]):
        """Set domains list."""
        self.domains_var.set('\n'.join(domains))
    
    def get_selected_modules(self) -> List[str]:
        """Get list of selected modules."""
        return [name for name, var in self.module_vars.items() if var.get()]
    
    def set_selected_modules(self, modules: List[str]):
        """Set selected modules."""
        for name, var in self.module_vars.items():
            var.set(name in modules)
    
    def start_scan(self) -> bool:
        """
        Start scan in headless mode.
        Returns True if scan started successfully, False otherwise.
        """
        domains = self.get_domains()
        if not domains:
            print("❌ Error: No domains specified")
            return False

        domain_limit = self.subscription_manager.get_domain_limit()
        if domain_limit != -1 and len(domains) > domain_limit:
            print("⚠️ Upgrade required: Free tier limited to 3 domains.")
            return False
            
        selected_modules = self.get_selected_modules()
        if not selected_modules:
            print("❌ Error: No modules selected")
            return False

        if self.allow_invasive_var.get():
            if not self.can_start_invasive_scan():
                self.allow_invasive_var.set(False)
                print("⚠️ Invasive tests disabled for free tier. Upgrade to PRO.")
                return False
        
        print(f"[START] Starting headless scan for {len(domains)} domains...")
        print(f"[DOMAINS] Domains: {', '.join(domains)}")
        print(f"[MODULES] Modules: {', '.join(selected_modules)}")
        
        self.is_scanning = True
        self.scan_results.clear()
        
        try:
            # Perform scan for each domain
            for domain in domains:
                request = ScanRequest(
                    domain=domain,
                    timeout=self.timeout_var.get(),
                    allow_invasive=self.allow_invasive_var.get()
                )
                
                print(f"🔍 Scanning {domain}...")
                result = self.scanner.run(request, selected_modules)
                self.scan_results.append(result)
                
                print(f"   Found {len(result.findings)} findings")
            
            print(f"✅ Scan completed: {len(self.scan_results)} domains scanned")
            self.display_results()
            return True
            
        except Exception as e:
            print(f"❌ Scan error: {e}")
            return False
        finally:
            self.is_scanning = False
    
    def display_results(self):
        """Display scan results in headless mode."""
        if not self.scan_results:
            print("📝 No scan results to display")
            return
        
        print("\n" + "="*60)
        print("📊 SCAN RESULTS")
        print("="*60)
        
        total_findings = sum(len(result.findings) for result in self.scan_results)
        print(f"🎯 Summary: {len(self.scan_results)} domains, {total_findings} total findings")
        
        for result in self.scan_results:
            print(f"\n🌐 Domain: {result.request.domain}")
            
            if not result.findings:
                print("   ✅ No security issues found")
                continue
            
            # Group by severity
            by_severity = {}
            for finding in result.findings:
                severity = finding.severity
                if severity not in by_severity:
                    by_severity[severity] = []
                by_severity[severity].append(finding)
            
            for severity in ['critical', 'high', 'medium', 'low', 'info']:
                if severity in by_severity:
                    findings = by_severity[severity]
                    print(f"   🔴 {severity.upper()}: {len(findings)} findings")
                    for finding in findings[:3]:  # Show first 3
                        print(f"      • {finding.title}")
                    if len(findings) > 3:
                        print(f"      ... and {len(findings) - 3} more")
    
    def export_report(self, format_type: str = "json", output_path: Optional[str] = None) -> Optional[str]:
        """
        Export scan results to file.
        Returns path of exported file or None if failed.
        """
        if not self.scan_results:
            print("❌ No results to export")
            return None
        
        try:
            if format_type.lower() == "json":
                if not output_path:
                    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
                    output_path = f"web_sentinel_report_{timestamp}.json"
                
                data = {
                    "timestamp": datetime.datetime.now().isoformat(),
                    "domains": [result.request.domain for result in self.scan_results],
                    "results": [
                        {
                            "domain": result.request.domain,
                            "findings": [finding.to_dict() for finding in result.findings]
                        }
                        for result in self.scan_results
                    ]
                }
                
                with open(output_path, 'w', encoding='utf-8') as f:
                    json.dump(data, f, indent=2, ensure_ascii=False)
                
                print(f"✅ Report exported to: {output_path}")
                return output_path
            
            elif format_type.lower() == "html":
                if not self.subscription_manager.can_export_html():
                    print("⚠️ HTML export requires a PRO subscription.")
                    return None
                if not output_path:
                    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
                    output_path = f"web_sentinel_report_{timestamp}.html"
                
                # Use report engine for HTML generation
                context = self.report_engine.build_context(self.scan_results[0])
                html_content = self.report_engine.render_html(context)
                with open(output_path, 'w', encoding='utf-8') as f:
                    f.write(html_content)
                
                print(f"✅ HTML report exported to: {output_path}")
                return output_path
            
            else:
                print(f"❌ Unsupported format: {format_type}")
                return None
                
        except Exception as e:
            print(f"❌ Export failed: {e}")
            return None
    
    def run_headless_test(self, test_domains: List[str], test_modules: List[str] = None) -> Dict[str, Any]:
        """
        Run a complete test in headless mode.
        Returns test results summary.
        """
        print("🧪 Starting headless test mode...")
        
        # Set up test parameters
        self.set_domains(test_domains)
        if test_modules:
            self.set_selected_modules(test_modules)
        else:
            # Use default safe modules
            self.set_selected_modules(['tls', 'headers'])
        
        # Run scan
        scan_success = self.start_scan()
        
        # Generate summary
        result = {
            "test_timestamp": datetime.datetime.now().isoformat(),
            "domains_tested": test_domains,
            "modules_used": self.get_selected_modules(),
            "scan_success": scan_success,
            "total_findings": sum(len(result.findings) for result in self.scan_results) if scan_success else 0,
            "results_summary": {}
        }
        
        if scan_success and self.scan_results:
            for scan_result in self.scan_results:
                domain = scan_result.request.domain
                result["results_summary"][domain] = {
                    "findings_count": len(scan_result.findings),
                    "severities": {}
                }
                
                # Count by severity
                for finding in scan_result.findings:
                    severity = finding.severity
                    if severity not in result["results_summary"][domain]["severities"]:
                        result["results_summary"][domain]["severities"][severity] = 0
                    result["results_summary"][domain]["severities"][severity] += 1
        
        print(f"🎯 Test completed: {result}")
        return result

    def can_start_invasive_scan(self) -> bool:
        try:
            self.license_validator.ensure_invasive_tests_allowed()
        except LicenseError:
            return False
        return True

    def set_subscription_tier(self, tier: str | SubscriptionTier) -> None:
        self.subscription_manager.set_tier(tier)


def get_gui_class(headless: bool = False):
    """
    Factory function to get appropriate GUI class.
    
    Args:
        headless: If True, return headless version. If False, try tkinter version.
    
    Returns:
        GUI class (either WebSentinelGUI or HeadlessWebSentinelGUI)
    """
    if headless:
        return HeadlessWebSentinelGUI
    
    try:
        from .main_window import WebSentinelGUI
        try:
            import tkinter as tk

            test_root = tk.Tk()
            test_root.destroy()
        except Exception as exc:
            print(f"⚠️ tkinter initialization failed: {exc}")
            print("🔄 Falling back to headless mode...")
            return HeadlessWebSentinelGUI
        return WebSentinelGUI
    except ImportError as e:
        print(f"⚠️ tkinter not available: {e}")
        print("🔄 Falling back to headless mode...")
        return HeadlessWebSentinelGUI
