/*
 * 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.
 */

#include "media_datashare_client.h"

#include "media_uri_utils.h"
#include "medialibrary_napi_log.h"
#include "medialibrary_errno.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
#include "bundle_mgr_interface.h"
#include <unistd.h>

namespace OHOS::Media::IPC {
MediaDataShareClient::MediaDataShareClient() {}
MediaDataShareClient::~MediaDataShareClient() {}

sptr<AppExecFwk::IBundleMgr> MediaDataShareClient::bundleMgr_ = nullptr;
std::mutex MediaDataShareClient::bundleMgrMutex_;
// LCOV_EXCL_START

std::shared_ptr<DataShare::DataShareResultSet> MediaDataShareClient::Query(Uri &uri,
    const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns, int &errCode,
    const int32_t userId)
{
    OperationObject object = OperationObject::UNKNOWN_OBJECT;
    if (IsNoIpc(uri, object, predicates) && userId == -1) {
        return QueryWithoutIpc(predicates, columns, object, errCode);
    }
    uri = MediaUriUtils::GetMultiUri(uri, userId);
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("Query fail, helper null, userId is %{public}d", userId);
        return nullptr;
    }
    DataShare::DatashareBusinessError businessError;
    auto resultSet = helper->Query(uri, predicates, columns, &businessError);
    errCode = businessError.GetCode();
    return resultSet;
}

int MediaDataShareClient::Insert(Uri &uri, const DataShare::DataShareValuesBucket &value, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("insert fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->Insert(uri, value);
}

int MediaDataShareClient::InsertExt(Uri &uri, const DataShare::DataShareValuesBucket &value, std::string &result,
    const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("insert ext fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->InsertExt(uri, value, result);
}

int MediaDataShareClient::BatchInsert(Uri &uri, const std::vector<DataShare::DataShareValuesBucket> &values,
    const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("Batch insert fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->BatchInsert(uri, values);
}

int MediaDataShareClient::Delete(Uri &uri, const DataShare::DataSharePredicates &predicates, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("delete fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->Delete(uri, predicates);
}

void MediaDataShareClient::NotifyChange(const Uri &uri, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("notify change fail, helper null, userId is %{public}d", userId);
        return;
    }
    helper->NotifyChange(uri);
}

void MediaDataShareClient::RegisterObserver(const Uri &uri,
    const sptr<AAFwk::IDataAbilityObserver> &dataObserver, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("register observer fail, helper null, userId is %{public}d", userId);
        return;
    }
    helper->RegisterObserver(uri, dataObserver);
}

void MediaDataShareClient::UnregisterObserver(const Uri &uri,
    const sptr<AAFwk::IDataAbilityObserver> &dataObserver, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("unregister observer fail, helper null, userId is %{public}d", userId);
        return;
    }
    helper->UnregisterObserver(uri, dataObserver);
}

int MediaDataShareClient::OpenFile(Uri &uri, const std::string &mode, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("Open file fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    uri = MediaUriUtils::GetMultiUri(uri, userId);

    return helper->OpenFile(uri, mode);
}

int MediaDataShareClient::Update(Uri &uri, const DataShare::DataSharePredicates &predicates,
    const DataShare::DataShareValuesBucket &value, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("update fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->Update(uri, predicates, value);
}

void MediaDataShareClient::RegisterObserverExt(const Uri &uri,
    std::shared_ptr<DataShare::DataShareObserver> dataObserver, bool isDescendants, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("register observer fail, helper null, userId is %{public}d", userId);
        return;
    }
    helper->RegisterObserverExt(uri, std::move(dataObserver), isDescendants);
}

void MediaDataShareClient::UnregisterObserverExt(const Uri &uri,
    std::shared_ptr<DataShare::DataShareObserver> dataObserver, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("unregister observer fail, helper null, userId is %{public}d", userId);
        return;
    }
    helper->UnregisterObserverExt(uri, std::move(dataObserver));
}

std::string MediaDataShareClient::GetType(Uri &uri, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("get type fail, helper null, userId is %{public}d", userId);
        return "";
    }
    return helper->GetType(uri);
}

int32_t MediaDataShareClient::RegisterObserverExtProvider(const Uri &uri,
    std::shared_ptr<DataShare::DataShareObserver> dataObserver, bool isDescendants, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("register observer fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->RegisterObserverExtProvider(uri, std::move(dataObserver), isDescendants);
}

int32_t MediaDataShareClient::UnregisterObserverExtProvider(const Uri &uri,
    std::shared_ptr<DataShare::DataShareObserver> dataObserver, const int32_t userId)
{
    auto helper = GetDataShareHelperByUser(userId);
    if (helper == nullptr) {
        NAPI_ERR_LOG("unregister observer fail, helper null, userId is %{public}d", userId);
        return E_FAIL;
    }
    return helper->UnregisterObserverExtProvider(uri, std::move(dataObserver));
}

std::shared_ptr<DataShare::DataShareResultSet> MediaDataShareClient::QueryWithoutIpc(
    const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns, OperationObject &object,
    int &errCode)
{
    return nullptr;
}

bool MediaDataShareClient::IsNoIpc(Uri &uri, OperationObject &object, const DataShare::DataSharePredicates &predicates,
    bool isIgnoreSELinux)
{
    return false;
}

std::string MediaDataShareClient::GetBundleName()
{
    std::lock_guard<std::mutex> lock(bundleMgrMutex_);
    auto bundleMgr = GetSysBundleManager();
    if (bundleMgr == nullptr) {
        NAPI_ERR_LOG("GetBundleName: bundleMgr is null");
        return "";
    }
    std::string bundleName;
    bool result = bundleMgr->GetBundleNameForUid(getuid(), bundleName);
    if (!result) {
        NAPI_ERR_LOG("GetBundleName: failed to get bundle name");
        return "";
    }
    return bundleName;
}

sptr<AppExecFwk::IBundleMgr> MediaDataShareClient::GetSysBundleManager()
{
    if (bundleMgr_ != nullptr) {
        return bundleMgr_;
    }
    auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (saManager == nullptr) {
        NAPI_ERR_LOG("GetSysBundleManager: get system ability mgr failed.");
        return nullptr;
    }
    bundleMgr_ = iface_cast<AppExecFwk::IBundleMgr>(
        saManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID));
    if (bundleMgr_ == nullptr) {
        NAPI_ERR_LOG("GetSysBundleManager: GetSystemAbility failed.");
    }
    return bundleMgr_;
}
// LCOV_EXCL_STOP
}