import '../interfaces/i_activity_detector.dart';
import '../detectors/hyprland_activity_detector.dart';
import '../detectors/sway_activity_detector.dart';
import '../detectors/window_manager_detector.dart';
import '../testing/mock_activity_detector.dart';
import 'dart:io';

/// Factory for creating appropriate activity detector implementations based on the window manager
class ActivityDetectorFactory {
  /// Create an activity detector based on the detected window manager
  static IActivityDetector? create([WindowManager? windowManager]) {
    windowManager ??= WindowManagerDetector.instance.detect();

    return switch (windowManager) {
      WindowManager.hyprland => HyprlandActivityDetector(), // Existing Hyprland implementation
      WindowManager.sway => SwayActivityDetector(),         // New Sway implementation
      WindowManager.unknown => _createFallbackDetector(),
    };
  }

  /// Create a mock activity detector for testing
  static IActivityDetector createMock() {
    return MockActivityDetector();
  }

  /// Create an activity detector for a specific window manager (useful for testing)
  static IActivityDetector? createForWindowManager(WindowManager windowManager) {
    return create(windowManager);
  }

  /// Create a fallback activity detector when window manager is unknown
  static IActivityDetector? _createFallbackDetector() {
    print('⚠️  Unknown window manager detected for activity detection');
    print('   Activity detection will be disabled - only legacy polling mode will be available');
    
    // Return null to indicate activity detection is not available
    // This will cause the ProductivityMonitor to fall back to legacy polling mode
    return null;
  }

  /// Get information about available activity detector implementations
  static Map<String, dynamic> getAvailableImplementations() {
    return {
      'hyprland': {
        'class': 'HyprlandActivityDetector',
        'description': 'Uses hyprctl activewindow for activity detection',
        'requirements': ['hyprctl'],
        'polling_interval': '5 seconds',
      },
      'sway': {
        'class': 'SwayActivityDetector', 
        'description': 'Uses swaymsg get_tree for activity detection',
        'requirements': ['swaymsg'],
        'polling_interval': '5 seconds',
      },
      'mock': {
        'class': 'MockActivityDetector',
        'description': 'Controllable mock for testing',
        'requirements': [],
        'polling_interval': 'configurable',
      },
    };
  }

  /// Check if activity detection is supported for the given window manager
  static bool isSupported(WindowManager windowManager) {
    return WindowManagerDetector.instance.supportsActivityDetection(windowManager);
  }

  /// Validate that required tools are available for the window manager
  static Future<bool> validateRequirements(WindowManager windowManager) async {
    return switch (windowManager) {
      WindowManager.hyprland => await _validateHyprlandRequirements(),
      WindowManager.sway => await SwayActivityDetector.isAvailable(),
      WindowManager.unknown => false,
    };
  }

  static Future<bool> _validateHyprlandRequirements() async {
    try {
      final result = await Process.run('which', ['hyprctl']);
      if (result.exitCode != 0) return false;
      
      // Test that hyprctl actually works
      final testResult = await Process.run('hyprctl', ['version']);
      return testResult.exitCode == 0;
    } catch (e) {
      return false;
    }
  }

  /// Get version information for activity detection tools
  static Future<Map<String, String?>> getToolVersions() async {
    final versions = <String, String?>{};

    // Check Hyprland version
    try {
      final hyprResult = await Process.run('hyprctl', ['version']);
      if (hyprResult.exitCode == 0) {
        final output = hyprResult.stdout as String;
        final lines = output.split('\n');
        if (lines.isNotEmpty) {
          versions['hyprland'] = lines.first.trim();
        }
      }
    } catch (e) {
      versions['hyprland'] = null;
    }

    // Check Sway version
    try {
      final swayVersion = await SwayActivityDetector.getVersion();
      versions['sway'] = swayVersion;
    } catch (e) {
      versions['sway'] = null;
    }

    return versions;
  }

  /// Test connectivity to window manager APIs
  static Future<Map<String, bool>> testConnectivity() async {
    final connectivity = <String, bool>{};

    // Test Hyprland connectivity
    try {
      final hyprResult = await Process.run('hyprctl', ['activewindow', '-j']);
      connectivity['hyprland'] = hyprResult.exitCode == 0;
    } catch (e) {
      connectivity['hyprland'] = false;
    }

    // Test Sway connectivity  
    try {
      final swayResult = await Process.run('swaymsg', ['-t', 'get_tree']);
      connectivity['sway'] = swayResult.exitCode == 0;
    } catch (e) {
      connectivity['sway'] = false;
    }

    return connectivity;
  }
}