///| HTTP client abstraction for cross-platform support

///| Similar to FileSystem/RepoFileSystem traits

///|
pub struct HttpResponse {
  code : Int
  headers : Map[String, String]
}

///|
pub fn HttpResponse::new(code : Int) -> HttpResponse {
  { code, headers: {} }
}

///|
pub fn HttpResponse::with_headers(
  code : Int,
  headers : Map[String, String],
) -> HttpResponse {
  { code, headers }
}

///|
/// HTTP client trait for abstracting HTTP operations
/// Implementations:
/// - Native: Uses @http package (real HTTP)
/// - WASM/JS: Uses browser fetch API
/// - Test: Mock implementation for testing
pub(open) trait HttpClient {
  /// Perform HTTP GET request
  /// Returns (response, body) or raises GitError
  get(Self, String, Map[String, String]) -> (HttpResponse, Bytes) raise GitError

  /// Perform HTTP POST request
  /// Returns (response, body) or raises GitError
  post(Self, String, Bytes, Map[String, String]) -> (HttpResponse, Bytes) raise GitError
}

///|
/// Mock HTTP client for testing
pub struct MockHttpClient {
  responses : Map[String, (Int, Bytes)]
}

///|
pub fn MockHttpClient::new() -> MockHttpClient {
  { responses: {} }
}

///|
pub fn MockHttpClient::add_response(
  self : MockHttpClient,
  url : String,
  code : Int,
  body : Bytes,
) -> Unit {
  self.responses[url] = (code, body)
}

///|
pub impl HttpClient for MockHttpClient with get(self, url, _headers) {
  match self.responses.get(url) {
    Some((code, body)) => (HttpResponse::new(code), body)
    None => raise GitError::IoError("Mock: No response for URL: " + url)
  }
}

///|
pub impl HttpClient for MockHttpClient with post(self, url, _body, _headers) {
  match self.responses.get(url) {
    Some((code, body)) => (HttpResponse::new(code), body)
    None => raise GitError::IoError("Mock: No response for URL: " + url)
  }
}