import 'dart:io';

import '../interfaces/i_desktop_enhancer.dart';
import '../enhancers/hyprland_enhancer.dart';
import '../enhancers/sway_enhancer.dart';
import '../detectors/window_manager_detector.dart';
import '../testing/mock_desktop_enhancer.dart';

/// Factory for creating appropriate desktop enhancer implementations based on the window manager
class DesktopEnhancerFactory {
  /// Create a desktop enhancer based on the detected window manager
  static IDesktopEnhancer create([WindowManager? windowManager]) {
    windowManager ??= WindowManagerDetector.instance.detect();

    return switch (windowManager) {
      WindowManager.hyprland => HyprlandEnhancer(), // Existing Hyprland implementation with full visual effects
      WindowManager.sway => SwayEnhancer(), // New Sway implementation with no visual effects
      WindowManager.unknown => _createFallbackEnhancer(),
    };
  }

  /// Create a mock desktop enhancer for testing
  static IDesktopEnhancer createMock() {
    return MockDesktopEnhancer();
  }

  /// Create a desktop enhancer for a specific window manager (useful for testing)
  static IDesktopEnhancer createForWindowManager(WindowManager windowManager) {
    return create(windowManager);
  }

  /// Create a fallback desktop enhancer when window manager is unknown
  static IDesktopEnhancer _createFallbackEnhancer() {
    print('⚠️  Unknown window manager detected, using no-op desktop enhancer');
    print('   Visual enhancements will be disabled');

    // Use Sway enhancer as fallback since it's no-op
    return SwayEnhancer();
  }

  /// Get information about available desktop enhancer implementations
  static Map<String, dynamic> getAvailableImplementations() {
    return {
      'hyprland': {
        'class': 'HyprlandEnhancer',
        'description': 'Full visual enhancements for Hyprland',
        'features': [
          'Dynamic blur effects',
          'Progressive shadows',
          'Animated borders',
          'Level-based themes',
          'Config backup/restore',
          'Real-time visual updates',
        ],
        'requirements': ['hyprctl'],
        'visual_enhancements': true,
      },
      'sway': {
        'class': 'SwayEnhancer',
        'description': 'Minimal enhancer for Sway (notifications only)',
        'features': ['Level-up notifications', 'Theme name tracking', 'API compatibility'],
        'requirements': ['notify-send (optional)'],
        'visual_enhancements': false,
      },
      'mock': {
        'class': 'MockDesktopEnhancer',
        'description': 'No-op mock for testing',
        'features': ['API compatibility'],
        'requirements': [],
        'visual_enhancements': false,
      },
    };
  }

  /// Check if visual enhancements are supported for the given window manager
  static bool supportsVisualEnhancements(WindowManager windowManager) {
    return WindowManagerDetector.instance.supportsVisualEnhancements(windowManager);
  }

  /// Get the feature set available for a window manager
  static List<String> getAvailableFeatures(WindowManager windowManager) {
    final implementations = getAvailableImplementations();

    return switch (windowManager) {
      WindowManager.hyprland => List<String>.from(implementations['hyprland']['features']),
      WindowManager.sway => List<String>.from(implementations['sway']['features']),
      WindowManager.unknown => ['Basic notifications'],
    };
  }

  /// 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 _validateSwayRequirements(),
      WindowManager.unknown => true, // Fallback always works
    };
  }

  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;
    }
  }

  static Future<bool> _validateSwayRequirements() async {
    // Sway enhancer has no hard requirements, but check for optional notify-send
    try {
      final result = await Process.run('which', ['notify-send']);
      // Even if notify-send is not available, Sway enhancer still works
      return true;
    } catch (e) {
      return true;
    }
  }

  /// Get capability information for the current window manager
  static Future<Map<String, dynamic>> getCapabilityInfo([WindowManager? windowManager]) async {
    windowManager ??= WindowManagerDetector.instance.detect();

    final enhancer = create(windowManager);
    final implementations = getAvailableImplementations();

    final info = {
      'window_manager': windowManager.toString(),
      'enhancer_class': enhancer.runtimeType.toString(),
      'visual_enhancements': supportsVisualEnhancements(windowManager),
      'available_features': getAvailableFeatures(windowManager),
      'requirements_met': await validateRequirements(windowManager),
    };

    // Add window manager specific info
    if (windowManager == WindowManager.sway && enhancer is SwayEnhancer) {
      info['sway_capabilities'] = enhancer.getCapabilityInfo();
      info['notification_availability'] = await SwayEnhancer.checkNotificationAvailability();
    }

    return info;
  }
}
