use crate::ayb_db::db_interfaces::AybDb;
use crate::ayb_db::models::{InstantiatedEntity, PartialDatabase, PublicSharingLevel};
use std::str::FromStr;

use crate::error::AybError;
use crate::http::structs::{EmptyResponse, EntityDatabasePath};
use crate::server::permissions::can_manage_database;
use crate::server::utils::{get_optional_header, unwrap_authenticated_entity};
use actix_web::{patch, web, HttpRequest, HttpResponse};

#[patch(
    "/{entity}/{database}/update",
    wrap = "actix_web_httpauth::middleware::HttpAuthentication::bearer(crate::server::server_runner::entity_validator)"
)]
async fn update_database(
    path: web::Path<EntityDatabasePath>,
    req: HttpRequest,
    ayb_db: web::Data<Box<dyn AybDb>>,
    authenticated_entity: Option<web::ReqData<InstantiatedEntity>>,
) -> Result<HttpResponse, AybError> {
    let entity_slug = &path.entity.to_lowercase();
    let database_slug = &path.database;
    let database = ayb_db.get_database(entity_slug, database_slug).await?;
    let authenticated_entity = unwrap_authenticated_entity(&authenticated_entity)?;
    if can_manage_database(&authenticated_entity, &database, &ayb_db).await? {
        let public_sharing_level = get_optional_header(&req, "public-sharing-level")?;
        let mut partial_database = PartialDatabase {
            public_sharing_level: None,
        };
        if let Some(level) = public_sharing_level {
            partial_database.public_sharing_level =
                Some(PublicSharingLevel::from_str(&level)? as i16);
        }

        // Check if there are any fields to update
        if !partial_database.has_updates() {
            return Err(AybError::EmptyUpdateError {
                message:
                    "No fields provided to update. Please specify at least one field to update."
                        .to_string(),
            });
        }

        ayb_db
            .update_database_by_id(database.id, &partial_database)
            .await?;
        Ok(HttpResponse::Ok().json(EmptyResponse {}))
    } else {
        Err(AybError::Other {
            message: format!(
                "Authenticated entity {} can't update database {}/{}",
                authenticated_entity.slug, entity_slug, database_slug
            ),
        })
    }
}
