//
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation
public import LibSignalClient

public struct AccountEntropyPool: Codable, Equatable {
    private enum CodingKeys: String, CodingKey {
        case rawString = "rawData"
    }

    public enum Constants {
        public static let byteLength: Int = 64 /* bytes */
    }

    /// The raw representation of the AEP, suitable for passing to LibSignal and
    /// other APIs.
    ///
    /// - Important
    /// Not suitable for display to the user. See: `DisplayableAccountEntropyPool`.
    public let rawString: String

    public init() {
        let generatedKey: String = LibSignalClient.AccountEntropyPool.generate()
        owsAssertBeta(generatedKey == generatedKey.lowercased())
        self.rawString = generatedKey
    }

    public init(key: String) throws {
        let normalizedKey = key.lowercased()

        guard LibSignalClient.AccountEntropyPool.isValid(normalizedKey) else {
            throw OWSAssertionError("Invalid entropy pool key")
        }

        self.rawString = normalizedKey
    }

    // MARK: - Derived Keys

    public func getMasterKey() -> MasterKey {
        // Force unwrap here.  At this point, the AEP value should either have been validated by
        // LibSignal on init, or generated by LibSignal, so should correctly generate a MasterKey.
        return try! MasterKey(data: try! LibSignalClient.AccountEntropyPool.deriveSvrKey(rawString))
    }

    public func getBackupKey() -> BackupKey {
        return try! LibSignalClient.AccountEntropyPool.deriveBackupKey(rawString)
    }

    public func getLoggingKey() -> String {
        return String(getMasterKey().data(for: .loggingKey).canonicalStringRepresentation.suffix(4))
    }
}
