Documentation
// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file

use std::time::Duration;

use crate::proxy_wasm::hostcalls;
use crate::proxy_wasm::types::{BufferType, Status};

pub trait GrpcHost {
    fn dispatch_grpc_call(
        &self,
        upstream_name: &str,
        service_name: &str,
        method_name: &str,
        initial_metadata: Vec<(&str, &[u8])>,
        message: Option<&[u8]>,
        timeout: Duration,
    ) -> Result<u32, Status>;

    fn get_grpc_call_response_body(&self, start: usize, max_size: usize) -> Option<Vec<u8>>;

    fn get_grpc_status(&self) -> Option<String>;

    fn cancel_grpc_call(&self, token_id: u32) -> Result<(), Status>;
}

pub struct DefaultGrpcHost;

impl GrpcHost for DefaultGrpcHost {
    fn dispatch_grpc_call(
        &self,
        upstream_name: &str,
        service_name: &str,
        method_name: &str,
        initial_metadata: Vec<(&str, &[u8])>,
        message: Option<&[u8]>,
        timeout: Duration,
    ) -> Result<u32, Status> {
        hostcalls::dispatch_grpc_call(
            upstream_name,
            service_name,
            method_name,
            initial_metadata,
            message,
            timeout,
        )
    }

    fn get_grpc_call_response_body(&self, start: usize, max_size: usize) -> Option<Vec<u8>> {
        hostcalls::get_buffer(BufferType::GrpcReceiveBuffer, start, max_size).unwrap_or_default()
    }

    fn cancel_grpc_call(&self, token_id: u32) -> Result<(), Status> {
        hostcalls::cancel_grpc_call(token_id)
    }

    fn get_grpc_status(&self) -> Option<String> {
        hostcalls::get_grpc_status().ok().and_then(|(_, s)| s)
    }
}