/*
 * Copyright 2026 Snowflake Inc.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <string>
#include <string_view>

namespace snowflake::ingest::streaming {

/// Mirrors IngestError variants from the Rust core.
/// String values match the Rust serde serialization (PascalCase).
enum class error_code {
  // 400 Bad Request
  kConfigError,
  kInvalidRequest,
  kInvalidArgument,
  kSfApiUserError,
  kNotImplemented,
  kHttpClientNonRetryableError,
  kSfApiPipeFailedOverError,
  kChannelAlreadyExists,

  // 401 Unauthorized
  kAuthTokenError,
  kSfApiAuthError,

  // 404 Not Found
  kChannelNotFound,

  // 408 Request Timeout
  kChannelWaitForFlushTimeout,
  kClientWaitForFlushTimeout,

  // 409 Conflict
  kClosedChannelError,
  kClosedClientError,
  kChannelClosedByUser,
  kInvalidChannelError,
  kInvalidClientError,
  kInputChannelClosed,
  kOutputChannelClosed,

  // 429 Too Many Requests
  kReceiverSaturated,
  kMemoryThresholdExceeded,
  kMemoryThresholdExceededInContainer,

  // 500 Internal Server Error
  kFatal,
  kNonFatal,
  kMutexLockFailed,
  kSfApiUnexpectedBehaviorError,
  kSfApiInternalServerError,
  kFileUploadError,
  kHttpRetriesExhaustedError,
  kCloseAllChannelsFailedError,

  // 503 Service Unavailable
  kHttpRetryableClientError,

  // Fallback for unrecognised codes from future Rust versions
  kUnknown,
};

/// Returns the canonical string representation used by the Rust core.
std::string_view error_code_to_string(error_code code) noexcept;

/// Parses a Rust error_code string into the enum.  Unknown strings map to
/// kUnknown rather than throwing.
error_code error_code_from_string(std::string_view s) noexcept;

/// Structured error type returned by all SDK operations via result<T>.
///
/// Carries the full error information serialized by the Rust core:
///   { "error_code": "...", "message": "...",
///     "http_status_code": N, "http_status_name": "..." }
class error {
 public:
  error(error_code code, std::string message, int http_status_code,
        std::string http_status_name);

  /// Parse the JSON error payload produced by the Rust core.
  /// On parse failure falls back to kFatal with the raw string as message.
  static error from_rust_json(std::string_view json_error);

  error_code code() const noexcept { return code_; }
  const std::string& message() const noexcept { return message_; }
  int http_status_code() const noexcept { return http_status_code_; }
  const std::string& http_status_name() const noexcept {
    return http_status_name_;
  }

 private:
  error_code code_;
  std::string message_;
  int http_status_code_;
  std::string http_status_name_;
};

}  // namespace snowflake::ingest::streaming
