use crate::error::OrmError;
use crate::pagination::{Page, Pagination};
use crate::{DeleteQuery, DropQuery, InsertQuery, SelectQuery, UpdateQuery};
use sqlx::{Any, Pool};

#[async_trait::async_trait]
pub trait Entity:
where
    Self: Sized,
{
    async fn get_pool() -> Result<Pool<Any>, OrmError>;
    fn dump_schema() -> std::io::Result<()>;
    fn get_table_name() -> String;
    fn get_column_names() -> Vec<String>;
    fn get_sequence_name() -> Option<String>;
    fn get_primary_key_column() -> String;
    fn get_query_example(&self) -> SelectQuery;
    fn get_plain_query() -> SelectQuery;
    fn get_insert_query(&self) -> InsertQuery;
    fn get_update_query(&self) -> UpdateQuery;
    fn get_plain_insert_query() -> InsertQuery;
    fn get_delete_query() -> DeleteQuery;
    fn get_drop_query() -> DropQuery;
    async fn query_example(&self, pagination: Option<Pagination>, pool: &Pool<Any>) -> Result<Page<Self>, OrmError>;
    async fn insert(&self, pool: &Pool<Any>) -> Result<Self, OrmError>;
    async fn bulk_insert(entities: Vec<Self>, pool: &Pool<Any>) -> Result<Vec<Self>, OrmError>;
    async fn update(&self, pool: &Pool<Any>) -> Result<Self, OrmError>;
    async fn bulk_update(entities: Vec<Self>, pool: &Pool<Any>) -> Result<Vec<Self>, OrmError>;
    async fn update_by_example(example: Self, update: Self, pool: &Pool<Any>) -> Result<Vec<Self>, OrmError>;
    async fn delete(&self, pool: &Pool<Any>) -> Result<Self, OrmError>;
    async fn bulk_delete(entities: Vec<Self>, pool: &Pool<Any>) -> Result<Vec<Self>, OrmError>;
    async fn drop(pool: &Pool<Any>) -> Result<(), OrmError>;
}

#[rglw::codegen::test(name = "Test Entity Macro")]
mod tests {
    use crate::pagination::calculate_pagination;
    use crate::pagination::Page;
    use crate::types::{IdentityType, TriggerType::{BeforeInsert}};
    use crate::{error::OrmError, traits::entity::{Entity}, Storable};
    use crate::{get_pool, load_configuration, pagination::Pagination, query::{DeleteQuery, DropQuery, InsertQuery, Query, SelectQuery, UpdateQuery, WhereStatement, WhereType, WhereType::*}};
    use rglw_orm_codegen::{trigger, Entity, Enum};
    use serde::{Deserialize, Serialize};
    use sqlx::any::*;
    use sqlx::encode::*;
    use sqlx::error::*;
    use sqlx::postgres::any::*;
    use sqlx::*;
    use sqlx::{Any, Pool};
    use std::path::Path;
    use std::fs;

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    struct EntityA {
        #[primary_key]
        id: i64,
        some_field: String,
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, PartialEq, Entity, Serialize, Deserialize)]
    struct EntityB {
        #[primary_key(sequence = "some_sequence")]
        id: i64,
        some_field: String,
        #[unique]
        entity_a_id: i64,
        some_array: Storable<Vec<i64>>,
    }

    // #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    // #[relation(with=EntityD, foreign_key="entity_c_id", references="id", type="OneToMany", method="getAllD")]
    // struct EntityC {
    //     #[primary_key]
    //     id: i64,
    //     some_field: String,
    // }
    //
    // #[derive(Default, Debug, Clone, sqlx::FromRow, PartialEq, Entity, Serialize, Deserialize)]
    // struct EntityD {
    //     #[primary_key]
    //     id: i64,
    //     some_field: String,
    //     entity_c_id: i64,
    // }
    //
    // #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    // #[relation(with=EntityF, type="ManyToMany", method="getAllF", relationship_table="relationship_ef")]
    // struct EntityE {
    //     #[primary_key]
    //     id: i64,
    //     some_field: String,
    // }
    //
    // #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    // #[relation(with=EntityE, type="ManyToMany", method="getAllE", relationship_table="relationship_ef")]
    // struct EntityF {
    //     #[primary_key]
    //     id: i64,
    //     some_field: String,
    // }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[table_name = "some_other_name"]
    struct SomeEntityWithLargeName {
        #[primary_key]
        some_field: String,
    }

    #[derive(Clone, Default, Debug, Enum, PartialEq)]
    pub enum UserType {
        #[default]
        Customer,
        Admin,
    }

    #[derive(Clone, Default, Debug, Enum, PartialEq)]
    pub enum UserStatus {
        #[default]
        Active,
        Inactive,
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[triggers("some_trigger")]
    struct User {
        #[primary_key]
        pub id: i64,
        #[index="user_index"]
        #[unique]
        pub username: String,
        #[index="user_index"]
        #[check="email <> ''"]
        #[unique]
        pub email: String,
        pub user_type: UserType,
        #[column(name = "some_name", type = "VARCHAR(1000) NOT NULL")]
        pub user_status: UserStatus,
        pub age: Option<i64>,
    }
    
    impl User {
        #[trigger(name="TriggerName", event=BeforeInsert)]
        pub fn some_trigger() -> String {
            r"
            IF NEW.age < 18 THEN
                SIGNAL SQLSTATE '45000'
                SET MESSAGE_TEXT = 'ERROR: AGE MUST BE GREATER THAN OR EQUALS TO 18!';
            END IF;
            ".to_string()
        }
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    struct Users {
        #[primary_key]
        pub user_id: i64,
        pub username: String,
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[relation(with=Users, foreign_key="user_id", references="user_id", type="OneToOne", method="getUser")]
    struct UserProfiles {
        #[primary_key]
        pub profile_id: i64,
        pub user_id: i64,
        pub profile_data: String
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[relation(with=Employees, foreign_key="department_id", references="department_id", type="OneToMany", method="getEmployees")]
    struct Departments {
        #[primary_key]
        pub department_id: i64,
        pub department_name: String,
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[relation(with=Departments, foreign_key="department_id", references="department_id", type="ManyToOne", method="getDepartment")]
    struct Employees {
        #[primary_key]
        pub employee_id: i64,
        pub department_id: i64,
        pub employee_name: String
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[relation(with=Courses, type="ManyToMany", method="getAllCourses", relationship_table="student_courses")]
    struct Students {
        #[primary_key]
        pub student_id: i64,
        pub student_name: String,
    }

    #[derive(Default, Debug, Clone, sqlx::FromRow, Entity)]
    #[relation(with=Students, type="ManyToMany", method="getAllStudents", relationship_table="student_courses")]
    struct Courses {
        #[primary_key]
        pub course_id: i64,
        pub course_name: String,
    }

    #[rglw_codegen::before_all]
    pub async fn before_all() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let result = sqlx::query(
            "CREATE TABLE IF NOT EXISTS User(\
                    id INTEGER PRIMARY KEY AUTOINCREMENT,\
                    username TEXT NOT NULL,\
                    email TEXT NOT NULL,\
                    user_type TEXT NOT NULL,\
                    user_status TEXT NOT NULL,\
                    age INTEGER NULL DEFAULT 0\
                );\
                CREATE TABLE IF NOT EXISTS entity_a(\
                    id INTEGER PRIMARY KEY AUTOINCREMENT,\
                    some_field TEXT NOT NULL\
                );\
                CREATE TABLE IF NOT EXISTS entity_b(\
                    id INTEGER PRIMARY KEY AUTOINCREMENT,\
                    some_field TEXT NOT NULL,\
                    entity_a_id INTEGER UNIQUE NOT NULL,\
                    some_array TEXT NOT NULL,\
                    CONSTRAINT one_to_one FOREIGN KEY (entity_a_id) REFERENCES entity_a(id) ON DELETE CASCADE
                );\
                CREATE TABLE users (
                    user_id INT PRIMARY KEY,
                    username VARCHAR(50));
                CREATE TABLE user_profiles (
                    profile_id INT PRIMARY KEY,
                    user_id INT UNIQUE,
                    profile_data VARCHAR(255),
                    FOREIGN KEY (user_id) REFERENCES users(user_id));
                CREATE TABLE departments (
                    department_id INT PRIMARY KEY,
                    department_name VARCHAR(50));
                CREATE TABLE employees (
                    employee_id INT PRIMARY KEY,
                    employee_name VARCHAR(50),
                    department_id INT,
                    FOREIGN KEY (department_id) REFERENCES departments(department_id));
                CREATE TABLE students (
                    student_id INT PRIMARY KEY,
                    student_name VARCHAR(50));
                CREATE TABLE courses (
                    course_id INT PRIMARY KEY,
                    course_name VARCHAR(50));
                CREATE TABLE student_courses (
                    students_id INT,
                    courses_id INT,
                    PRIMARY KEY (students_id, courses_id),
                    FOREIGN KEY (students_id) REFERENCES students(student_id),
                    FOREIGN KEY (courses_id) REFERENCES courses(course_id));
").execute(&pool).await;
        assert!(result.is_ok());
        let result = sqlx::query(
            "\
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'Jonathan',
                    'email@rustyglw.org',
                    'Admin',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'User 1',
                    'user1@rustyglw.org',
                    'Customer',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'User 2',
                    'user2@rustyglw.org',
                    'Customer',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'User 3',
                    'user3@rustyglw.org',
                    'Customer',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'User 4',
                    'user4@rustyglw.org',
                    'Customer',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'User 5',
                    'user5@rustyglw.org',
                    'Customer',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'Delete Example',
                    'delete1@rustyglw.org',
                    'Customer',
                    'Active'
                );
                INSERT INTO User(username,email,user_type,user_status) VALUES (
                    'Delete Example',
                    'delete2@rustyglw.org',
                    'Customer',
                    'Active'
                );
            ").execute(&pool).await;
        assert!(result.is_ok());
    }

    #[rglw_codegen::after_all]
    pub async fn after_all() {
        fs::remove_file(Path::new("./entity.sqlite")).unwrap();
    }

    pub fn test_table_name() {
        assert_eq!(SomeEntityWithLargeName::get_table_name(), "some_other_name");
    }

    pub fn test_get_column_names() {
        assert_eq!(SomeEntityWithLargeName::get_column_names(), vec!["some_field"])
    }

    pub fn test_get_primary_key_column() {
        assert_eq!(EntityB::get_primary_key_column(), "id");
    }

    pub fn test_sequence_name() {
        assert_eq!(SomeEntityWithLargeName::get_sequence_name(), None);
        assert_eq!(EntityA::get_sequence_name(), None);
        assert_eq!(EntityB::get_sequence_name(), Some("some_sequence".to_string()));
    }

    pub fn test_get_query_example() {
        let entity = EntityA {
            id: 1,
            some_field: "some_field".to_string(),
        };
        let query = entity.get_query_example();
        assert_eq!(query.build(), "SELECT id, some_field\nFROM entity_a\nWHERE id = $1 AND some_field = $2;");
    }

    pub fn test_get_plain_query() {
        assert_eq!(User::get_plain_query().build(), "SELECT id, username, email, user_type, user_status, age\nFROM user;");
    }

    pub fn test_get_insert_query() {
        let entity = EntityB {
            some_field: "some_field".to_string(),
            entity_a_id: 2,
            ..Default::default()
        };
        let query = entity.get_insert_query();
        assert_eq!(query.build(), "INSERT INTO entity_b (id, some_field, entity_a_id, some_array) VALUES (nextval('some_sequence'), $1, $2, $3) RETURNING id;");
        let entity = EntityB {
            id: 1,
            some_field: "some_field".to_string(),
            entity_a_id: 2,
            some_array: Storable(Vec::new())
        };
        let query = entity.get_insert_query();
        assert_eq!(query.build(), "INSERT INTO entity_b (id, some_field, entity_a_id, some_array) VALUES ($1, $2, $3, $4) RETURNING id;");
        let entity = EntityA {
            some_field: "some_field".to_string(),
            ..Default::default()
        };
        let query = entity.get_insert_query();
        assert_eq!(query.build(), "INSERT INTO entity_a (some_field) VALUES ($1) RETURNING id;");
        let entity = EntityA {
            id: 1,
            some_field: "some_field".to_string(),
        };
        let query = entity.get_insert_query();
        assert_eq!(query.build(), "INSERT INTO entity_a (id, some_field) VALUES ($1, $2) RETURNING id;");
    }

    pub fn test_get_update_query() {
        let entity = EntityB {
            some_field: "some_field".to_string(),
            entity_a_id: 2,
            ..Default::default()
        };
        let query = entity.get_update_query();
        assert_eq!(query.build(), "UPDATE entity_b\nSET some_field = $1, entity_a_id = $2;");
    }

    pub fn test_get_plain_insert_query() {
        let mut query = EntityB::get_plain_insert_query();
        let query_string = query.build();
        assert_eq!(query_string, "INSERT INTO entity_b (id, some_field, entity_a_id, some_array) VALUES ($1, $2, $3, $4) RETURNING id;");
        query.remove_column("id".to_string());
        let query_string = query.build();
        assert_eq!(query_string, "INSERT INTO entity_b (id, some_field, entity_a_id, some_array) VALUES (nextval('some_sequence'), $1, $2, $3) RETURNING id;");
        let query = EntityA::get_plain_insert_query();
        assert_eq!(query.build(), "INSERT INTO entity_a (id, some_field) VALUES ($1, $2) RETURNING id;");
    }

    pub fn test_get_delete_query() {
        let query = EntityB::get_delete_query();
        assert_eq!(query.build(), "DELETE FROM entity_b;");
    }

    pub fn test_get_drop_query() {
        let query = EntityB::get_drop_query();
        assert_eq!(query.build(), "DROP TABLE entity_b;");
    }

    pub async fn test_query_example() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Jonathan".to_string(),
            ..Default::default()
        };
        let result = user.query_example(Some(Pagination {
            page_number: 1,
            page_size: 10,
        }), &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        assert_eq!(result.data.len(), 1);
        assert_eq!(result.data.first().unwrap().username, "Jonathan".to_string());
        assert_eq!(result.data.first().unwrap().user_type, UserType::Admin);
    }

    pub async fn test_insert() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Jonathan".to_string(),
            email: "some_new_email@test.com".to_string(),
            user_type: UserType::Admin,
            ..Default::default()
        };
        let result = user.insert(&pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        assert_eq!(result.username, "Jonathan".to_string());
        assert_eq!(result.email, "some_new_email@test.com".to_string());
        assert_eq!(result.user_type, UserType::Admin);
        assert_eq!(result.user_status, UserStatus::Active);
        assert!(result.id > 0);
    }

    pub async fn test_bulk_insert() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user1 = User {
            username: "Jonathan".to_string(),
            email: "some_new_email1@test.com".to_string(),
            user_type: UserType::Customer,
            ..Default::default()
        };
        let user2 = User {
            username: "Jonathan".to_string(),
            email: "some_new_email2@test.com".to_string(),
            user_type: UserType::Customer,
            ..Default::default()
        };
        let result = User::bulk_insert(vec![user1, user2], &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        assert_eq!(result.len(), 2);
        let first = result.first().unwrap();
        let last = result.last().unwrap();
        assert_eq!(first.email, "some_new_email1@test.com".to_string());
        assert_eq!(first.user_type, UserType::Customer);
        assert_eq!(last.email, "some_new_email2@test.com".to_string());
        assert_eq!(last.user_type, UserType::Customer);
    }

    pub async fn test_update() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Jonathan".to_string(),
            ..Default::default()
        };
        let result = user.query_example(None, &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        let mut user = result.data.first().unwrap().clone();
        user.username = "Updated username".to_string();
        user.user_status = UserStatus::Inactive;
        let updated_user = user.update(&pool).await.unwrap();
        assert_eq!(updated_user.username, "Updated username");
        assert_eq!(updated_user.user_status, UserStatus::Inactive);
    }

    pub async fn test_bulk_update() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Jonathan".to_string(),
            ..Default::default()
        };
        let result = user.query_example(None, &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        let users = result.data;
        let mut user1 = users.first().unwrap().clone();
        let mut user2 = users.last().unwrap().clone();
        user1.username = "Updated username 1".to_string();
        user2.username = "Updated username 2".to_string();
        let updated_user = User::bulk_update(vec![user1, user2], &pool).await;
        assert!(updated_user.is_ok());
        let updated_user = updated_user.unwrap();
        assert_eq!(updated_user.first().unwrap().username, "Updated username 1");
        assert_eq!(updated_user.last().unwrap().username, "Updated username 2");
    }

    pub async fn test_update_by_example() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Jonathan".to_string(),
            ..Default::default()
        };
        let result = User::update_by_example(user, User {
            username: "Updated username by example".to_string(),
            ..Default::default()
        }, &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        for entity in result {
            assert_eq!(entity.username, "Updated username by example");
        }
    }

    pub async fn test_delete() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Jonathan".to_string(),
            ..Default::default()
        };
        let result = user.query_example(Some(Pagination {
            page_number: 1,
            page_size: 10,
        }), &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        for entity in result.data {
            let deleted = entity.delete(&pool).await;
            assert!(deleted.is_ok());
        }
        let result = user.query_example(Some(Pagination {
            page_number: 1,
            page_size: 10,
        }), &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        assert_eq!(result.total_rows, 0);
    }

    pub async fn test_bulk_delete() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = User {
            username: "Delete Example".to_string(),
            ..Default::default()
        };
        let result = user.query_example(Some(Pagination {
            page_number: 1,
            page_size: 10,
        }), &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        let result = User::bulk_delete(result.data, &pool).await;
        assert!(result.is_ok());
        let result = user.query_example(Some(Pagination {
            page_number: 1,
            page_size: 10,
        }), &pool).await;
        assert!(result.is_ok());
        let result = result.unwrap();
        assert_eq!(result.total_rows, 0);
    }

    pub async fn test_drop() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let result = User::drop(&pool).await;
        assert!(result.is_ok());
        let user = User {
            username: "Delete Example".to_string(),
            ..Default::default()
        };
        let result = user.query_example(Some(Pagination {
            page_number: 1,
            page_size: 10,
        }), &pool).await;
        assert!(result.is_err());
        let error_message = result.err().unwrap().message;
        assert_eq!(error_message, "error returned from database: (code: 1) no such table: user");
    }

    pub async  fn test_relationships_one_to_one() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let user = Users {
            user_id: 20,
            username: "Some username".to_string(),
        };
        user.insert(&pool).await.unwrap();
        let user_profile = UserProfiles {
            profile_id: 21,
            user_id: 20,
            profile_data: String::from("Some profile data"),
        };
        user_profile.insert(&pool).await.unwrap();
        let profile_user = user_profile.getUser(&pool).await;
        assert!(profile_user.is_ok());
        let profile_user = profile_user.unwrap();
        assert_eq!(profile_user.user_id, 20);
    }

    pub async  fn test_relationships_one_to_many() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let department = Departments {
            department_id: 30,
            department_name: "Software".to_string(),
        };
        department.insert(&pool).await.unwrap();
        let employee_1 = Employees {
            employee_id: 31,
            employee_name: "Junior Dev".to_string(),
            department_id: 30,
        };
        employee_1.insert(&pool).await.unwrap();
        let employee_2 = Employees {
            employee_id: 32,
            employee_name: "Senior Dev".to_string(),
            department_id: 30,
        };
        employee_2.insert(&pool).await.unwrap();
        let department = employee_2.getDepartment(&pool).await;
        assert!(department.is_ok());
        let department: Departments = department.unwrap();
        assert_eq!(department.department_id, 30);
    }

    pub async  fn test_relationships_many_to_one() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        let department = Departments {
            department_id: 40,
            department_name: "Software".to_string(),
        };
        department.insert(&pool).await.unwrap();
        let employee_1 = Employees {
            employee_id: 41,
            employee_name: "Junior Dev".to_string(),
            department_id: 40,
        };
        employee_1.insert(&pool).await.unwrap();
        let employee_2 = Employees {
            employee_id: 42,
            employee_name: "Senior Dev".to_string(),
            department_id: 40,
        };
        employee_2.insert(&pool).await.unwrap();
        let employees = department.getEmployees(&pool).await;
        assert!(employees.is_ok());
        let employees: Vec<Employees> = employees.unwrap();
        assert_eq!(employees.len(), 2);
    }
    pub async  fn test_relationships_many_to_many() {
        let pool = get_pool("entity".to_string()).await;
        assert!(pool.is_ok());
        
        let pool = pool.unwrap();
        
        let student_1 = Students {
            student_id: 50,
            student_name: "Jonathan Franco".to_string(),
        };
        student_1.insert(&pool).await.unwrap();
        
        let student_2 = Students {
            student_id: 51,
            student_name: "Marcos Franco".to_string(),
        };
        student_2.insert(&pool).await.unwrap();
        
        let course_1 = Courses {
            course_id: 52,
            course_name: "Algorithms".to_string(),
        };
        course_1.insert(&pool).await.unwrap();
        
        let course_2 = Courses {
            course_id: 53,
            course_name: "Rustlang".to_string(),
        };
        course_2.insert(&pool).await.unwrap();
        
        course_1.with_Students(vec![50, 51], &pool).await.unwrap();
        course_2.with_Students(vec![50], &pool).await.unwrap();
        
        let student_1_courses = student_1.getAllCourses(&pool).await;
        assert!(student_1_courses.is_ok());
        let student_1_courses: Vec<Courses> = student_1_courses.unwrap();
        assert_eq!(student_1_courses.len(), 2);

        let student_2_courses = student_2.getAllCourses(&pool).await;
        assert!(student_2_courses.is_ok());
        let student_2_courses: Vec<Courses> = student_2_courses.unwrap();
        assert_eq!(student_2_courses.len(), 1);
        
        let course_1_students = course_1.getAllStudents(&pool).await;
        assert!(course_1_students.is_ok());
        let course_1_students: Vec<Students> = course_1_students.unwrap();
        assert_eq!(course_1_students.len(), 2);

        let course_2_students = course_2.getAllStudents(&pool).await;
        assert!(course_2_students.is_ok());
        let course_2_students: Vec<Students> = course_2_students.unwrap();
        assert_eq!(course_2_students.len(), 1);
    }

    pub fn test_dump_schema() {
        let result = User::dump_schema();
        assert!(result.is_ok());
        let result = EntityB::dump_schema();
        assert!(result.is_ok());
    }
}