// file: kb_lib/src/db/dtos/wallet.rs

//! Wallet DTO.

/// Application-facing wallet DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WalletDto {
    /// Optional numeric primary key.
    pub id: std::option::Option<i64>,
    /// Stable wallet address.
    pub address: std::string::String,
    /// Optional user-defined label.
    pub label: std::option::Option<std::string::String>,
    /// Creation timestamp.
    pub first_seen_at: chrono::DateTime<chrono::Utc>,
    /// Update timestamp.
    pub last_seen_at: chrono::DateTime<chrono::Utc>,
}

impl WalletDto {
    /// Creates a new wallet DTO.
    pub fn new(
        address: std::string::String,
        label: std::option::Option<std::string::String>,
    ) -> Self {
        let now = chrono::Utc::now();
        return Self {
            id: None,
            address,
            label,
            first_seen_at: now,
            last_seen_at: now,
        };
    }
}

impl TryFrom<crate::WalletEntity> for WalletDto {
    type Error = crate::Error;

    fn try_from(entity: crate::WalletEntity) -> Result<Self, Self::Error> {
        let first_seen_at_result = chrono::DateTime::parse_from_rfc3339(&entity.first_seen_at);
        let first_seen_at = match first_seen_at_result {
            Ok(first_seen_at) => first_seen_at.with_timezone(&chrono::Utc),
            Err(error) => {
                return Err(crate::Error::Db(format!(
                    "cannot parse wallet first_seen_at '{}': {}",
                    entity.first_seen_at, error
                )));
            },
        };
        let last_seen_at_result = chrono::DateTime::parse_from_rfc3339(&entity.last_seen_at);
        let last_seen_at = match last_seen_at_result {
            Ok(last_seen_at) => last_seen_at.with_timezone(&chrono::Utc),
            Err(error) => {
                return Err(crate::Error::Db(format!(
                    "cannot parse wallet last_seen_at '{}': {}",
                    entity.last_seen_at, error
                )));
            },
        };
        return Ok(Self {
            id: Some(entity.id),
            address: entity.address,
            label: entity.label,
            first_seen_at,
            last_seen_at,
        });
    }
}
