//! The `ProductViewDelegate` trait.
//!
//! Implementors receive decoded host-api outcomes and are responsible for
//! routing them to the correct platform subsystem (WebView, wallet, RPC
//! bridge, navigation stack, …).
//!
//! All parameters use primitive std types (`Vec<u8>`, `String`, `u8`, `bool`)
//! so the trait can be implemented on any platform without coupling to
//! host-api internal types. Callers that hold a `HostApiOutcome` are
//! responsible for mapping its fields before calling the delegate.

use crate::error::ProductError;

/// Parameters for a chain head RPC operation dispatched to the host.
///
/// Grouping these fields avoids clippy's `too_many_arguments` lint while
/// keeping the data co-located for callers building the request.
#[derive(Debug, Clone)]
pub struct ChainRpcRequest {
    /// Original protocol byte; the host echoes it in the response so the
    /// product SDK can route it to the right handler.
    pub request_tag: u8,
    /// Raw 32-byte genesis hash identifying the target chain.
    pub genesis_hash: Vec<u8>,
    /// JSON-RPC method name (e.g. `"chainHead_v1_header"`).
    pub method: String,
    /// Serialised JSON params array (e.g. `"[]"` or `"[\"0x...\"]"`).
    pub params_json: String,
    /// Opaque follow-subscription ID from the product SDK; present for all
    /// chainHead operations that operate within a follow context.
    pub follow_sub_id: Option<String>,
}

/// Platform callback interface for a single embedded product view.
///
/// Each method corresponds to one `HostApiOutcome` variant that requires
/// host-side action. The `product_id` parameter identifies which product
/// is making the request when multiple views are hosted simultaneously.
///
/// **Note on `HostApiOutcome::Silent`:** this variant is intentionally
/// omitted from the delegate. Silent outcomes are fire-and-forget messages
/// that need no host action and no response to the product. Callers
/// dispatching `HostApiOutcome` should simply ignore `Silent`.
pub trait ProductViewDelegate {
    /// Deliver an encoded response back to the product's message port.
    ///
    /// Corresponds to `HostApiOutcome::Response`. The `bytes` are already
    /// SCALE-encoded; the host must forward them verbatim to the WebView.
    fn send_response(&self, product_id: &str, bytes: Vec<u8>) -> Result<(), ProductError>;

    /// A signing request is ready for wallet approval.
    ///
    /// Corresponds to `HostApiOutcome::NeedsSign`.
    ///
    /// - `request_tag` is the original protocol tag; the host must echo it in
    ///   the response so the product SDK can dispatch it correctly.
    /// - `public_key` identifies which account should sign.
    /// - `payload` is the raw bytes to be signed (extrinsic payload or raw data).
    fn needs_sign(
        &self,
        product_id: &str,
        request_id: &str,
        request_tag: u8,
        public_key: Vec<u8>,
        payload: Vec<u8>,
    ) -> Result<(), ProductError>;

    /// A JSON-RPC query must be forwarded to the chain RPC bridge.
    ///
    /// Corresponds to `HostApiOutcome::NeedsChainQuery`.
    ///
    /// `params_json` is the serialised JSON array or object from the
    /// JSON-RPC request (e.g. `"[]"` or `"[\"0x...\"]"`). Using `String`
    /// rather than `serde_json::Value` avoids pulling serde_json into every
    /// platform implementation.
    fn needs_chain_query(
        &self,
        product_id: &str,
        request_id: &str,
        method: &str,
        params_json: &str,
    ) -> Result<(), ProductError>;

    /// A JSON-RPC subscription must be set up via the chain RPC bridge.
    ///
    /// Corresponds to `HostApiOutcome::NeedsChainSubscription`.
    ///
    /// Unlike a one-shot query, the bridge must keep the subscription alive
    /// and forward each notification back via `send_response`.
    fn needs_chain_subscription(
        &self,
        product_id: &str,
        request_id: &str,
        method: &str,
        params_json: &str,
    ) -> Result<(), ProductError>;

    /// A `chainHead_v1_follow` subscription should be started for `genesis_hash`.
    ///
    /// Corresponds to `HostApiOutcome::NeedsChainFollow`.
    ///
    /// `genesis_hash` is the raw 32-byte genesis hash identifying the chain.
    /// `with_runtime` mirrors the chainHead follow `withRuntime` flag.
    fn needs_chain_follow(
        &self,
        product_id: &str,
        request_id: &str,
        genesis_hash: Vec<u8>,
        with_runtime: bool,
    ) -> Result<(), ProductError>;

    /// A chain head operation (header, storage, call, …) must be dispatched.
    ///
    /// Corresponds to `HostApiOutcome::NeedsChainRpc`.
    ///
    /// See [`ChainRpcRequest`] for field semantics.
    fn needs_chain_rpc(
        &self,
        product_id: &str,
        request_id: &str,
        req: ChainRpcRequest,
    ) -> Result<(), ProductError>;

    /// The product is requesting navigation to `url`.
    ///
    /// Corresponds to `HostApiOutcome::NeedsNavigate`.
    ///
    /// The host should resolve the URL (which may be a `.dot` name) and open
    /// it in the appropriate context (same tab, new tab, external browser, …).
    fn needs_navigate(
        &self,
        product_id: &str,
        request_id: &str,
        url: &str,
    ) -> Result<(), ProductError>;
}
