use serde::{Deserialize, Serialize};
use time::OffsetDateTime;

use crate::ids::{SecretId, UserId, WorkspaceId};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SecretKind {
    Token,
    UsernamePassword,
    Header,
    Generic,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SecretStatus {
    Active,
    Disabled,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Secret {
    pub id: SecretId,
    pub workspace_id: WorkspaceId,
    pub name: String,
    pub kind: SecretKind,
    pub status: SecretStatus,
    pub current_version: u32,
    #[serde(with = "time::serde::rfc3339")]
    pub created_at: OffsetDateTime,
    #[serde(with = "time::serde::rfc3339")]
    pub updated_at: OffsetDateTime,
    #[serde(with = "time::serde::rfc3339::option")]
    pub last_used_at: Option<OffsetDateTime>,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct SecretVersion {
    pub secret_id: SecretId,
    pub version: u32,
    pub ciphertext: String,
    pub key_version: String,
    #[serde(with = "time::serde::rfc3339")]
    pub created_at: OffsetDateTime,
    pub created_by: Option<UserId>,
}

#[cfg(test)]
mod tests {
    use serde_json::json;
    use time::{OffsetDateTime, format_description::well_known::Rfc3339};

    use super::{Secret, SecretKind, SecretStatus, SecretVersion};
    use crate::ids::{SecretId, UserId, WorkspaceId};

    #[test]
    fn secret_serializes_timestamps_as_rfc3339() {
        let secret = Secret {
            id: SecretId::new("secret_01"),
            workspace_id: WorkspaceId::new("ws_01"),
            name: "primary".to_owned(),
            kind: SecretKind::Token,
            status: SecretStatus::Active,
            current_version: 2,
            created_at: OffsetDateTime::parse("2026-03-25T12:00:00Z", &Rfc3339).unwrap(),
            updated_at: OffsetDateTime::parse("2026-03-25T12:05:00Z", &Rfc3339).unwrap(),
            last_used_at: Some(OffsetDateTime::parse("2026-03-25T12:07:00Z", &Rfc3339).unwrap()),
        };

        let value = serde_json::to_value(&secret).unwrap();

        assert_eq!(value["created_at"], json!("2026-03-25T12:00:00Z"));
        assert_eq!(value["updated_at"], json!("2026-03-25T12:05:00Z"));
        assert_eq!(value["last_used_at"], json!("2026-03-25T12:07:00Z"));
    }

    #[test]
    fn secret_version_deserializes_created_at_from_rfc3339() {
        let version: SecretVersion = serde_json::from_value(json!({
            "secret_id": "secret_01",
            "version": 2,
            "ciphertext": "opaque",
            "key_version": "v2",
            "created_at": "2026-03-25T12:07:00Z",
            "created_by": "user_01"
        }))
        .unwrap();

        assert_eq!(
            version.created_at,
            OffsetDateTime::parse("2026-03-25T12:07:00Z", &Rfc3339).unwrap()
        );
        assert_eq!(version.created_by, Some(UserId::new("user_01")));
    }
}
