/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 <lib/core/StringBuilderAdapters.h>
#include <pw_unit_test/framework.h>

#include <access/examples/PermissiveAccessControlDelegate.h>
#include <app/ConcreteAttributePath.h>
#include <app/ConcreteEventPath.h>
#include <app/InteractionModelEngine.h>
#include <app/MessageDef/AttributeReportIBs.h>
#include <app/MessageDef/EventDataIB.h>
#include <app/reporting/tests/MockReportScheduler.h>
#include <app/tests/AppTestContext.h>
#include <app/tests/test-interaction-model-api.h>
#include <app/util/basic-types.h>
#include <app/util/mock/Constants.h>
#include <app/util/mock/Functions.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/ErrorStr.h>
#include <lib/core/TLV.h>
#include <lib/core/TLVDebug.h>
#include <lib/core/TLVUtilities.h>
#include <lib/support/CHIPCounter.h>
#include <lib/support/tests/ExtraPwTestMacros.h>
#include <messaging/ExchangeContext.h>
#include <messaging/Flags.h>
#include <protocols/interaction_model/Constants.h>

namespace {
using namespace chip;
using namespace chip::Access;
using namespace chip::Testing;

constexpr CommandId kTestUnsupportedCommandId = 77;
constexpr CommandId kTestCommandId            = 4;

const MockNodeConfig & TestMockNodeConfig()
{
    using namespace chip::app;
    using namespace chip::app::Clusters::Globals::Attributes;
    // clang-format off
    static const MockNodeConfig config({
        MockEndpointConfig(kTestEndpointId, {
            MockClusterConfig(kTestClusterId, {
                ClusterRevision::Id, FeatureMap::Id, 1, 2
            }),
        }),
        MockEndpointConfig(kTestDeniedEndpointId, {
            MockClusterConfig(kTestClusterId, {
                ClusterRevision::Id, FeatureMap::Id, 1, 2
            }),
        }),
    });
    // clang-format on
    return config;
}

class TestAccessControlDelegate : public AccessControl::Delegate
{
public:
    CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const chip::Access::RequestPath & requestPath,
                     Privilege requestPrivilege) override
    {
        if (requestPath.cluster == kTestDeniedClusterId2 || requestPath.endpoint == kTestDeniedEndpointId)
        {
            return CHIP_ERROR_ACCESS_DENIED;
        }
        return CHIP_NO_ERROR;
    }
};

AccessControl::Delegate * GetTestAccessControlDelegate()
{
    static TestAccessControlDelegate accessControlDelegate;
    return &accessControlDelegate;
}

class TestDeviceTypeResolver : public AccessControl::DeviceTypeResolver
{
public:
    bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint) override { return false; }
} gDeviceTypeResolver;

class MockCommandSenderCallback : public app::CommandSender::Callback
{
public:
    void OnError(const app::CommandSender * apCommandSender, CHIP_ERROR aError) override
    {
        ChipLogError(Controller, "OnError happens with %" CHIP_ERROR_FORMAT, aError.Format());
        mError = aError;
        onErrorCalledTimes++;
        mError = aError;
    }
    void OnDone(app::CommandSender * apCommandSender) override { onFinalCalledTimes++; }

    void ResetCounter()
    {
        onErrorCalledTimes = 0;
        onFinalCalledTimes = 0;
    }

    int onErrorCalledTimes = 0;
    int onFinalCalledTimes = 0;
    CHIP_ERROR mError      = CHIP_NO_ERROR;
} mockCommandSenderDelegate;

} // namespace

namespace chip {
namespace app {

class TestAclCommand : public AppContext
{
public:
    void SetUp() override
    {
        AppContext::SetUp();

        Access::GetAccessControl().Finish();
        EXPECT_SUCCESS(Access::GetAccessControl().Init(GetTestAccessControlDelegate(), gDeviceTypeResolver));
        mOldProvider = InteractionModelEngine::GetInstance()->SetDataModelProvider(&TestImCustomDataModel::Instance());
        SetMockNodeConfig(TestMockNodeConfig());
    }

    void TearDown() override
    {
        ResetMockNodeConfig();
        AppContext::TearDown();
        InteractionModelEngine::GetInstance()->SetDataModelProvider(mOldProvider);
    }

    static void AddInvokeRequestData(CommandSender * apCommandSender, CommandPathParams aCommandPathParams);

private:
    chip::app::DataModel::Provider * mOldProvider = nullptr;
};

void TestAclCommand::AddInvokeRequestData(CommandSender * apCommandSender, CommandPathParams aCommandPathParams)
{

    EXPECT_EQ(apCommandSender->PrepareCommand(aCommandPathParams), CHIP_NO_ERROR);

    chip::TLV::TLVWriter * writer = apCommandSender->GetCommandDataIBTLVWriter();

    EXPECT_EQ(writer->PutBoolean(chip::TLV::ContextTag(1), true), CHIP_NO_ERROR);
    EXPECT_EQ(apCommandSender->FinishCommand(), CHIP_NO_ERROR);
}

// If an endpoint isn't supported, but access to the request path is denied, we should receive UnsupportedAccess rather than
// UnsupportedEndpoint to prevent information leakage
TEST_F(TestAclCommand, AccessDeniedPrecedenceOverUnsupportedEndpoint)
{

    {
        mockCommandSenderDelegate.ResetCounter();
        app::CommandSender commandSender(&mockCommandSenderDelegate, &GetExchangeManager());

        auto commandPathParams = CommandPathParams(kTestUnsupportedEndpointId, 0, kTestDeniedClusterId2, kTestCommandId,
                                                   (chip::app::CommandPathFlags::kEndpointIdValid));
        AddInvokeRequestData(&commandSender, commandPathParams);
        EXPECT_EQ(commandSender.SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR);
        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 0u);

        DrainAndServiceIO();

        EXPECT_EQ(mockCommandSenderDelegate.mError, CHIP_IM_GLOBAL_STATUS(UnsupportedAccess));

        EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 1);
        EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 1);

        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 1u);
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    {
        mockCommandSenderDelegate.ResetCounter();
        app::CommandSender commandSender(&mockCommandSenderDelegate, &GetExchangeManager());

        auto commandPathParams = CommandPathParams(kTestUnsupportedEndpointId, 0, kTestClusterId, kTestCommandId,
                                                   (chip::app::CommandPathFlags::kEndpointIdValid));
        AddInvokeRequestData(&commandSender, commandPathParams);
        EXPECT_EQ(commandSender.SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR);
        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 0u);

        DrainAndServiceIO();

        EXPECT_EQ(mockCommandSenderDelegate.mError, CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint));

        EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 1);
        EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 1);

        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 1u);
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }
}

// If a Cluster isn't supported, but access to the request path is denied, we should receive UnsupportedAccess rather than
// UnsupportedCluster to prevent information leakage
TEST_F(TestAclCommand, AccessDeniedPrecedenceOverUnsupportedCluster)
{

    {
        mockCommandSenderDelegate.ResetCounter();
        app::CommandSender commandSender(&mockCommandSenderDelegate, &GetExchangeManager());

        auto commandPathParams = CommandPathParams(kTestDeniedEndpointId, 0, kTestUnsupportedClusterId, kTestCommandId,
                                                   (chip::app::CommandPathFlags::kEndpointIdValid));
        AddInvokeRequestData(&commandSender, commandPathParams);
        EXPECT_EQ(commandSender.SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR);
        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 0u);

        DrainAndServiceIO();

        EXPECT_EQ(mockCommandSenderDelegate.mError, CHIP_IM_GLOBAL_STATUS(UnsupportedAccess));

        EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 1);
        EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 1);

        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 1u);
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    {
        mockCommandSenderDelegate.ResetCounter();
        app::CommandSender commandSender(&mockCommandSenderDelegate, &GetExchangeManager());

        auto commandPathParams = CommandPathParams(kTestEndpointId, 0, kTestUnsupportedClusterId, kTestCommandId,
                                                   (chip::app::CommandPathFlags::kEndpointIdValid));
        AddInvokeRequestData(&commandSender, commandPathParams);
        EXPECT_EQ(commandSender.SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR);
        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 0u);

        DrainAndServiceIO();

        EXPECT_EQ(mockCommandSenderDelegate.mError, CHIP_IM_GLOBAL_STATUS(UnsupportedCluster));

        EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 1);
        EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 1);

        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 1u);
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }
}
// If a Command isn't supported, but access to the request path is denied, we should receive UnsupportedAccess rather than
// UnsupportedCommand to prevent information leakage
TEST_F(TestAclCommand, AccessDeniedPrecedenceOverUnsupportedCommand)
{

    {
        mockCommandSenderDelegate.ResetCounter();
        app::CommandSender commandSender(&mockCommandSenderDelegate, &GetExchangeManager());

        auto commandPathParams = CommandPathParams(kTestDeniedEndpointId, 0, kTestClusterId, kTestUnsupportedCommandId,
                                                   (chip::app::CommandPathFlags::kEndpointIdValid));
        AddInvokeRequestData(&commandSender, commandPathParams);
        EXPECT_EQ(commandSender.SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR);
        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 0u);

        DrainAndServiceIO();

        EXPECT_EQ(mockCommandSenderDelegate.mError, CHIP_IM_GLOBAL_STATUS(UnsupportedAccess));

        EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 1);
        EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 1);

        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 1u);
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }

    {
        mockCommandSenderDelegate.ResetCounter();
        app::CommandSender commandSender(&mockCommandSenderDelegate, &GetExchangeManager());

        auto commandPathParams = CommandPathParams(kTestEndpointId, 0, kTestClusterId, kTestUnsupportedCommandId,
                                                   (chip::app::CommandPathFlags::kEndpointIdValid));
        AddInvokeRequestData(&commandSender, commandPathParams);
        EXPECT_EQ(commandSender.SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR);
        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 0u);

        DrainAndServiceIO();

        EXPECT_EQ(mockCommandSenderDelegate.mError, CHIP_IM_GLOBAL_STATUS(UnsupportedCommand));

        EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 1);
        EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 1);

        EXPECT_EQ(commandSender.GetInvokeResponseMessageCount(), 1u);
        EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
    }
}

} // namespace app
} // namespace chip
