//! Base credential policy builder for WASM.

use wasm_bindgen::prelude::*;

use crate::error::LastIDError;
use crate::policies::PolicyBuilder;
use crate::types::CredentialPolicyRequest;

/// Base credential policy builder for WASM.
///
/// Creates a policy for requesting the basic user DID credential.
///
/// # JavaScript Usage
///
/// ```javascript
/// const policy = new BaseCredentialPolicy()
///     .withState("csrf-token")
///     .withNonce("binding-nonce")
///     .withCallback("https://yourapp.com/callback");
///
/// const response = await client.requestCredential(policy);
/// ```
#[wasm_bindgen(js_name = BaseCredentialPolicy)]
pub struct WasmBaseCredentialPolicy {
    callback_url: Option<String>,
    state: Option<String>,
    nonce: Option<String>,
}

#[wasm_bindgen(js_class = BaseCredentialPolicy)]
impl WasmBaseCredentialPolicy {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Self {
        Self {
            callback_url: None,
            state: None,
            nonce: None,
        }
    }

    #[wasm_bindgen(js_name = withCallback)]
    pub fn with_callback(mut self, url: String) -> Self {
        self.callback_url = Some(url);
        self
    }

    #[wasm_bindgen(js_name = withState)]
    pub fn with_state(mut self, state: String) -> Self {
        self.state = Some(state);
        self
    }

    #[wasm_bindgen(js_name = withNonce)]
    pub fn with_nonce(mut self, nonce: String) -> Self {
        self.nonce = Some(nonce);
        self
    }

    #[wasm_bindgen(js_name = credentialType, getter)]
    pub fn credential_type(&self) -> String {
        "LastID.Base".to_string()
    }

    #[wasm_bindgen(js_name = isComplete, getter)]
    pub fn is_complete(&self) -> bool {
        self.callback_url.is_some()
    }
}

impl Default for WasmBaseCredentialPolicy {
    fn default() -> Self {
        Self::new()
    }
}

impl PolicyBuilder for WasmBaseCredentialPolicy {
    fn credential_type(&self) -> &'static str {
        "LastID.Base"
    }

    fn to_request(self) -> Result<CredentialPolicyRequest, LastIDError> {
        let callback_url = self
            .callback_url
            .ok_or_else(|| LastIDError::policy_validation("Callback URL is required"))?;

        crate::types::EndpointUrl::new(&callback_url)?;

        let mut request = CredentialPolicyRequest::with_chain("LastID.Base");
        request.callback_url = Some(callback_url);
        request.state = self.state;
        request.nonce = self.nonce;
        Ok(request)
    }
}
