//use ::entity::entities::prelude::Book;
//use ::entity::entities::{prelude::*, *};
use ::entity::entities::book::Entity as Book;
use ::entity::entities::user::Entity as User;
//, book_author::Entity as Author, book_person::Entity as Person, book_place::Entity as Place, book_subject::Entity as Subject, book_time::Entity as Time, book_isbn::Entity as ISBN};
use ::entity::entities::{
    book, book_author, book_isbn, book_person, book_place, book_subject, book_time, user,
};
use sea_orm::*;
//use ::entity::entities::prelude::Book;

pub struct Mutation;

impl Mutation {
    pub async fn create_user(
        db: &DbConn,
        form_data: user::Model,
    ) -> Result<InsertResult<user::ActiveModel>, DbErr> {
        let record = user::ActiveModel {
            user_name: Set(form_data.user_name.to_owned()),
            password_hash: Set(form_data.password_hash.to_owned()),
            ..Default::default()
        };
        User::insert(record).exec(db).await
    }

    pub async fn delete_user(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        let user: user::ActiveModel = User::find_by_id(id)
            .one(db)
            .await?
            .ok_or(DbErr::Custom("Cannot find user.".to_owned()))
            .map(Into::into)?;

        user.delete(db).await
    }

    pub async fn create_book(
        db: &DbConn,
        form_data: book::Model,
    ) -> Result<InsertResult<book::ActiveModel>, DbErr> {
        let record = book::ActiveModel {
            open_library_key: Set(form_data.open_library_key.to_owned()),
            title: Set(form_data.title.to_owned()),
            edition_count: Set(form_data.edition_count.to_owned()),
            first_publish_year: Set(form_data.first_publish_year.to_owned()),
            median_page_count: Set(form_data.median_page_count.to_owned()),
            goodread_id: Set(form_data.goodread_id.to_owned()),
            description: Set(form_data.description.to_owned()),
            cover: Set(form_data.cover.to_owned()),
            location: Set(form_data.location.to_owned()),
            time_added: Set(form_data.time_added.to_owned()),
            rating: Set(form_data.rating.to_owned()),
            comments: Set(form_data.comments.to_owned()),
            user_id: Set(form_data.user_id.to_owned()),
            ..Default::default()
        };
        Book::insert(record).exec(db).await
    }

    pub async fn create_book_author(
        db: &DbConn,
        form_data: book_author::Model,
    ) -> Result<book_author::ActiveModel, DbErr> {
        book_author::ActiveModel {
            book_id: Set(form_data.book_id.to_owned()),
            author_name: Set(form_data.author_name.to_owned()),
            ..Default::default()
        }
        .save(db)
        .await
    }

    pub async fn create_book_person(
        db: &DbConn,
        form_data: book_person::Model,
    ) -> Result<book_person::ActiveModel, DbErr> {
        book_person::ActiveModel {
            book_id: Set(form_data.book_id.to_owned()),
            person: Set(form_data.person.to_owned()),
            ..Default::default()
        }
        .save(db)
        .await
    }

    pub async fn create_book_place(
        db: &DbConn,
        form_data: book_place::Model,
    ) -> Result<book_place::ActiveModel, DbErr> {
        book_place::ActiveModel {
            book_id: Set(form_data.book_id.to_owned()),
            place: Set(form_data.place.to_owned()),
            ..Default::default()
        }
        .save(db)
        .await
    }
    pub async fn create_book_subject(
        db: &DbConn,
        form_data: book_subject::Model,
    ) -> Result<book_subject::ActiveModel, DbErr> {
        book_subject::ActiveModel {
            book_id: Set(form_data.book_id.to_owned()),
            subject: Set(form_data.subject.to_owned()),
            ..Default::default()
        }
        .save(db)
        .await
    }

    pub async fn create_book_time(
        db: &DbConn,
        form_data: book_time::Model,
    ) -> Result<book_time::ActiveModel, DbErr> {
        book_time::ActiveModel {
            book_id: Set(form_data.book_id.to_owned()),
            time: Set(form_data.time.to_owned()),
            ..Default::default()
        }
        .save(db)
        .await
    }

    pub async fn create_book_isbn(
        db: &DbConn,
        form_data: book_isbn::Model,
    ) -> Result<book_isbn::ActiveModel, DbErr> {
        book_isbn::ActiveModel {
            book_id: Set(form_data.book_id.to_owned()),
            isbn: Set(form_data.isbn.to_owned()),
            ..Default::default()
        }
        .save(db)
        .await
    }

    pub async fn update_book_by_id(
        db: &DbConn,
        id: i32,
        form_data: book::Model,
    ) -> Result<book::Model, DbErr> {
        let book: book::ActiveModel = Book::find_by_id(id)
            .one(db)
            .await?
            .ok_or(DbErr::Custom("Cannot find book.".to_owned()))
            .map(Into::into)?;

        book::ActiveModel {
            id: book.id,
            open_library_key: Set(form_data.open_library_key.to_owned()),
            title: Set(form_data.title.to_owned()),
            edition_count: Set(form_data.edition_count.to_owned()),
            first_publish_year: Set(form_data.first_publish_year.to_owned()),
            median_page_count: Set(form_data.median_page_count.to_owned()),
            goodread_id: Set(form_data.goodread_id.to_owned()),
            description: Set(form_data.description.to_owned()),
            cover: Set(form_data.cover.to_owned()),
            location: Set(form_data.location.to_owned()),
            time_added: Set(form_data.time_added.to_owned()),
            rating: Set(form_data.rating.to_owned()),
            comments: Set(form_data.comments.to_owned()),
            user_id: Set(form_data.user_id.to_owned()),
        }
        .update(db)
        .await
    }

    pub async fn delete_book(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        let book: book::ActiveModel = Book::find_by_id(id)
            .one(db)
            .await?
            .ok_or(DbErr::Custom("Cannot find book.".to_owned()))
            .map(Into::into)?;

        book.delete(db).await
    }

    pub async fn delete_book_author(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        book_author::Entity::delete_many()
            .filter(Condition::any().add(book_author::Column::BookId.eq(id)))
            .exec(db)
            .await
    }

    pub async fn delete_book_person(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        book_person::Entity::delete_many()
            .filter(Condition::any().add(book_person::Column::BookId.eq(id)))
            .exec(db)
            .await
    }

    pub async fn delete_book_place(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        book_place::Entity::delete_many()
            .filter(Condition::any().add(book_place::Column::BookId.eq(id)))
            .exec(db)
            .await
    }

    pub async fn delete_book_subject(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        book_subject::Entity::delete_many()
            .filter(Condition::any().add(book_subject::Column::BookId.eq(id)))
            .exec(db)
            .await
    }

    pub async fn delete_book_time(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        book_time::Entity::delete_many()
            .filter(Condition::any().add(book_time::Column::BookId.eq(id)))
            .exec(db)
            .await
    }

    pub async fn delete_book_isbn(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
        book_isbn::Entity::delete_many()
            .filter(Condition::any().add(book_isbn::Column::BookId.eq(id)))
            .exec(db)
            .await
    }

    pub async fn delete_all_books(db: &DbConn) -> Result<DeleteResult, DbErr> {
        Book::delete_many().exec(db).await
    }
}
