// ABOUTME: This file defines security settings model for user security preferences
// ABOUTME: Includes encryption settings, authentication preferences, and security policies

import 'package:equatable/equatable.dart';
import 'auth_method.dart';

/// Security settings for the application
class SecuritySettings extends Equatable {
  final AuthConfig authConfig;
  final EncryptionSettings encryptionSettings;
  final SecurityPolicies policies;
  final bool isFirstTimeSetup;
  final DateTime? lastSecurityUpdate;

  const SecuritySettings({
    required this.authConfig,
    required this.encryptionSettings,
    required this.policies,
    this.isFirstTimeSetup = true,
    this.lastSecurityUpdate,
  });

  /// Creates default security settings for a new installation
  factory SecuritySettings.defaultSettings() {
    return SecuritySettings(
      authConfig: AuthConfig.defaultConfig(),
      encryptionSettings: EncryptionSettings.defaultSettings(),
      policies: SecurityPolicies.defaultPolicies(),
      isFirstTimeSetup: true,
    );
  }

  /// Whether any security features are enabled
  bool get hasSecurityEnabled {
    return authConfig.requiresAuth || encryptionSettings.isLocalEncryptionEnabled;
  }

  /// Overall security level (0-10, 10 being most secure)
  int get securityLevel {
    var level = 0;
    
    // Authentication level (0-4)
    level += authConfig.method.securityLevel;
    
    // Encryption level (0-3)
    if (encryptionSettings.isLocalEncryptionEnabled) level += 2;
    if (encryptionSettings.isCloudEncryptionEnabled) level += 1;
    
    // Policies level (0-3)
    if (policies.requireScreenLock) level += 1;
    if (policies.autoLockEnabled) level += 1;
    if (policies.sessionTimeout <= const Duration(minutes: 15)) level += 1;
    
    return level.clamp(0, 10);
  }

  /// Creates a copy with updated values
  SecuritySettings copyWith({
    AuthConfig? authConfig,
    EncryptionSettings? encryptionSettings,
    SecurityPolicies? policies,
    bool? isFirstTimeSetup,
    DateTime? lastSecurityUpdate,
  }) {
    return SecuritySettings(
      authConfig: authConfig ?? this.authConfig,
      encryptionSettings: encryptionSettings ?? this.encryptionSettings,
      policies: policies ?? this.policies,
      isFirstTimeSetup: isFirstTimeSetup ?? this.isFirstTimeSetup,
      lastSecurityUpdate: lastSecurityUpdate ?? this.lastSecurityUpdate,
    );
  }

  /// Marks first-time setup as complete
  SecuritySettings completeFirstTimeSetup() {
    return copyWith(
      isFirstTimeSetup: false,
      lastSecurityUpdate: DateTime.now(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'authConfig': authConfig.toJson(),
      'encryptionSettings': encryptionSettings.toJson(),
      'policies': policies.toJson(),
      'isFirstTimeSetup': isFirstTimeSetup,
      'lastSecurityUpdate': lastSecurityUpdate?.toIso8601String(),
    };
  }

  factory SecuritySettings.fromJson(Map<String, dynamic> json) {
    return SecuritySettings(
      authConfig: AuthConfig.fromJson(json['authConfig'] as Map<String, dynamic>),
      encryptionSettings: EncryptionSettings.fromJson(json['encryptionSettings'] as Map<String, dynamic>),
      policies: SecurityPolicies.fromJson(json['policies'] as Map<String, dynamic>),
      isFirstTimeSetup: json['isFirstTimeSetup'] as bool? ?? true,
      lastSecurityUpdate: json['lastSecurityUpdate'] != null
          ? DateTime.parse(json['lastSecurityUpdate'])
          : null,
    );
  }

  @override
  List<Object?> get props => [
        authConfig,
        encryptionSettings,
        policies,
        isFirstTimeSetup,
        lastSecurityUpdate,
      ];

  @override
  String toString() {
    return 'SecuritySettings(level: $securityLevel, auth: ${authConfig.method}, encrypted: ${encryptionSettings.isLocalEncryptionEnabled})';
  }
}

/// Encryption settings for local and cloud data
class EncryptionSettings extends Equatable {
  final bool isLocalEncryptionEnabled;
  final bool isCloudEncryptionEnabled;
  final String encryptionAlgorithm;
  final int keySize;
  final bool encryptBackups;
  final bool encryptExports;

  const EncryptionSettings({
    required this.isLocalEncryptionEnabled,
    required this.isCloudEncryptionEnabled,
    required this.encryptionAlgorithm,
    required this.keySize,
    required this.encryptBackups,
    required this.encryptExports,
  });

  /// Creates default encryption settings (encryption disabled by default)
  factory EncryptionSettings.defaultSettings() {
    return const EncryptionSettings(
      isLocalEncryptionEnabled: false,
      isCloudEncryptionEnabled: false,
      encryptionAlgorithm: 'AES-256-GCM',
      keySize: 256,
      encryptBackups: false,
      encryptExports: false,
    );
  }

  /// Creates secure encryption settings (encryption enabled)
  factory EncryptionSettings.secure() {
    return const EncryptionSettings(
      isLocalEncryptionEnabled: true,
      isCloudEncryptionEnabled: true,
      encryptionAlgorithm: 'AES-256-GCM',
      keySize: 256,
      encryptBackups: true,
      encryptExports: true,
    );
  }

  /// Whether any encryption is enabled
  bool get hasEncryptionEnabled {
    return isLocalEncryptionEnabled || isCloudEncryptionEnabled;
  }

  /// Creates a copy with updated values
  EncryptionSettings copyWith({
    bool? isLocalEncryptionEnabled,
    bool? isCloudEncryptionEnabled,
    String? encryptionAlgorithm,
    int? keySize,
    bool? encryptBackups,
    bool? encryptExports,
  }) {
    return EncryptionSettings(
      isLocalEncryptionEnabled: isLocalEncryptionEnabled ?? this.isLocalEncryptionEnabled,
      isCloudEncryptionEnabled: isCloudEncryptionEnabled ?? this.isCloudEncryptionEnabled,
      encryptionAlgorithm: encryptionAlgorithm ?? this.encryptionAlgorithm,
      keySize: keySize ?? this.keySize,
      encryptBackups: encryptBackups ?? this.encryptBackups,
      encryptExports: encryptExports ?? this.encryptExports,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'isLocalEncryptionEnabled': isLocalEncryptionEnabled,
      'isCloudEncryptionEnabled': isCloudEncryptionEnabled,
      'encryptionAlgorithm': encryptionAlgorithm,
      'keySize': keySize,
      'encryptBackups': encryptBackups,
      'encryptExports': encryptExports,
    };
  }

  factory EncryptionSettings.fromJson(Map<String, dynamic> json) {
    return EncryptionSettings(
      isLocalEncryptionEnabled: json['isLocalEncryptionEnabled'] as bool? ?? false,
      isCloudEncryptionEnabled: json['isCloudEncryptionEnabled'] as bool? ?? false,
      encryptionAlgorithm: json['encryptionAlgorithm'] as String? ?? 'AES-256-GCM',
      keySize: json['keySize'] as int? ?? 256,
      encryptBackups: json['encryptBackups'] as bool? ?? false,
      encryptExports: json['encryptExports'] as bool? ?? false,
    );
  }

  @override
  List<Object?> get props => [
        isLocalEncryptionEnabled,
        isCloudEncryptionEnabled,
        encryptionAlgorithm,
        keySize,
        encryptBackups,
        encryptExports,
      ];
}

/// Security policies and constraints
class SecurityPolicies extends Equatable {
  final bool requireScreenLock;
  final bool autoLockEnabled;
  final Duration sessionTimeout;
  final int maxFailedAttempts;
  final Duration lockoutDuration;
  final bool allowScreenshots;
  final bool allowCopyPaste;
  final bool requireSecureKeyboard;

  const SecurityPolicies({
    required this.requireScreenLock,
    required this.autoLockEnabled,
    required this.sessionTimeout,
    required this.maxFailedAttempts,
    required this.lockoutDuration,
    required this.allowScreenshots,
    required this.allowCopyPaste,
    required this.requireSecureKeyboard,
  });

  /// Creates default security policies
  factory SecurityPolicies.defaultPolicies() {
    return const SecurityPolicies(
      requireScreenLock: false,
      autoLockEnabled: false,
      sessionTimeout: Duration(hours: 1),
      maxFailedAttempts: 5,
      lockoutDuration: Duration(minutes: 15),
      allowScreenshots: true,
      allowCopyPaste: true,
      requireSecureKeyboard: false,
    );
  }

  /// Creates strict security policies
  factory SecurityPolicies.strict() {
    return const SecurityPolicies(
      requireScreenLock: true,
      autoLockEnabled: true,
      sessionTimeout: Duration(minutes: 15),
      maxFailedAttempts: 3,
      lockoutDuration: Duration(hours: 1),
      allowScreenshots: false,
      allowCopyPaste: false,
      requireSecureKeyboard: true,
    );
  }

  /// Creates a copy with updated values
  SecurityPolicies copyWith({
    bool? requireScreenLock,
    bool? autoLockEnabled,
    Duration? sessionTimeout,
    int? maxFailedAttempts,
    Duration? lockoutDuration,
    bool? allowScreenshots,
    bool? allowCopyPaste,
    bool? requireSecureKeyboard,
  }) {
    return SecurityPolicies(
      requireScreenLock: requireScreenLock ?? this.requireScreenLock,
      autoLockEnabled: autoLockEnabled ?? this.autoLockEnabled,
      sessionTimeout: sessionTimeout ?? this.sessionTimeout,
      maxFailedAttempts: maxFailedAttempts ?? this.maxFailedAttempts,
      lockoutDuration: lockoutDuration ?? this.lockoutDuration,
      allowScreenshots: allowScreenshots ?? this.allowScreenshots,
      allowCopyPaste: allowCopyPaste ?? this.allowCopyPaste,
      requireSecureKeyboard: requireSecureKeyboard ?? this.requireSecureKeyboard,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'requireScreenLock': requireScreenLock,
      'autoLockEnabled': autoLockEnabled,
      'sessionTimeoutMinutes': sessionTimeout.inMinutes,
      'maxFailedAttempts': maxFailedAttempts,
      'lockoutDurationMinutes': lockoutDuration.inMinutes,
      'allowScreenshots': allowScreenshots,
      'allowCopyPaste': allowCopyPaste,
      'requireSecureKeyboard': requireSecureKeyboard,
    };
  }

  factory SecurityPolicies.fromJson(Map<String, dynamic> json) {
    return SecurityPolicies(
      requireScreenLock: json['requireScreenLock'] as bool? ?? false,
      autoLockEnabled: json['autoLockEnabled'] as bool? ?? false,
      sessionTimeout: Duration(minutes: json['sessionTimeoutMinutes'] as int? ?? 60),
      maxFailedAttempts: json['maxFailedAttempts'] as int? ?? 5,
      lockoutDuration: Duration(minutes: json['lockoutDurationMinutes'] as int? ?? 15),
      allowScreenshots: json['allowScreenshots'] as bool? ?? true,
      allowCopyPaste: json['allowCopyPaste'] as bool? ?? true,
      requireSecureKeyboard: json['requireSecureKeyboard'] as bool? ?? false,
    );
  }

  @override
  List<Object?> get props => [
        requireScreenLock,
        autoLockEnabled,
        sessionTimeout,
        maxFailedAttempts,
        lockoutDuration,
        allowScreenshots,
        allowCopyPaste,
        requireSecureKeyboard,
      ];
}

/// Security status information
class SecurityStatus extends Equatable {
  final bool isAuthenticated;
  final DateTime? lastAuthenticationAt;
  final bool isSessionValid;
  final DateTime? sessionExpiresAt;
  final List<String> securityWarnings;

  const SecurityStatus({
    required this.isAuthenticated,
    this.lastAuthenticationAt,
    required this.isSessionValid,
    this.sessionExpiresAt,
    this.securityWarnings = const [],
  });

  /// Creates default security status (not authenticated)
  factory SecurityStatus.unauthenticated() {
    return const SecurityStatus(
      isAuthenticated: false,
      isSessionValid: false,
    );
  }

  /// Whether authentication is required
  bool get requiresAuthentication => !isAuthenticated || !isSessionValid;

  /// Time until session expires
  Duration? get sessionTimeRemaining {
    if (sessionExpiresAt == null) return null;
    final remaining = sessionExpiresAt!.difference(DateTime.now());
    return remaining.isNegative ? Duration.zero : remaining;
  }

  /// Creates a copy with updated values
  SecurityStatus copyWith({
    bool? isAuthenticated,
    DateTime? lastAuthenticationAt,
    bool? isSessionValid,
    DateTime? sessionExpiresAt,
    List<String>? securityWarnings,
  }) {
    return SecurityStatus(
      isAuthenticated: isAuthenticated ?? this.isAuthenticated,
      lastAuthenticationAt: lastAuthenticationAt ?? this.lastAuthenticationAt,
      isSessionValid: isSessionValid ?? this.isSessionValid,
      sessionExpiresAt: sessionExpiresAt ?? this.sessionExpiresAt,
      securityWarnings: securityWarnings ?? this.securityWarnings,
    );
  }

  @override
  List<Object?> get props => [
        isAuthenticated,
        lastAuthenticationAt,
        isSessionValid,
        sessionExpiresAt,
        securityWarnings,
      ];

  @override
  String toString() {
    return 'SecurityStatus(authenticated: $isAuthenticated, sessionValid: $isSessionValid, warnings: ${securityWarnings.length})';
  }
}
