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

//! Known WebSocket endpoint DTO.

/// Application-facing known WebSocket endpoint DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KnownWsEndpointDto {
    /// Logical endpoint name.
    pub name: std::string::String,
    /// Provider name.
    pub provider: std::string::String,
    /// Endpoint URL.
    pub url: std::string::String,
    /// Whether this endpoint is enabled.
    pub enabled: bool,
    /// Declared roles.
    pub roles: std::vec::Vec<std::string::String>,
    /// Optional last seen timestamp.
    pub last_seen_at: std::option::Option<chrono::DateTime<chrono::Utc>>,
    /// Last update timestamp.
    pub updated_at: chrono::DateTime<chrono::Utc>,
}

impl KnownWsEndpointDto {
    /// Creates a new DTO with the current update timestamp.
    pub fn new(
        name: std::string::String,
        provider: std::string::String,
        url: std::string::String,
        enabled: bool,
        roles: std::vec::Vec<std::string::String>,
    ) -> Self {
        return Self {
            name,
            provider,
            url,
            enabled,
            roles,
            last_seen_at: None,
            updated_at: chrono::Utc::now(),
        };
    }
}

impl TryFrom<crate::KnownWsEndpointEntity> for KnownWsEndpointDto {
    type Error = crate::Error;

    fn try_from(entity: crate::KnownWsEndpointEntity) -> Result<Self, Self::Error> {
        let roles_result =
            serde_json::from_str::<std::vec::Vec<std::string::String>>(&entity.roles_json);
        let roles = match roles_result {
            Ok(roles) => roles,
            Err(error) => {
                return Err(crate::Error::Db(format!(
                    "cannot parse known ws endpoint roles_json '{}': {}",
                    entity.roles_json, error
                )));
            },
        };
        let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
        let updated_at = match updated_at_result {
            Ok(updated_at) => updated_at.with_timezone(&chrono::Utc),
            Err(error) => {
                return Err(crate::Error::Db(format!(
                    "cannot parse known ws endpoint updated_at '{}': {}",
                    entity.updated_at, error
                )));
            },
        };
        let last_seen_at = match entity.last_seen_at {
            Some(last_seen_at_text) => {
                let parsed_result = chrono::DateTime::parse_from_rfc3339(&last_seen_at_text);
                match parsed_result {
                    Ok(parsed) => Some(parsed.with_timezone(&chrono::Utc)),
                    Err(error) => {
                        return Err(crate::Error::Db(format!(
                            "cannot parse known ws endpoint last_seen_at '{}': {}",
                            last_seen_at_text, error
                        )));
                    },
                }
            },
            None => None,
        };
        return Ok(Self {
            name: entity.name,
            provider: entity.provider,
            url: entity.url,
            enabled: entity.enabled != 0,
            roles,
            last_seen_at,
            updated_at,
        });
    }
}

impl TryFrom<KnownWsEndpointDto> for crate::KnownWsEndpointEntity {
    type Error = crate::Error;

    fn try_from(dto: KnownWsEndpointDto) -> Result<Self, Self::Error> {
        let roles_json_result = serde_json::to_string(&dto.roles);
        let roles_json = match roles_json_result {
            Ok(roles_json) => roles_json,
            Err(error) => {
                return Err(crate::Error::Db(format!(
                    "cannot serialize known ws endpoint roles: {}",
                    error
                )));
            },
        };
        return Ok(Self {
            name: dto.name,
            provider: dto.provider,
            url: dto.url,
            enabled: if dto.enabled { 1 } else { 0 },
            roles_json,
            last_seen_at: dto.last_seen_at.map(|value| return value.to_rfc3339()),
            updated_at: dto.updated_at.to_rfc3339(),
        });
    }
}
