/*
 *    Copyright (c) 2025 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 "CodeDrivenDataModelProvider.h"
#include <app/persistence/AttributePersistenceProvider.h>
#include <app/server-cluster/ServerClusterContext.h>
#include <app/server-cluster/ServerClusterInterface.h>
#include <data-model-providers/codedriven/endpoint/EndpointInterface.h>
#include <lib/core/CHIPError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <protocols/interaction_model/StatusCode.h>

using chip::Protocols::InteractionModel::Status;

namespace chip {
namespace app {

CHIP_ERROR CodeDrivenDataModelProvider::Startup(DataModel::InteractionModelContext context)
{
    ReturnErrorOnFailure(DataModel::Provider::Startup(context));

    mInteractionModelContext.emplace(context);

    mServerClusterContext.emplace(ServerClusterContext{
        .provider           = *this,
        .storage            = mPersistentStorageDelegate,
        .attributeStorage   = mAttributePersistenceProvider,
        .interactionContext = *mInteractionModelContext,
    });

    // Start up registered server clusters if one of their associated endpoints is registered.
    bool had_failure = false;
    for (auto * cluster : mServerClusterRegistry.AllServerClusterInstances())
    {
        bool endpointRegistered = false;
        for (const auto & path : cluster->GetPaths())
        {
            if (mEndpointInterfaceRegistry.Get(path.mEndpointId) != nullptr)
            {
                endpointRegistered = true;
                break;
            }
        }

        if (endpointRegistered)
        {
            if (cluster->Startup(*mServerClusterContext) != CHIP_NO_ERROR)
            {
                had_failure = true;
            }
        }
    }

    if (had_failure)
    {
        return CHIP_ERROR_HAD_FAILURES;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR CodeDrivenDataModelProvider::Shutdown()
{
    bool had_failure = false;

    // Remove all endpoints. This will trigger Shutdown() on associated clusters.
    while (mEndpointInterfaceRegistry.begin() != mEndpointInterfaceRegistry.end())
    {
        if (RemoveEndpoint(mEndpointInterfaceRegistry.begin()->GetEndpointEntry().id) != CHIP_NO_ERROR)
        {
            had_failure = true;
        }
    }

    // Now we're safe to clean up the cluster registry.
    while (mServerClusterRegistry.AllServerClusterInstances().begin() != mServerClusterRegistry.AllServerClusterInstances().end())
    {
        ServerClusterInterface * clusterToRemove = *mServerClusterRegistry.AllServerClusterInstances().begin();
        if (mServerClusterRegistry.Unregister(clusterToRemove) != CHIP_NO_ERROR)
        {
            had_failure = true;
        }
    }

    mServerClusterContext.reset();
    mInteractionModelContext.reset();

    if (had_failure)
    {
        return CHIP_ERROR_HAD_FAILURES;
    }
    return CHIP_NO_ERROR;
}

DataModel::ActionReturnStatus CodeDrivenDataModelProvider::ReadAttribute(const DataModel::ReadAttributeRequest & request,
                                                                         AttributeValueEncoder & encoder)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(request.path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->ReadAttribute(request, encoder);
}

DataModel::ActionReturnStatus CodeDrivenDataModelProvider::WriteAttribute(const DataModel::WriteAttributeRequest & request,
                                                                          AttributeValueDecoder & decoder)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(request.path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->WriteAttribute(request, decoder);
}

void CodeDrivenDataModelProvider::ListAttributeWriteNotification(const ConcreteAttributePath & path,
                                                                 DataModel::ListWriteOperation opType)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(path);
    VerifyOrReturn(serverCluster != nullptr);
    serverCluster->ListAttributeWriteNotification(path, opType);
}

std::optional<DataModel::ActionReturnStatus> CodeDrivenDataModelProvider::InvokeCommand(const DataModel::InvokeRequest & request,
                                                                                        TLV::TLVReader & input_arguments,
                                                                                        CommandHandler * handler)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(request.path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->InvokeCommand(request, input_arguments, handler);
}

CHIP_ERROR CodeDrivenDataModelProvider::Endpoints(ReadOnlyBufferBuilder<DataModel::EndpointEntry> & out)
{
    // TODO: Add a size() method to EndpointInterfaceRegistry to avoid iterating twice.
    size_t count = 0;
    for (const auto & registration : mEndpointInterfaceRegistry)
    {
        (void) registration; // Silence unused variable warning
        count++;
    }

    ReturnErrorOnFailure(out.EnsureAppendCapacity(count));
    for (const auto & registration : mEndpointInterfaceRegistry)
    {
        ReturnErrorOnFailure(out.Append(registration.GetEndpointEntry()));
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR
CodeDrivenDataModelProvider::SemanticTags(EndpointId endpointId,
                                          ReadOnlyBufferBuilder<Clusters::Descriptor::Structs::SemanticTagStruct::Type> & out)
{
    EndpointInterface * endpoint = GetEndpointInterface(endpointId);
    VerifyOrReturnError(endpoint != nullptr, CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint));
    return endpoint->SemanticTags(out);
}

CHIP_ERROR CodeDrivenDataModelProvider::DeviceTypes(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::DeviceTypeEntry> & out)
{
    EndpointInterface * endpoint = GetEndpointInterface(endpointId);
    VerifyOrReturnError(endpoint != nullptr, CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint));
    return endpoint->DeviceTypes(out);
}

CHIP_ERROR CodeDrivenDataModelProvider::ClientClusters(EndpointId endpointId, ReadOnlyBufferBuilder<ClusterId> & out)
{
    EndpointInterface * endpoint = GetEndpointInterface(endpointId);
    VerifyOrReturnError(endpoint != nullptr, CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint));
    return endpoint->ClientClusters(out);
}

CHIP_ERROR CodeDrivenDataModelProvider::ServerClusters(EndpointId endpointId,
                                                       ReadOnlyBufferBuilder<DataModel::ServerClusterEntry> & out)
{
    EndpointInterface * endpoint = GetEndpointInterface(endpointId);
    VerifyOrReturnError(endpoint != nullptr, CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint));

    size_t count = 0;
    for (auto * cluster : mServerClusterRegistry.AllServerClusterInstances())
    {
        for (const auto & path : cluster->GetPaths())
        {
            if (path.mEndpointId == endpointId)
            {
                count++;
            }
        }
    }

    ReturnErrorOnFailure(out.EnsureAppendCapacity(count));

    for (auto * cluster : mServerClusterRegistry.AllServerClusterInstances())
    {
        for (const auto & path : cluster->GetPaths())
        {
            if (path.mEndpointId == endpointId)
            {
                ReturnErrorOnFailure(
                    out.Append({ path.mClusterId, cluster->GetDataVersion(path), cluster->GetClusterFlags(path) }));
            }
        }
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR CodeDrivenDataModelProvider::GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<CommandId> & out)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->GeneratedCommands(path, out);
}
CHIP_ERROR CodeDrivenDataModelProvider::AcceptedCommands(const ConcreteClusterPath & path,
                                                         ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> & out)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->AcceptedCommands(path, out);
}

CHIP_ERROR CodeDrivenDataModelProvider::Attributes(const ConcreteClusterPath & path,
                                                   ReadOnlyBufferBuilder<DataModel::AttributeEntry> & out)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->Attributes(path, out);
}

CHIP_ERROR CodeDrivenDataModelProvider::EventInfo(const ConcreteEventPath & path, DataModel::EventEntry & eventInfo)
{
    ServerClusterInterface * serverCluster = GetServerClusterInterface(path);
    VerifyOrReturnError(serverCluster != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
    return serverCluster->EventInfo(path, eventInfo);
}

void CodeDrivenDataModelProvider::Temporary_ReportAttributeChanged(const AttributePathParams & path)
{
    if (!mInteractionModelContext)
    {
        ChipLogError(DataManagement, "Temporary_ReportAttributeChanged called before provider has been started.");
        return;
    }
    mInteractionModelContext->dataModelChangeListener.MarkDirty(path);
}

CHIP_ERROR CodeDrivenDataModelProvider::AddEndpoint(EndpointInterfaceRegistration & registration)
{
    VerifyOrReturnError(registration.endpointEntry.id != kInvalidEndpointId, CHIP_ERROR_INVALID_ARGUMENT);

    // If the endpoint ID is already in use, return an error.
    if (mEndpointInterfaceRegistry.Get(registration.endpointEntry.id) != nullptr)
    {
        return CHIP_ERROR_DUPLICATE_KEY_ID;
    }

    ReturnErrorOnFailure(mEndpointInterfaceRegistry.Register(registration));

    if (mServerClusterContext.has_value())
    {
        // If the provider has been started, we need to check if any clusters on this new endpoint
        // should be started up.
        for (auto * cluster : mServerClusterRegistry.AllServerClusterInstances())
        {
            bool clusterIsOnNewEndpoint = false;
            int registeredEndpointCount = 0;

            for (const auto & path : cluster->GetPaths())
            {
                if (mEndpointInterfaceRegistry.Get(path.mEndpointId) != nullptr)
                {
                    registeredEndpointCount++;
                }
                if (path.mEndpointId == registration.endpointEntry.id)
                {
                    clusterIsOnNewEndpoint = true;
                }
            }

            // If the cluster is on the endpoint we just added, and this is the *only*
            // registered endpoint for this cluster, it's time to start it.
            if (clusterIsOnNewEndpoint && registeredEndpointCount == 1)
            {
                ReturnErrorOnFailure(cluster->Startup(*mServerClusterContext));
            }
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR CodeDrivenDataModelProvider::RemoveEndpoint(EndpointId endpointId)
{
    if (mServerClusterContext.has_value())
    {
        // If the provider has been started, we need to check if any clusters on this endpoint
        // need to be shut down because it's their last registered endpoint.
        for (auto * cluster : mServerClusterRegistry.AllServerClusterInstances())
        {
            bool clusterIsOnEndpoint    = false;
            int registeredEndpointCount = 0;

            for (const auto & path : cluster->GetPaths())
            {
                if (mEndpointInterfaceRegistry.Get(path.mEndpointId) != nullptr)
                {
                    registeredEndpointCount++;
                }
                if (path.mEndpointId == endpointId)
                {
                    clusterIsOnEndpoint = true;
                }
            }

            if (clusterIsOnEndpoint && registeredEndpointCount == 1)
            {
                // This is the last registered endpoint for this cluster. Shut it down.
                cluster->Shutdown();
            }
        }
    }

    return mEndpointInterfaceRegistry.Unregister(endpointId);
}

CHIP_ERROR CodeDrivenDataModelProvider::AddCluster(ServerClusterRegistration & entry)
{
    VerifyOrReturnError(entry.serverClusterInterface != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    if (mServerClusterContext.has_value())
    {
        // If the provider has been started, prevent non-atomic changes to an endpoint.
        // Check if any of the cluster's paths are associated with an already registered endpoint.
        for (const auto & path : entry.serverClusterInterface->GetPaths())
        {
            if (mEndpointInterfaceRegistry.Get(path.mEndpointId) != nullptr)
            {
                return CHIP_ERROR_INCORRECT_STATE;
            }
        }
    }

    return mServerClusterRegistry.Register(entry);
}

CHIP_ERROR CodeDrivenDataModelProvider::RemoveCluster(ServerClusterInterface * cluster)
{
    VerifyOrReturnError(cluster != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    if (mServerClusterContext.has_value())
    {
        for (const auto & path : cluster->GetPaths())
        {
            if (mEndpointInterfaceRegistry.Get(path.mEndpointId) != nullptr)
            {
                return CHIP_ERROR_INCORRECT_STATE;
            }
        }
    }

    return mServerClusterRegistry.Unregister(cluster);
}

EndpointInterface * CodeDrivenDataModelProvider::GetEndpointInterface(EndpointId endpointId)
{
    return mEndpointInterfaceRegistry.Get(endpointId);
}

ServerClusterInterface * CodeDrivenDataModelProvider::GetServerClusterInterface(const ConcreteClusterPath & clusterPath)
{
    return mServerClusterRegistry.Get(clusterPath);
}

} // namespace app
} // namespace chip
