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

#include <credentials/FabricTable.h>
#include <credentials/GroupDataProvider.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/NodeId.h>
#include <lib/core/Optional.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/TypeTraits.h>

namespace {

using namespace chip;

using chip::Access::AccessControl;
using chip::Access::AuthMode;
using chip::Access::AuxiliaryType;
using chip::Access::Privilege;
using chip::Access::RequestPath;
using chip::Access::SubjectDescriptor;

using Entry         = chip::Access::AccessControl::Entry;
using EntryIterator = chip::Access::AccessControl::EntryIterator;
using Target        = Entry::Target;

class EntryDelegate : public AccessControl::Entry::Delegate
{
public:
    void Init(Entry & entry, FabricIndex fabricIndex, GroupId groupId, EndpointId endpointId)
    {
        mFabricIndex = fabricIndex;
        mGroupId     = groupId;
        mEndpointId  = endpointId;
        entry.SetDelegate(*this);
    }

    void Release() override { Platform::Delete(this); }

    CHIP_ERROR GetAuthMode(AuthMode & authMode) const override
    {
        authMode = AuthMode::kGroup;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetFabricIndex(FabricIndex & fabricIndex) const override
    {
        fabricIndex = mFabricIndex;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetPrivilege(Privilege & privilege) const override
    {
        privilege = Privilege::kOperate;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetAuxiliaryType(AuxiliaryType & auxiliaryType) const override
    {
        auxiliaryType = AuxiliaryType::kGroupcast;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSubjectCount(size_t & count) const override
    {
        count = 1;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetSubject(size_t index, NodeId & subject) const override
    {
        if (index == 0)
        {
            subject = NodeIdFromGroupId(mGroupId);
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

    CHIP_ERROR GetTargetCount(size_t & count) const override
    {
        count = 1;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR GetTarget(size_t index, Target & target) const override
    {
        if (index == 0)
        {
            target.flags    = Target::kEndpoint;
            target.endpoint = mEndpointId;
            return CHIP_NO_ERROR;
        }
        return CHIP_ERROR_SENTINEL;
    }

private:
    FabricIndex mFabricIndex;
    GroupId mGroupId;
    EndpointId mEndpointId;
};

class AuxiliaryEntryIteratorDelegate : public EntryIterator::Delegate
{
public:
    void Init(EntryIterator & iterator, Credentials::GroupDataProvider * groupDataProvider, FabricTable * fabricTable,
              FabricIndex fabricIndex)
    {
        mGroupDataProvider = groupDataProvider;
        mFabricTable       = fabricTable;
        mFabricIndex       = fabricIndex;

        if (mFabricIndex == kUndefinedFabricIndex)
        {
            mIterateOverFabricIndices = true;
            // If the fabric table is defined, it can be used to find and iterate over all
            // valid existing fabric indices. Otherwise, iteration can be done starting from
            // the minimum fabric index and going up
            if (mFabricTable)
            {
                mFabricTableIter.SetValue(mFabricTable->begin());
                if (mFabricTableIter.Value() != mFabricTable->end())
                {
                    mFabricIndex = mFabricTableIter.Value()->GetFabricIndex();
                }
            }
            else
            {
                mFabricIndex = kMinValidFabricIndex;
            }
        }

        if (mGroupDataProvider)
        {
            mGroupInfoIterator = mGroupDataProvider->IterateGroupInfo(mFabricIndex);
        }
        iterator.SetDelegate(*this);
    }

    ~AuxiliaryEntryIteratorDelegate() override
    {
        if (mGroupInfoIterator)
        {
            mGroupInfoIterator->Release();
        }
        if (mEndpointIterator)
        {
            mEndpointIterator->Release();
        }
    }

    void Release() override { Platform::Delete(this); }

    CHIP_ERROR Next(Entry & entry) override
    {
        if (mGroupDataProvider == nullptr)
        {
            return CHIP_ERROR_SENTINEL;
        }

        while (mGroupInfoIterator != nullptr || mEndpointIterator != nullptr || mIterateOverFabricIndices)
        {
            if (mEndpointIterator != nullptr)
            {
                Credentials::GroupDataProvider::GroupEndpoint endpoint;
                if (mEndpointIterator->Next(endpoint))
                {
                    // Groups cannot be created with endpoint 0, so this state should never be reached
                    // because of restrictions with creating/joining groups. We skip here in the case
                    // this does occur, no entry would be needed to validate against for endpoint 0.
                    if (endpoint.endpoint_id == kRootEndpointId)
                    {
                        continue;
                    }

                    auto * delegate = Platform::New<EntryDelegate>();
                    if (delegate == nullptr)
                    {
                        return CHIP_ERROR_NO_MEMORY;
                    }
                    delegate->Init(entry, mFabricIndex, mGroupId, endpoint.endpoint_id);
                    return CHIP_NO_ERROR;
                }
                mEndpointIterator->Release();
                mEndpointIterator = nullptr;
            }

            if (mGroupInfoIterator != nullptr)
            {
                Credentials::GroupDataProvider::GroupInfo info;
                if (mGroupInfoIterator->Next(info))
                {
                    if (info.flags & to_underlying(Credentials::GroupDataProvider::GroupInfo::Flags::kHasAuxiliaryACL))
                    {
                        mGroupId          = info.group_id;
                        mEndpointIterator = mGroupDataProvider->IterateEndpoints(mFabricIndex, mGroupId);
                    }
                    continue;
                }
                mGroupInfoIterator->Release();
                mGroupInfoIterator = nullptr;
            }

            if (mIterateOverFabricIndices)
            {
                // This indicates that there are no more fabric indices to iterate over (unless it is
                // determined in the conditions below that at least 1 more is remaining, in which
                // case this will be set to true again).
                mIterateOverFabricIndices = false;

                if (mFabricTable && mFabricTableIter.HasValue())
                {
                    if ((mFabricTableIter.Value() != mFabricTable->end()) && (++mFabricTableIter.Value() != mFabricTable->end()))
                    {
                        mFabricIndex              = mFabricTableIter.Value()->GetFabricIndex();
                        mGroupInfoIterator        = mGroupDataProvider->IterateGroupInfo(mFabricIndex);
                        mIterateOverFabricIndices = true;
                    }
                }
                else if (mFabricIndex < kMaxValidFabricIndex)
                {
                    mFabricIndex++;
                    mGroupInfoIterator        = mGroupDataProvider->IterateGroupInfo(mFabricIndex);
                    mIterateOverFabricIndices = true;
                }
            }
        }

        return CHIP_ERROR_SENTINEL;
    }

private:
    Credentials::GroupDataProvider * mGroupDataProvider;
    FabricTable * mFabricTable;
    FabricIndex mFabricIndex;
    chip::Optional<chip::ConstFabricIterator> mFabricTableIter;
    Credentials::GroupDataProvider::GroupInfoIterator * mGroupInfoIterator = nullptr;
    Credentials::GroupDataProvider::EndpointIterator * mEndpointIterator   = nullptr;
    GroupId mGroupId                                                       = kUndefinedGroupId;

    // When true, this indicates the entries are not fabric scoped. AuxiliaryEntries() through
    // the Next() function will iterate over all fabrics to fetch auxiliary ACL entries. This
    // will be set to true when a fabric index is not specified (kUndefinedFabricIndex).
    bool mIterateOverFabricIndices = false;
};

} // namespace

namespace chip {
namespace Access {
namespace Examples {

CHIP_ERROR GroupAuxiliaryAccessControlDelegateImpl::Initialize(Credentials::GroupDataProvider * groupDataProvider,
                                                               FabricTable * fabricTable)
{
    VerifyOrReturnError(groupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(mGroupDataProvider == nullptr, CHIP_ERROR_INCORRECT_STATE);
    mGroupDataProvider = groupDataProvider;
    mFabricTable       = fabricTable;
    return CHIP_NO_ERROR;
}

void GroupAuxiliaryAccessControlDelegateImpl::Shutdown()
{
    mGroupDataProvider = nullptr;
    mFabricTable       = nullptr;
}

/*
 * This function (in conjunction with Next() from the AuxiliaryEntryIteratorDelegate) will create an auxiliary
 * ACL entry for every <fabric index, group ID, endpoint ID> that belongs based on the information from
 * the group data provider. This is the simplest base case of what a set of auxiliary ACL entries will look
 * like. The structure of auxiliary ACL entries can be formatted differently, as long as the equivalence class
 * maps to this simplest base case.
 */
CHIP_ERROR GroupAuxiliaryAccessControlDelegateImpl::AuxiliaryEntries(AccessControl::EntryIterator & iterator,
                                                                     const FabricIndex * fabricIndex) const
{
    VerifyOrReturnError(mGroupDataProvider != nullptr, CHIP_ERROR_INCORRECT_STATE);
    auto * delegate = Platform::New<AuxiliaryEntryIteratorDelegate>();
    if (delegate)
    {
        delegate->Init(iterator, mGroupDataProvider, mFabricTable, fabricIndex ? *fabricIndex : kUndefinedFabricIndex);
        return CHIP_NO_ERROR;
    }
    return CHIP_ERROR_NO_MEMORY;
}

CHIP_ERROR GroupAuxiliaryAccessControlDelegateImpl::Check(const SubjectDescriptor & subjectDescriptor,
                                                          const RequestPath & requestPath, Privilege requestPrivilege)
{
    if (IsGroupId(subjectDescriptor.subject) && (mGroupDataProvider != nullptr))
    {
        GroupId groupId = GroupIdFromNodeId(subjectDescriptor.subject);
        if ((requestPath.endpoint != kRootEndpointId) &&
            (mGroupDataProvider->HasEndpoint(subjectDescriptor.fabricIndex, groupId, requestPath.endpoint)) &&
            (requestPath.requestType == Access::RequestType::kCommandInvokeRequest) && (requestPrivilege == Privilege::kOperate) &&
            (subjectDescriptor.authMode == Access::AuthMode::kGroup))
        {
            ChipLogProgress(SecureChannel, "AccessControl: Approved (from Auxiliary ACL)");
            return CHIP_NO_ERROR;
        }
    }

    ChipLogProgress(DataManagement, "AccessControl: Denied (from Auxiliary ACL)");
    return CHIP_ERROR_ACCESS_DENIED;
}

} // namespace Examples
} // namespace Access
} // namespace chip
