// Copyright (C) 2025 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use ani_rs::business_error::BusinessError;
use ani_rs::AniEnv;
use request_client::RequestClient;
use request_utils::context::Context;

use crate::api10::bridge::GroupConfig;
use crate::constant::*;

/// Maximum allowed length for notification titles.
const MAX_TITLE_LENGTH: usize = 1024;
/// Maximum allowed length for notification text content.
const MAX_TEXT_LENGTH: usize = 3072;

/// Validates notification title and text length.
///
/// Checks that the title and text do not exceed their maximum allowed lengths.
///
/// # Parameters
///
/// * `title` - Optional notification title to validate
/// * `text` - Optional notification text to validate
///
/// # Returns
///
/// * `Ok(())` if both title and text are within limits
/// * `Err(BusinessError)` if either exceeds its maximum length
fn ParseTitleText(title: &Option<String>, text: &Option<String>) -> Result<(), BusinessError> {
    if let Some(v) = title {
        if v.len() > MAX_TITLE_LENGTH {
            return Err(BusinessError::new(
                ExceptionErrorCode::E_PARAMETER_CHECK as i32,
                "wrong parameters".to_string(),
            ));
        }
    }
    if let Some(v) = text {
        if v.len() > MAX_TEXT_LENGTH {
            return Err(BusinessError::new(
                ExceptionErrorCode::E_PARAMETER_CHECK as i32,
                "wrong parameters".to_string(),
            ));
        }
    }
    Ok(())
}

/// Validates group ID format.
///
/// Checks that the group ID is not empty.
///
/// # Parameters
///
/// * `gid` - Group ID to validate
///
/// # Returns
///
/// * `Ok(())` if the group ID is valid
/// * `Err(BusinessError)` if the group ID is empty
fn ParseGid(gid: &str) -> Result<(), BusinessError> {
    if gid.is_empty() {
        return Err(BusinessError::new(
            ExceptionErrorCode::E_PARAMETER_CHECK as i32,
            "wrong parameters".to_string(),
        ));
    }
    Ok(())
}

/// Validates the notification configuration for a task group.
///
/// # Returns
///
/// * `Ok(())` if the configuration is valid
/// * `Err(BusinessError)` if `visibility` is not 1, 2, or 3
#[ani_rs::native]
pub fn check_group_config(env: &AniEnv, config: GroupConfig) -> Result<(), BusinessError> {
    if let Some(visibility) = config.notification.visibility {
        if visibility == 0 || (visibility & 0b11) != visibility {
            error!("notification visibility must be 1 or 2 or 3");
            return Err(BusinessError::new(
                ExceptionErrorCode::E_PARAMETER_CHECK as i32,
                "notification visibility must be 1 or 2 or 3".to_string(),
            ));
        }
    }
    Ok(())
}

/// Creates a new task group and returns its group ID.
///
/// # Returns
///
/// * `Ok(String)` containing the new group ID
/// * `Err(BusinessError)` if title/text validation or group creation fails
#[ani_rs::native]
pub fn create_group(env: &AniEnv, mut config: GroupConfig) -> Result<String, BusinessError> {
    ParseTitleText(&config.notification.title, &config.notification.text)?;
    let want_agent = config
        .notification
        .want_agent
        .as_ref()
        .map(|agent| Context::stringfy_want_agent(env, agent));
    let notification = request_core::config::Notification {
        title: config.notification.title,
        text: config.notification.text,
        disable: config.notification.disable,
        visibility: config.notification.visibility,
        want_agent,
    };
    RequestClient::get_instance()
        .create_group(config.gauge, notification)
        .map(|info| {
            info!("create_group: {:?}", info);
            info
        })
        .map_err(|e| BusinessError::new_static(e, "Failed to create group"))
}

/// Attaches a list of tasks to an existing task group.
///
/// # Returns
///
/// * `Ok(())` if the tasks were successfully attached
/// * `Err(BusinessError)` if the group ID is empty or attachment fails
#[ani_rs::native]
pub fn attach_group(gid: String, tids: Vec<String>) -> Result<(), BusinessError> {
    ParseGid(&gid)?;
    RequestClient::get_instance()
        .attach_group(gid, tids)
        .map_err(|e| BusinessError::new_static(e, "Failed to attach group"))
}

/// Deletes an existing task group.
///
/// # Returns
///
/// * `Ok(())` if the group was successfully deleted
/// * `Err(BusinessError)` if the group ID is empty or deletion fails
#[ani_rs::native]
pub fn delete_group(gid: String) -> Result<(), BusinessError> {
    ParseGid(&gid)?;
    RequestClient::get_instance()
        .delete_group(gid)
        .map_err(|e| BusinessError::new_static(e, "Failed to delete group"))
}