#pragma once

#include "chat_protocol.h"

#include <cstddef>
#include <string>
#include <vector>

// HushChat compatibility-fixture / capture-manifest / seed-projection tooling.
//
// Everything in this header is DEAD AT RUNTIME in the shipping app and test
// binaries — its only caller is the standalone dev CLI
// tools/hushchat_fixture_check.cpp. It is deliberately compiled ONLY into the
// HushChatFixtureCheck target so this validation scaffolding (and its libsodium
// seed-projection path) never reaches the wallet binary. Keep it that way: do
// not add chat_fixture_tooling.cpp to APP_SOURCES or the test target.
//
// It builds on the runtime types declared in chat_protocol.h.

namespace dragonx::chat {

enum class HushChatDecryptPreflightError {
    None,
    FeatureDisabled,
    NonMessageHeader,
    InvalidHeaderNumber,
    UnsupportedVersion,
    MissingReplyAddress,
    MissingConversationId,
    InvalidSecretstreamHeader,
    InvalidPublicKey,
    EmptyCiphertext,
    OversizedCiphertext,
    OddLengthCiphertext,
    InvalidCiphertextHex,
    TruncatedCiphertext
};

struct HushChatDecryptPreflightInput {
    HushChatHeader header;
    std::string ciphertext_hex;
};

struct HushChatDecryptPreflightResult {
    bool ok = false;
    bool feature_enabled = false;
    HushChatDecryptPreflightError error = HushChatDecryptPreflightError::None;
    const char* error_name = "None";
    std::size_t ciphertext_size = 0;
};

enum class HushChatHexDecodeError {
    None,
    Empty,
    OddLength,
    InvalidHex,
    UnexpectedByteLength
};

struct HushChatHexDecodeResult {
    bool ok = false;
    HushChatHexDecodeError error = HushChatHexDecodeError::None;
    const char* error_name = "None";
    std::vector<unsigned char> bytes;
};

enum class HushChatDecryptDirection {
    Incoming,
    Outgoing
};

enum class HushChatSessionKeySelection {
    ClientRx,
    ServerTx
};

enum class HushChatDecryptInputError {
    None,
    FeatureDisabled,
    InvalidStoredChatKey,
    DecryptPreflightFailed,
    InvalidPeerPublicKey,
    InvalidStreamHeader,
    InvalidCiphertext
};

struct HushChatDecryptInputMaterial {
    std::string stored_chat_key_hex;
    HushChatHeader header;
    std::string ciphertext_hex;
    HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
    std::string peer_public_key_hex;
};

struct HushChatPreparedDecryptInput {
    std::vector<unsigned char> stored_chat_key_bytes;
    std::vector<unsigned char> seed_bytes;
    std::vector<unsigned char> peer_public_key_bytes;
    std::vector<unsigned char> stream_header_bytes;
    std::vector<unsigned char> ciphertext_bytes;
    HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
    HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx;
    std::size_t plaintext_capacity = 0;
};

struct HushChatDecryptInputPreparationResult {
    bool ok = false;
    bool feature_enabled = false;
    HushChatDecryptInputError error = HushChatDecryptInputError::None;
    const char* error_name = "None";
    HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
    HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None;
    HushChatPreparedDecryptInput prepared;
};

struct HushChatDecryptFixtureReadinessResult {
    bool ready = false;
    std::size_t stored_chat_key_size = 0;
    std::size_t seed_size = 0;
    std::size_t peer_public_key_size = 0;
    std::size_t stream_header_size = 0;
    std::size_t ciphertext_size = 0;
    std::size_t plaintext_capacity = 0;
    HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx;
};

enum class HushChatCompatibilityFixtureError {
    None,
    FeatureDisabled,
    MissingFixtureId,
    InvalidLocalPublicKey,
    InvalidPeerPublicKey,
    InvalidHeaderMemo,
    InvalidMemoPair,
    NonMemoHeader,
    HeaderPublicKeyMismatch,
    DecryptInputFailed,
    NotFixtureReady,
    ExpectedStoredChatKeyLengthMismatch,
    ExpectedSeedLengthMismatch,
    ExpectedLocalPublicKeyLengthMismatch,
    ExpectedPeerPublicKeyLengthMismatch,
    ExpectedStreamHeaderLengthMismatch,
    ExpectedCiphertextLengthMismatch,
    ExpectedPlaintextLengthMismatch,
    ExpectedRoleMismatch,
    InvalidPlaintextHash
};

struct HushChatCompatibilityFixture {
    std::string fixture_id;
    std::string stored_chat_key_hex;
    std::string local_public_key_hex;
    std::string peer_public_key_hex;
    std::string header_memo;
    std::string ciphertext_memo;
    HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming;
    HushChatSessionKeySelection expected_session_key_selection = HushChatSessionKeySelection::ClientRx;
    std::size_t expected_stored_chat_key_size = 32;
    std::size_t expected_seed_size = 32;
    std::size_t expected_local_public_key_size = 32;
    std::size_t expected_peer_public_key_size = 32;
    std::size_t expected_stream_header_size = 24;
    std::size_t expected_ciphertext_size = 0;
    std::size_t expected_plaintext_size = 0;
    std::string expected_plaintext_hash_hex;
};

struct HushChatCompatibilityFixtureVerificationResult {
    bool ok = false;
    bool feature_enabled = false;
    HushChatCompatibilityFixtureError error = HushChatCompatibilityFixtureError::None;
    const char* error_name = "None";
    HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
    HushChatDecryptInputError decrypt_input_error = HushChatDecryptInputError::None;
    HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None;
    HushChatHeader header;
    HushChatDecryptInputPreparationResult preparation;
    HushChatDecryptFixtureReadinessResult readiness;
    std::size_t local_public_key_size = 0;
    std::size_t peer_public_key_size = 0;
    std::size_t plaintext_hash_size = 0;
};

enum class HushChatCompatibilityFixtureKind {
    IncomingMemo,
    OutgoingMemo,
    SeedPublicKeyProjection,
    CorruptedAuthFailure,
    ContactExclusion
};

enum class HushChatCompatibilityFixtureFileStatus {
    Pending,
    Ready
};

enum class HushChatCompatibilityFixtureFileError {
    None,
    FeatureDisabled,
    InvalidJson,
    JsonNotObject,
    InvalidSchema,
    MissingKind,
    UnknownKind,
    MissingStatus,
    UnknownStatus,
    MissingFixtureId,
    MissingPendingReason,
    MissingFixtureObject,
    InvalidFixtureField,
    FixtureVerificationFailed,
    ContactFixtureNotExcluded,
    FileReadFailed
};

struct HushChatCompatibilityFixtureFile {
    std::string schema;
    HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    HushChatCompatibilityFixtureFileStatus status = HushChatCompatibilityFixtureFileStatus::Pending;
    std::string fixture_id;
    std::string pending_reason;
    HushChatCompatibilityFixture fixture;
};

struct HushChatCompatibilityFixtureFileParseResult {
    bool ok = false;
    bool feature_enabled = false;
    bool pending = false;
    bool verified = false;
    bool excluded_from_decrypt = false;
    HushChatCompatibilityFixtureFileError error = HushChatCompatibilityFixtureFileError::None;
    const char* error_name = "None";
    HushChatCompatibilityFixtureFile file;
    HushChatCompatibilityFixtureVerificationResult verification;
};

enum class HushChatSeedPublicKeyProjectionError {
    None,
    FeatureDisabled,
    MissingFixtureId,
    InvalidStoredChatKey,
    InvalidLocalPublicKey,
    ExpectedStoredChatKeyLengthMismatch,
    ExpectedSeedLengthMismatch,
    ExpectedLocalPublicKeyLengthMismatch,
    SodiumInitializationFailed,
    KeypairProjectionFailed,
    ProjectedPublicKeyMismatch
};

struct HushChatSeedPublicKeyProjectionResult {
    bool ok = false;
    bool feature_enabled = false;
    HushChatSeedPublicKeyProjectionError error = HushChatSeedPublicKeyProjectionError::None;
    const char* error_name = "None";
    HushChatHexDecodeError hex_error = HushChatHexDecodeError::None;
    std::size_t stored_chat_key_size = 0;
    std::size_t seed_size = 0;
    std::size_t local_public_key_size = 0;
    std::size_t projected_public_key_size = 0;
};

enum class HushChatCorruptedAuthFailureReadinessError {
    None,
    FeatureDisabled,
    FixturePending,
    WrongFixtureKind,
    FixtureNotVerified,
    SeedProjectionNotVerified
};

struct HushChatCorruptedAuthFailureReadinessResult {
    bool ok = false;
    bool feature_enabled = false;
    bool structurally_ready_for_future_auth_check = false;
    bool requires_future_secretstream_auth_failure = false;
    bool decrypted = false;
    bool authenticated = false;
    HushChatCorruptedAuthFailureReadinessError error = HushChatCorruptedAuthFailureReadinessError::None;
    const char* error_name = "None";
};

enum class HushChatCompatibilityFixtureImportError {
    None,
    FeatureDisabled,
    MissingRequiredKind,
    DuplicateKind,
    FixtureLoadFailed,
    FixtureKindMismatch,
    FixturePending,
    FixtureInvalid,
    FixtureNotVerified,
    SeedProjectionFailed,
    AuthFailureScaffoldFailed,
    ContactFixtureNotExcluded
};

struct HushChatCompatibilityFixtureImportCandidate {
    HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    std::string path;
};

struct HushChatCompatibilityFixtureImportItem {
    HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    std::string path;
    bool supplied = false;
    bool pending = false;
    bool replacement_eligible = false;
    bool seed_projection_verified = false;
    bool future_auth_failure_required = false;
    bool structurally_ready_for_future_auth_check = false;
    HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
    const char* error_name = "None";
    HushChatCompatibilityFixtureFileParseResult parsed;
    HushChatSeedPublicKeyProjectionResult seed_projection;
    HushChatCorruptedAuthFailureReadinessResult auth_failure_readiness;
};

struct HushChatCompatibilityFixtureImportChecklistResult {
    bool ok = false;
    bool feature_enabled = false;
    bool replacement_ready = false;
    HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
    const char* error_name = "None";
    std::size_t required_count = 0;
    std::size_t supplied_count = 0;
    std::size_t missing_count = 0;
    std::size_t pending_count = 0;
    std::size_t verified_count = 0;
    std::size_t seed_projection_verified_count = 0;
    std::size_t future_auth_failure_required_count = 0;
    std::size_t auth_failure_structural_ready_count = 0;
    std::size_t excluded_count = 0;
    std::size_t rejected_count = 0;
    std::vector<HushChatCompatibilityFixtureImportItem> items;
};

struct HushChatCompatibilityFixtureReplacementReportItem {
    HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    std::string path;
    bool supplied = false;
    bool pending = false;
    bool replacement_eligible = false;
    bool refused = true;
    bool seed_projection_verified = false;
    bool future_auth_failure_required = false;
    bool structurally_ready_for_future_auth_check = false;
    bool cont_excluded = false;
    bool decrypted = false;
    bool authenticated = false;
    HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
    const char* error_name = "None";
};

struct HushChatCompatibilityFixtureReplacementDryRunResult {
    bool ok = false;
    bool feature_enabled = false;
    bool dry_run_only = true;
    bool redacted_report = true;
    bool would_replace = false;
    bool replacement_refused = true;
    HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None;
    const char* error_name = "None";
    std::size_t required_count = 0;
    std::size_t supplied_count = 0;
    std::size_t missing_count = 0;
    std::size_t pending_count = 0;
    std::size_t verified_count = 0;
    std::size_t seed_projection_verified_count = 0;
    std::size_t future_auth_failure_required_count = 0;
    std::size_t auth_failure_structural_ready_count = 0;
    std::size_t excluded_count = 0;
    std::size_t rejected_count = 0;
    std::vector<HushChatCompatibilityFixtureReplacementReportItem> report_items;
};

enum class HushChatCaptureManifestError {
    None,
    FeatureDisabled,
    FileReadFailed,
    InvalidJson,
    JsonNotObject,
    InvalidSchema,
    MissingManifestId,
    MissingStatus,
    UnknownStatus,
    MissingFixtureDirectory,
    MissingDryRunCommand,
    InvalidDryRunCommand,
    MissingProvenance,
    MissingSourceClient,
    InvalidSourceClient,
    MissingSourceClientVersion,
    MissingCaptureDate,
    MissingNetwork,
    MissingCaptureMethod,
    MissingHandling,
    MissingHandlingFlag,
    HandlingFlagNotTrue,
    MissingCategories,
    InvalidCategoryEntry,
    UnknownCategory,
    DuplicateCategory,
    MissingRequiredCategory,
    ProhibitedFieldPresent
};

enum class HushChatCaptureManifestStatus {
    Staged
};

struct HushChatCaptureManifestCategoryReport {
    HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo;
    std::string staged_filename;
    bool declared = false;
};

struct HushChatCaptureManifestValidationResult {
    bool ok = false;
    bool feature_enabled = false;
    bool redacted_report = true;
    bool validates_provenance_only = true;
    bool no_sensitive_material_declared = false;
    bool has_dry_run_command = false;
    HushChatCaptureManifestError error = HushChatCaptureManifestError::None;
    const char* error_name = "None";
    HushChatCaptureManifestStatus status = HushChatCaptureManifestStatus::Staged;
    std::string manifest_path;
    std::string fixture_directory;
    std::size_t required_count = 0;
    std::size_t declared_count = 0;
    std::size_t missing_count = 0;
    std::size_t duplicate_count = 0;
    std::size_t prohibited_field_count = 0;
    std::size_t handling_flag_count = 0;
    std::vector<HushChatCaptureManifestCategoryReport> categories;
};

constexpr std::size_t kHushChatSecretstreamABytes = 17;
constexpr std::size_t kHushChatStoredChatKeyByteLength = 32;
constexpr std::size_t kHushChatStoredChatKeyHexLength = kHushChatStoredChatKeyByteLength * 2;
constexpr std::size_t kHushChatSeedByteLength = 32;
constexpr std::size_t kHushChatPublicKeyByteLength = kHushChatPublicKeyHexLength / 2;
constexpr std::size_t kHushChatSecretstreamHeaderByteLength = kHushChatSecretstreamHeaderHexLength / 2;
constexpr const char* kHushChatCompatibilityFixtureSchema = "dragonx.hushchat.compat-fixture.v1";
constexpr const char* kHushChatCaptureManifestSchema = "dragonx.hushchat.capture-manifest.v1";

HushChatDecryptPreflightResult validateHushChatMemoDecryptPreflight(
    const HushChatDecryptPreflightInput& input,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatHexDecodeResult decodeHushChatHexBytes(const std::string& hex,
                                               std::size_t expectedByteLength);
HushChatDecryptInputPreparationResult prepareHushChatDecryptInput(
    const HushChatDecryptInputMaterial& material,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatDecryptFixtureReadinessResult inspectHushChatDecryptFixtureReadiness(
    const HushChatPreparedDecryptInput& prepared);
HushChatSessionKeySelection hushChatSessionKeySelectionForDirection(HushChatDecryptDirection direction);
HushChatCompatibilityFixtureVerificationResult verifyHushChatCompatibilityFixture(
    const HushChatCompatibilityFixture& fixture,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureFileParseResult parseHushChatCompatibilityFixtureFile(
    const std::string& jsonText,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureFileParseResult loadHushChatCompatibilityFixtureFile(
    const std::string& path,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatSeedPublicKeyProjectionResult verifyHushChatSeedPublicKeyProjection(
    const HushChatCompatibilityFixture& fixture,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCorruptedAuthFailureReadinessResult inspectHushChatCorruptedAuthFailureReadiness(
    const HushChatCompatibilityFixtureFileParseResult& parsed,
    const HushChatSeedPublicKeyProjectionResult& seedProjection,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
std::vector<HushChatCompatibilityFixtureKind> hushChatRequiredCompatibilityFixtureKinds();
HushChatCompatibilityFixtureImportChecklistResult inspectHushChatCompatibilityFixtureImportChecklist(
    const std::vector<HushChatCompatibilityFixtureImportCandidate>& candidates,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCompatibilityFixtureReplacementDryRunResult inspectHushChatCompatibilityFixtureReplacementDryRun(
    const std::vector<HushChatCompatibilityFixtureImportCandidate>& candidates,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCaptureManifestValidationResult validateHushChatCaptureManifest(
    const std::string& jsonText,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
HushChatCaptureManifestValidationResult loadHushChatCaptureManifestFile(
    const std::string& path,
    bool featureEnabled = hushChatFeatureEnabledAtBuild());
const char* hushChatDecryptPreflightErrorName(HushChatDecryptPreflightError error);
const char* hushChatHexDecodeErrorName(HushChatHexDecodeError error);
const char* hushChatDecryptDirectionName(HushChatDecryptDirection direction);
const char* hushChatSessionKeySelectionName(HushChatSessionKeySelection selection);
const char* hushChatDecryptInputErrorName(HushChatDecryptInputError error);
const char* hushChatCompatibilityFixtureErrorName(HushChatCompatibilityFixtureError error);
const char* hushChatCompatibilityFixtureKindName(HushChatCompatibilityFixtureKind kind);
const char* hushChatCompatibilityFixtureFileStatusName(HushChatCompatibilityFixtureFileStatus status);
const char* hushChatCompatibilityFixtureFileErrorName(HushChatCompatibilityFixtureFileError error);
const char* hushChatSeedPublicKeyProjectionErrorName(HushChatSeedPublicKeyProjectionError error);
const char* hushChatCorruptedAuthFailureReadinessErrorName(HushChatCorruptedAuthFailureReadinessError error);
const char* hushChatCompatibilityFixtureImportErrorName(HushChatCompatibilityFixtureImportError error);
const char* hushChatCaptureManifestErrorName(HushChatCaptureManifestError error);

} // namespace dragonx::chat
