// ABOUTME: This file defines the KeyPair model for RSA key pair management
// ABOUTME: Includes RSA public/private key storage and cryptographic operations

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

/// Represents an RSA key pair for encryption and signing operations
class KeyPair extends Equatable {
  final RSAPublicKey publicKey;
  final RSAPrivateKey privateKey;
  final DateTime createdAt;
  final String keyId;

  const KeyPair({
    required this.publicKey,
    required this.privateKey,
    required this.createdAt,
    required this.keyId,
  });

  /// Creates a KeyPair from PEM-encoded strings
  factory KeyPair.fromPem({
    required String publicPem,
    required String privatePem,
    required String keyId,
    DateTime? createdAt,
  }) {
    // Note: In a real implementation, you would parse PEM here
    // For now, this is a placeholder structure
    throw UnimplementedError('PEM parsing to be implemented');
  }

  /// Converts the public key to PEM format
  String get publicKeyPem {
    // Note: In a real implementation, you would convert to PEM here
    throw UnimplementedError('PEM conversion to be implemented');
  }

  /// Converts the private key to PEM format
  String get privateKeyPem {
    // Note: In a real implementation, you would convert to PEM here
    throw UnimplementedError('PEM conversion to be implemented');
  }

  /// Gets the key size in bits
  int get keySize => publicKey.modulus!.bitLength;

  /// Checks if the key pair is valid
  bool get isValid {
    try {
      // Basic validation - check if modulus exists and has reasonable size
      return publicKey.modulus != null && 
             privateKey.modulus != null &&
             keySize >= 2048; // Minimum secure key size
    } catch (e) {
      return false;
    }
  }

  /// Creates a copy with updated values
  KeyPair copyWith({
    RSAPublicKey? publicKey,
    RSAPrivateKey? privateKey,
    DateTime? createdAt,
    String? keyId,
  }) {
    return KeyPair(
      publicKey: publicKey ?? this.publicKey,
      privateKey: privateKey ?? this.privateKey,
      createdAt: createdAt ?? this.createdAt,
      keyId: keyId ?? this.keyId,
    );
  }

  /// Converts to JSON for secure storage (excludes private key)
  Map<String, dynamic> toJson() {
    return {
      'keyId': keyId,
      'createdAt': createdAt.toIso8601String(),
      'keySize': keySize,
      'publicKeyPem': publicKeyPem,
      // Note: Private key should never be included in regular JSON
    };
  }

  /// Creates from JSON (public key only)
  factory KeyPair.fromJson(Map<String, dynamic> json) {
    throw UnimplementedError('JSON deserialization to be implemented');
  }

  @override
  List<Object?> get props => [keyId, createdAt, keySize];

  @override
  String toString() {
    return 'KeyPair(keyId: $keyId, createdAt: $createdAt, keySize: $keySize)';
  }
}

/// Key pair generation result with metadata
class KeyGenerationResult extends Equatable {
  final KeyPair keyPair;
  final Duration generationTime;
  final bool isSecurelyStored;

  const KeyGenerationResult({
    required this.keyPair,
    required this.generationTime,
    required this.isSecurelyStored,
  });

  @override
  List<Object?> get props => [keyPair, generationTime, isSecurelyStored];
}

/// Key derivation parameters for symmetric key generation
class KeyDerivationParams extends Equatable {
  final String algorithm;
  final String salt;
  final int iterations;
  final int keyLength;

  const KeyDerivationParams({
    required this.algorithm,
    required this.salt,
    required this.iterations,
    required this.keyLength,
  });

  /// Default secure parameters for PBKDF2
  factory KeyDerivationParams.defaultPBKDF2() {
    return const KeyDerivationParams(
      algorithm: 'PBKDF2',
      salt: '', // Will be generated
      iterations: 100000,
      keyLength: 32, // 256 bits
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'algorithm': algorithm,
      'salt': salt,
      'iterations': iterations,
      'keyLength': keyLength,
    };
  }

  factory KeyDerivationParams.fromJson(Map<String, dynamic> json) {
    return KeyDerivationParams(
      algorithm: json['algorithm'] as String,
      salt: json['salt'] as String,
      iterations: json['iterations'] as int,
      keyLength: json['keyLength'] as int,
    );
  }

  @override
  List<Object?> get props => [algorithm, salt, iterations, keyLength];
}
