use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Artifact {
    pub id: String,
    pub artifact_type: ArtifactType,
    pub producer_stage: String,
    pub producer_agent: String,
    pub content_ref: String,
    pub metadata: serde_json::Value,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ArtifactType {
    Adr,
    Code,
    TestResults,
    Review,
    Documentation,
    Custom(String),
}

impl Artifact {
    pub fn new(
        artifact_type: ArtifactType,
        producer_stage: String,
        producer_agent: String,
        content_ref: String,
    ) -> Self {
        Self {
            id: uuid::Uuid::new_v4().to_string(),
            artifact_type,
            producer_stage,
            producer_agent,
            content_ref,
            metadata: serde_json::json!({}),
            created_at: Utc::now(),
        }
    }

    pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
        self.metadata = metadata;
        self
    }
}

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

    #[test]
    fn test_artifact_creation() {
        let artifact = Artifact::new(
            ArtifactType::Code,
            "implementation".to_string(),
            "agent-123".to_string(),
            "kg://artifact/456".to_string(),
        );

        assert_eq!(artifact.artifact_type, ArtifactType::Code);
        assert_eq!(artifact.producer_stage, "implementation");
        assert_eq!(artifact.producer_agent, "agent-123");
    }

    #[test]
    fn test_artifact_with_metadata() {
        let metadata = serde_json::json!({
            "language": "rust",
            "files_changed": 5
        });

        let artifact = Artifact::new(
            ArtifactType::Code,
            "implementation".to_string(),
            "agent-123".to_string(),
            "kg://artifact/456".to_string(),
        )
        .with_metadata(metadata.clone());

        assert_eq!(artifact.metadata, metadata);
    }

    #[test]
    fn test_artifact_type_serialization() {
        let types = vec![
            ArtifactType::Adr,
            ArtifactType::Code,
            ArtifactType::TestResults,
            ArtifactType::Review,
            ArtifactType::Documentation,
            ArtifactType::Custom("benchmark".to_string()),
        ];

        for artifact_type in types {
            let json = serde_json::to_string(&artifact_type).unwrap();
            let deserialized: ArtifactType = serde_json::from_str(&json).unwrap();
            assert_eq!(artifact_type, deserialized);
        }
    }
}
