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

#pragma once

#include <app/CommandHandlerExchangeInterface.h>
#include <app/CommandHandlerImpl.h>
#include <app/StatusResponse.h>
#include <messaging/ExchangeHolder.h>
#include <system/SystemPacketBuffer.h>

namespace chip {
namespace app {

// TODO(#30453): Rename CommandResponseSender to CommandResponder in follow up PR
/**
 * Manages the process of sending InvokeResponseMessage(s) to the requester.
 *
 * Implements the CommandHandlerExchangeInterface. Uses a CommandHandler member to process
 * InvokeCommandRequest. The CommandHandler is provided a reference to this
 * CommandHandlerExchangeInterface implementation to enable sending InvokeResponseMessage(s).
 */
class CommandResponseSender : public Messaging::ExchangeDelegate,
                              public CommandHandlerImpl::Callback,
                              public CommandHandlerExchangeInterface
{
public:
    class Callback
    {
    public:
        virtual ~Callback() = default;
        /*
         * Signals registered callback that this object has finished its work and can now be
         * safely destroyed/released.
         */
        virtual void OnDone(CommandResponseSender & apResponderObj) = 0;
    };

    CommandResponseSender(Callback * apCallback, CommandHandlerImpl::Callback * apDispatchCallback) :
        mpCallback(apCallback), mpCommandHandlerCallback(apDispatchCallback), mCommandHandler(this), mExchangeCtx(*this)
    {}

    CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
                                 System::PacketBufferHandle && payload) override;

    void OnResponseTimeout(Messaging::ExchangeContext * ec) override;

    void OnDone(CommandHandlerImpl & apCommandObj) override;

    void DispatchCommand(CommandHandlerImpl & apCommandObj, const ConcreteCommandPath & aCommandPath,
                         TLV::TLVReader & apPayload) override;

    Protocols::InteractionModel::Status ValidateCommandCanBeDispatched(const DataModel::InvokeRequest & request) override;

    /**
     * Gets the inner exchange context object, without ownership.
     *
     * WARNING: This is dangerous, since it is directly interacting with the
     *          exchange being managed automatically by mExchangeCtx and
     *          if not done carefully, may end up with use-after-free errors.
     *
     * @return The inner exchange context, might be nullptr if no
     *         exchange context has been assigned or the context
     *         has been released.
     */
    Messaging::ExchangeContext * GetExchangeContext() const override { return mExchangeCtx.Get(); }

    /**
     * Gets subject descriptor of the exchange.
     *
     * WARNING: This method should only be called when the caller is certain the
     * session has not been evicted.
     */
    Access::SubjectDescriptor GetSubjectDescriptor() const override
    {
        VerifyOrDie(mExchangeCtx);
        return mExchangeCtx->GetSessionHandle()->GetSubjectDescriptor();
    }

    FabricIndex GetAccessingFabricIndex() const override
    {
        VerifyOrDie(mExchangeCtx);
        return mExchangeCtx->GetSessionHandle()->GetFabricIndex();
    }

    Optional<GroupId> GetGroupId() const override
    {
        VerifyOrDie(mExchangeCtx);
        auto sessionHandle = mExchangeCtx->GetSessionHandle();
        if (sessionHandle->GetSessionType() != Transport::Session::SessionType::kGroupIncoming)
        {
            return NullOptional;
        }
        return MakeOptional(sessionHandle->AsIncomingGroupSession()->GetGroupId());
    }

    void HandlingSlowCommand() override
    {
        VerifyOrReturn(mExchangeCtx);
        auto * msgContext = mExchangeCtx->GetReliableMessageContext();
        VerifyOrReturn(msgContext != nullptr);
        TEMPORARY_RETURN_IGNORED msgContext->FlushAcks();
    }

    void AddInvokeResponseToSend(System::PacketBufferHandle && aPacket) override
    {
        VerifyOrDie(mState == State::ReadyForInvokeResponses);
        mChunks.AddToEnd(std::move(aPacket));
    }

    void ResponseDropped() override { mReportResponseDropped = true; }

    size_t GetCommandResponseMaxBufferSize() override;

    /*
     * Main entrypoint for this class to handle an invoke request.
     *
     * isTimedInvoke is true if and only if this is part of a Timed Invoke
     * transaction (i.e. was preceded by a Timed Request).  If we reach here,
     * the timer verification has already been done.
     */
    void OnInvokeCommandRequest(Messaging::ExchangeContext * ec, System::PacketBufferHandle && payload, bool isTimedInvoke);

#if CHIP_WITH_NLFAULTINJECTION
    /**
     * @brief Sends InvokeResponseMessages with injected faults for certification testing.
     *
     * The Test Harness (TH) uses this to simulate various server response behaviors,
     * ensuring the Device Under Test (DUT) handles responses per specification.
     *
     * This function strictly validates the DUT's InvokeRequestMessage against the test plan.
     * If deviations occur, the TH terminates with a detailed error message.
     *
     * @param ec Exchange context for sending InvokeResponseMessages to the client.
     * @param payload Payload of the incoming InvokeRequestMessage from the client.
     * @param isTimedInvoke Indicates whether the interaction is timed.
     * @param faultType The specific type of fault to inject into the response.
     */
    void TestOnlyInvokeCommandRequestWithFaultsInjected(Messaging::ExchangeContext * ec, System::PacketBufferHandle && payload,
                                                        bool isTimedInvoke, CommandHandlerImpl::NlFaultInjectionType faultType);
#endif // CHIP_WITH_NLFAULTINJECTION

private:
    friend class TestSessionRelease;

    enum class State : uint8_t
    {
        ReadyForInvokeResponses,       ///< Accepting InvokeResponses to send back to requester.
        AwaitingStatusResponse,        ///< Awaiting status response from requester, after sending InvokeResponse.
        AllInvokeResponsesSent,        ///< All InvokeResponses have been sent out.
        ErrorSentDelayCloseUntilOnDone ///< We have sent an early error response, but still need to clean up.
    };

    void MoveToState(const State aTargetState);
    const char * GetStateStr() const;

    /**
     * @brief Initiates the sending of InvokeResponses previously queued using AddInvokeResponseToSend.
     */
    void StartSendingCommandResponses();

    void SendStatusResponse(Protocols::InteractionModel::Status aStatus)
    {
        VerifyOrReturn(!mCommandHandler.IsResponseSuppressed(),
                       ChipLogDetail(DataManagement, "Response suppressed, skipping status: " ChipLogFormatIMStatus,
                                     ChipLogValueIMStatus(aStatus)));
        TEMPORARY_RETURN_IGNORED StatusResponse::Send(aStatus, mExchangeCtx.Get(), /*aExpectResponse = */ false);
    }

    CHIP_ERROR SendCommandResponse();
    bool HasMoreToSend() { return !mChunks.IsNull() || mReportResponseDropped; }
    void Close();

    // A list of InvokeResponseMessages to be sent out by CommandResponseSender.
    System::PacketBufferHandle mChunks;

    Callback * mpCallback;
    CommandHandlerImpl::Callback * mpCommandHandlerCallback;
    CommandHandlerImpl mCommandHandler;
    Messaging::ExchangeHolder mExchangeCtx;
    State mState = State::ReadyForInvokeResponses;

    bool mReportResponseDropped = false;
};

} // namespace app
} // namespace chip
