// Copyright (c) 2025-2026 Rocky Software Inc.
// All rights reserved.
//
// This file is part of the RockyGuard library and is distributed under
// the terms of the RockyGuard Library Software License Agreement. See
// docs/RockyGuard_License_Agreement.pdf in the distribution.
//
// No part of this file may be copied, modified, or distributed except
// as expressly permitted by the license agreement.

#pragma once

#include "license.h"
#include "types.h"
#include <memory>
#include <string>

// Forward declare OpenSSL type
typedef struct evp_pkey_st EVP_PKEY;

namespace rockyguard {

class ROCKYGUARD_API LicenseVerifier {
public:
    // Construct with vendor's public key (PEM string)
    // The default algo is SignatureAlgorithm::AutoDetect (v1.2.1+):
    // the library inspects the loaded public key and picks Ed25519
    // for an Ed25519 key, RSA-SHA256 for an RSA key, removing the
    // need for the customer to track which algorithm they used at
    // keypair creation. Callers who want to assert a specific
    // algorithm (e.g., "this binary only accepts Ed25519 licenses")
    // can still pass Ed25519 / RSA_SHA256 explicitly; that overrides
    // auto-detection. v1.2.0 callers passing the previous default
    // (Ed25519) continue to work.
    explicit LicenseVerifier(const std::string& public_key_pem,
                             SignatureAlgorithm algo = SignatureAlgorithm::AutoDetect);
    ~LicenseVerifier();

    LicenseVerifier(const LicenseVerifier&) = delete;
    LicenseVerifier& operator=(const LicenseVerifier&) = delete;

    // Load and verify a license file
    LicenseResult load(const std::string& license_file_path);

    // Load and verify from a JSON string directly
    LicenseResult load_from_string(const std::string& license_json);

    // Check node-locked license against this machine's hardware
    LicenseResult check_node_locked();

    // Check if a specific feature is licensed
    LicenseResult check_feature(const std::string& feature_name);

    // Check expiry status
    LicenseResult check_expiry();

    // Check whether the running application's version satisfies the
    // license's version_range. Pass YOUR application's version as
    // a dotted string ("3.1.5"). The license's version_range supports
    // both glob form ("3.*", "3.1.*", "3.1.5", "*") and comparator
    // form (">=3.0,<4.0", "!=3.5.0", combinations comma-separated).
    // An empty version_range on the license matches anything, which
    // preserves v1.2.0 behavior for licenses issued before this API
    // existed.
    //
    // Returns:
    //   Valid           -- current_version satisfies the range
    //   VersionMismatch -- current_version does NOT satisfy the range
    //   MalformedFile   -- current_version or the license's
    //                      version_range is unparseable
    //
    // (v1.2.1+; License::version_range was previously informational
    // metadata that no shipped library code consulted.)
    LicenseResult check_version(const std::string& current_version) const;

    // Access the parsed license (valid after successful load)
    const License& license() const;
    bool is_loaded() const;

private:
    bool verify_signature(const std::string& payload, const std::string& signature_b64);

    struct Impl;
    std::unique_ptr<Impl> impl_;
};

} // namespace rockyguard
