use pubky_common::crypto::PublicKey;
use sea_query::Iden;
use sqlx::{postgres::PgRow, FromRow, Row};
use crate::{
persistence::sql::{entities::user::UserIden, entry::EntryIden},
shared::webdav::{EntryPath, WebDavPath},
};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct EntryEntity {
pub id: i64,
pub user_id: i32,
pub path: EntryPath,
pub content_hash: pubky_common::crypto::Hash,
pub content_length: u64,
pub content_type: String,
pub modified_at: sqlx::types::chrono::NaiveDateTime,
pub created_at: sqlx::types::chrono::NaiveDateTime,
}
impl FromRow<'_, PgRow> for EntryEntity {
fn from_row(row: &PgRow) -> Result<Self, sqlx::Error> {
let id: i64 = row.try_get(EntryIden::Id.to_string().as_str())?;
let user_id: i32 = row.try_get(EntryIden::User.to_string().as_str())?;
let user_pubkey: String = row.try_get(UserIden::PublicKey.to_string().as_str())?;
let user_pubkey: PublicKey = user_pubkey
.parse()
.map_err(|e: pkarr::errors::PublicKeyError| sqlx::Error::Decode(e.into()))?;
let path: String = row.try_get(EntryIden::Path.to_string().as_str())?;
let webdav_path = WebDavPath::new(&path).map_err(|e| sqlx::Error::Decode(e.into()))?;
let entry_path = EntryPath::new(user_pubkey, webdav_path);
let content_hash_vec: Vec<u8> = row.try_get(EntryIden::ContentHash.to_string().as_str())?;
let content_hash: [u8; 32] = content_hash_vec
.try_into()
.map_err(|_| sqlx::Error::Decode("Content hash must be exactly 32 bytes".into()))?;
let content_hash = pubky_common::crypto::Hash::from_bytes(content_hash);
let content_length: i64 = row.try_get(EntryIden::ContentLength.to_string().as_str())?;
let content_type: String = row.try_get(EntryIden::ContentType.to_string().as_str())?;
let modified_at: sqlx::types::chrono::NaiveDateTime =
row.try_get(EntryIden::ModifiedAt.to_string().as_str())?;
let created_at: sqlx::types::chrono::NaiveDateTime =
row.try_get(EntryIden::CreatedAt.to_string().as_str())?;
Ok(EntryEntity {
id,
user_id,
path: entry_path,
content_hash,
content_length: content_length as u64,
content_type,
modified_at,
created_at,
})
}
}