1
use std::collections::BTreeMap;
2

            
3
use serde::{Deserialize, Serialize};
4
use serde_json::json;
5
use thiserror::Error;
6

            
7
use crate::core::{
8
    protocol::request_validation::ValidationError,
9
    types::{DbOrUser, MySQLDatabase},
10
};
11

            
12
pub type CreateDatabasesRequest = Vec<MySQLDatabase>;
13

            
14
pub type CreateDatabasesResponse = BTreeMap<MySQLDatabase, Result<(), CreateDatabaseError>>;
15

            
16
#[derive(Error, Debug, Clone, PartialEq, Serialize, Deserialize)]
17
pub enum CreateDatabaseError {
18
    #[error("Validation error: {0}")]
19
    ValidationError(#[from] ValidationError),
20

            
21
    #[error("Database already exists")]
22
    DatabaseAlreadyExists,
23

            
24
    #[error("MySQL error: {0}")]
25
    MySqlError(String),
26
}
27

            
28
pub fn print_create_databases_output_status(output: &CreateDatabasesResponse) {
29
    for (database_name, result) in output {
30
        match result {
31
            Ok(()) => {
32
                println!("Database '{database_name}' created successfully.");
33
            }
34
            Err(err) => {
35
                eprintln!("{}", err.to_error_message(database_name));
36
                eprintln!("Skipping...");
37
            }
38
        }
39
        println!();
40
    }
41
}
42

            
43
pub fn print_create_databases_output_status_json(output: &CreateDatabasesResponse) {
44
    let value = output
45
        .iter()
46
        .map(|(name, result)| match result {
47
            Ok(()) => (name.to_string(), json!({ "status": "success" })),
48
            Err(err) => (
49
                name.to_string(),
50
                json!({
51
                  "status": "error",
52
                  "type": err.error_type(),
53
                  "error": err.to_error_message(name),
54
                }),
55
            ),
56
        })
57
        .collect::<serde_json::Map<_, _>>();
58
    println!(
59
        "{}",
60
        serde_json::to_string_pretty(&value)
61
            .unwrap_or("Failed to serialize result to JSON".to_string())
62
    );
63
}
64

            
65
impl CreateDatabaseError {
66
    #[must_use]
67
    pub fn to_error_message(&self, database_name: &MySQLDatabase) -> String {
68
        match self {
69
            CreateDatabaseError::ValidationError(err) => {
70
                err.to_error_message(&DbOrUser::Database(database_name.clone()))
71
            }
72
            CreateDatabaseError::DatabaseAlreadyExists => {
73
                format!("Database {database_name} already exists.")
74
            }
75
            CreateDatabaseError::MySqlError(err) => {
76
                format!("MySQL error: {err}")
77
            }
78
        }
79
    }
80

            
81
    #[must_use]
82
    pub fn error_type(&self) -> String {
83
        match self {
84
            CreateDatabaseError::ValidationError(err) => err.error_type(),
85
            CreateDatabaseError::DatabaseAlreadyExists => "database-already-exists".to_string(),
86
            CreateDatabaseError::MySqlError(_) => "mysql-error".to_string(),
87
        }
88
    }
89
}
90

            
91
#[cfg(test)]
92
mod tests {
93
    use super::*;
94

            
95
    #[test]
96
1
    fn test_serialize_deserialize_request() {
97
1
        let request: CreateDatabasesRequest =
98
1
            vec!["test_db1".into(), "test_db2".into(), "test_db3".into()];
99

            
100
1
        let json = serde_json::to_string_pretty(&request).unwrap();
101
1
        println!("Serialized request:\n{}", json);
102

            
103
1
        let deserialized: CreateDatabasesRequest = serde_json::from_str(&json).unwrap();
104
1
        assert_eq!(request, deserialized);
105
1
    }
106

            
107
    #[test]
108
1
    fn test_serialize_deserialize_response() {
109
1
        let response: CreateDatabasesResponse = BTreeMap::from([
110
1
            ("test_db1".into(), Ok(())),
111
1
            (
112
1
                "test_db2".into(),
113
1
                Err(CreateDatabaseError::DatabaseAlreadyExists),
114
1
            ),
115
1
            (
116
1
                "test_db3".into(),
117
1
                Err(CreateDatabaseError::MySqlError("Some MySQL error".into())),
118
1
            ),
119
1
        ]);
120

            
121
1
        let json = serde_json::to_string_pretty(&response).unwrap();
122
1
        println!("Serialized response:\n{}", json);
123

            
124
1
        let deserialized: CreateDatabasesResponse = serde_json::from_str(&json).unwrap();
125
1
        assert_eq!(response, deserialized);
126
1
    }
127
}