/*
 * Copyright (c) 2026 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.
 */

#define private   public
#define protected public
#include "notify_service_impl.h"
#undef private

#include <gtest/gtest.h>

#include "global.h"
#include "ipc_skeleton.h"
#include "os_account_adapter.h"
#include "peruser_session.h"
#include "user_session_manager.h"

using namespace testing::ext;
namespace OHOS {
namespace MiscServices {

class NotifyServiceImplTest : public testing::Test {
public:
    static void SetUpTestCase(void) { }
    static void TearDownTestCase(void) { }
    void SetUp() { }
    void TearDown() { }
};

// NotifyOnInputStopFinished - pid mismatch returns permission denied
HWTEST_F(NotifyServiceImplTest, NotifyOnInputStopFinished_PidMismatch, TestSize.Level0)
{
    IMSA_HILOGI("NotifyOnInputStopFinished_PidMismatch begin");
    // Construct with a PID that is different from IPCSkeleton::GetCallingPid()
    // IPCSkeleton::GetCallingPid() in test returns the actual process PID (getpid())
    // We set the service's pid_ to a different value
    OnInputStopNotifyServiceImpl service(-1); // pid_ = -1, which != GetCallingPid()
    auto ret = service.NotifyOnInputStopFinished();
    EXPECT_EQ(ret, ErrorCode::ERROR_STATUS_PERMISSION_DENIED);
}

// NotifyOnInputStopFinished - userId invalid (OsAccountAdapter returns INVALID_USER_ID)
HWTEST_F(NotifyServiceImplTest, NotifyOnInputStopFinished_InvalidUserId, TestSize.Level0)
{
    IMSA_HILOGI("NotifyOnInputStopFinished_InvalidUserId begin");
    // IPCSkeleton::GetCallingPid() returns the current process PID
    pid_t currentPid = getpid();
    OnInputStopNotifyServiceImpl service(currentPid);
    // In unit test environment, OsAccountAdapter may return a valid userId,
    // so the method proceeds past the userId check and fails at session-not-found.
    // If it returns INVALID_USER_ID, ERROR_EX_ILLEGAL_STATE is returned.
    auto ret = service.NotifyOnInputStopFinished();
    EXPECT_TRUE(ret == ErrorCode::ERROR_EX_ILLEGAL_STATE || ret == ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND);
}

// NotifyOnInputStopFinished - session is nullptr
// This requires a valid userId and a valid pid, but no session registered for that user.
// Since OsAccountAdapter mock returns INVALID_USER_ID, we need the userId to be valid.
// The only way to get a valid userId in the mock is if GetOsAccountLocalIdFromUid
// returns a non-INVALID_USER_ID value. The mock always returns INVALID_USER_ID,
// so this branch can only be tested when the userId path passes (requires real OsAccountAdapter).
// However, we can still set up a scenario by inserting a session for a specific user
// and verifying the session-not-found path.
HWTEST_F(NotifyServiceImplTest, NotifyOnInputStopFinished_SessionNotFound, TestSize.Level0)
{
    IMSA_HILOGI("NotifyOnInputStopFinished_SessionNotFound begin");
    // With current mock (GetOsAccountLocalIdFromUid returning INVALID_USER_ID),
    // the userId check fails before reaching the session check.
    // This test verifies the combined behavior:
    pid_t currentPid = getpid();
    OnInputStopNotifyServiceImpl service(currentPid);
    auto ret = service.NotifyOnInputStopFinished();
    // Will fail at userId check since mock returns INVALID_USER_ID
    EXPECT_TRUE(ret == ErrorCode::ERROR_EX_ILLEGAL_STATE || ret == ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND);
}

// NotifyOnInputStopFinished - normal path
// This test requires: 1) pid matches, 2) userId is valid, 3) session exists.
// With the current mock setup (GetOsAccountLocalIdFromUid returns INVALID_USER_ID),
// we cannot exercise the full normal path. We verify the method doesn't crash.
HWTEST_F(NotifyServiceImplTest, NotifyOnInputStopFinished_Normal, TestSize.Level0)
{
    IMSA_HILOGI("NotifyOnInputStopFinished_Normal begin");
    pid_t currentPid = getpid();
    OnInputStopNotifyServiceImpl service(currentPid);
    auto ret = service.NotifyOnInputStopFinished();
    // In the unit test environment, there is no active session, so it returns
    // ERROR_IMSA_USER_SESSION_NOT_FOUND. In a real integration test with a valid
    // session, this would return ERR_OK.
    EXPECT_TRUE(ret == ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND || ret == ERR_OK);
}
} // namespace MiscServices
} // namespace OHOS