//! Login item core: username, password (Zeroizing), URL, optional TOTP.

use serde::{Deserialize, Serialize};
use url::Url;
use zeroize::Zeroizing;

use crate::item_types::TotpConfig;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LoginCore {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub username: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub password: Option<Zeroizing<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub url: Option<Url>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub totp: Option<TotpConfig>,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn empty_login_round_trips() {
        let login = LoginCore::default();
        let json = serde_json::to_string(&login).unwrap();
        let parsed: LoginCore = serde_json::from_str(&json).unwrap();
        assert!(parsed.username.is_none());
        assert!(parsed.password.is_none());
    }

    #[test]
    fn full_login_round_trips() {
        let login = LoginCore {
            username: Some("alice".into()),
            password: Some(Zeroizing::new("hunter2".into())),
            url: Some(Url::parse("https://github.com/login").unwrap()),
            totp: None,
        };
        let json = serde_json::to_string(&login).unwrap();
        let parsed: LoginCore = serde_json::from_str(&json).unwrap();
        assert_eq!(parsed.username.as_deref(), Some("alice"));
        assert_eq!(parsed.password.as_deref().map(String::as_str), Some("hunter2"));
        assert_eq!(parsed.url.as_ref().map(Url::as_str), Some("https://github.com/login"));
    }

    #[test]
    fn omitted_fields_dont_appear_in_json() {
        let login = LoginCore {
            username: Some("alice".into()),
            password: None,
            url: None,
            totp: None,
        };
        let json = serde_json::to_string(&login).unwrap();
        assert!(!json.contains("password"));
        assert!(!json.contains("url"));
        assert!(!json.contains("totp"));
        assert!(json.contains("alice"));
    }
}
