//! Verified email credential policy builder for WASM.

use wasm_bindgen::prelude::*;

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

/// Verified email credential policy builder for WASM.
///
/// # JavaScript Usage
///
/// ```javascript
/// const policy = new VerifiedEmailPolicy()
///     .withDomainConstraint("company.com")
///     .withCallback("https://yourapp.com/callback");
/// ```
#[wasm_bindgen(js_name = VerifiedEmailPolicy)]
pub struct WasmVerifiedEmailPolicy {
    callback_url: Option<String>,
    domain_constraint: Option<String>,
}

#[wasm_bindgen(js_class = VerifiedEmailPolicy)]
impl WasmVerifiedEmailPolicy {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Self {
        Self {
            callback_url: None,
            domain_constraint: None,
        }
    }

    /// Add a domain constraint (e.g., "example.com" requires @example.com
    /// emails).
    #[wasm_bindgen(js_name = withDomainConstraint)]
    pub fn with_domain_constraint(mut self, domain: String) -> Self {
        self.domain_constraint = Some(domain);
        self
    }

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

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

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

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

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

    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)?;

        if let Some(ref domain) = self.domain_constraint {
            if domain.is_empty() || domain.contains('@') {
                return Err(LastIDError::policy_validation(
                    "Domain constraint must be a valid domain (e.g., 'example.com')",
                ));
            }
        }

        let constraints = self.domain_constraint.as_ref().map(|domain| {
            let mut map = std::collections::HashMap::new();
            map.insert("domainConstraint".to_string(), serde_json::json!(domain));
            map
        });

        let mut request = CredentialPolicyRequest::with_chain("LastID.VerifiedEmail");
        request.callback_url = Some(callback_url);
        request.constraints = constraints;
        Ok(request)
    }
}
