/*
 *
 *    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 "ClosureManager.h"
#include "ClosureControlEndpoint.h"
#include "ClosureDimensionEndpoint.h"

#include <app/server/Server.h>
#include <app/util/attribute-storage.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::DataModel;
using namespace chip::app::Clusters;
using namespace chip::DeviceLayer;
using namespace chip::app::Clusters::ClosureControl;
using namespace chip::app::Clusters::ClosureDimension;

namespace {
// Define a constant for the countdown time
constexpr uint32_t kCountdownTimeSeconds          = 10;
constexpr uint32_t kCalibrateCountdownTimeMs      = 3000; // 3 seconds for calibrate motion
constexpr uint32_t kMotionCountdownTimeMs         = 1000; // 1 second for each motion.
constexpr chip::Percent100ths kMotionPositionStep = 2000; // 20% of the total range per motion interval.

// Define the Namespace and Tag for the endpoint
// Derived from https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces/Namespace-Closure.adoc
constexpr uint8_t kNamespaceClosure   = 0x44;
constexpr uint8_t kTagClosureCovering = 0x00;
// Derived from
// https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces/Namespace-Closure-Covering.adoc
constexpr uint8_t kNamespaceCovering   = 0x46;
constexpr uint8_t kTagCoveringVenetian = 0x03;
// Derived from https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces/Namespace-ClosurePanel.adoc
constexpr uint8_t kNamespaceClosurePanel = 0x45;
constexpr uint8_t kTagClosurePanelLift   = 0x00;
constexpr uint8_t kTagClosurePanelTilt   = 0x01;

// Define the list of semantic tags for the endpoint
const Clusters::Descriptor::Structs::SemanticTagStruct::Type kClosureEndpoint1TagList[] = {
    { .namespaceID = kNamespaceClosure,
      .tag         = kTagClosureCovering,
      .label       = chip::MakeOptional(DataModel::Nullable<chip::CharSpan>("Closure.Covering"_span)) },
    { .namespaceID = kNamespaceCovering,
      .tag         = kTagCoveringVenetian,
      .label       = chip::MakeOptional(DataModel::Nullable<chip::CharSpan>("Covering.Venetian"_span)) },
};

const Clusters::Descriptor::Structs::SemanticTagStruct::Type kClosurePanelEndpoint2TagList[] = {
    { .namespaceID = kNamespaceClosurePanel,
      .tag         = kTagClosurePanelLift,
      .label       = chip::MakeOptional(DataModel::Nullable<chip::CharSpan>("ClosurePanel.Lift"_span)) },
};

const Clusters::Descriptor::Structs::SemanticTagStruct::Type kClosurePanelEndpoint3TagList[] = {
    { .namespaceID = kNamespaceClosurePanel,
      .tag         = kTagClosurePanelTilt,
      .label       = chip::MakeOptional(DataModel::Nullable<chip::CharSpan>("ClosurePanel.Tilt"_span)) },
};

} // namespace

// Definition of the static instance of ClosureManager
ClosureManager ClosureManager::sInstance;

void ClosureManager::Init()
{
    VerifyOrDie(mClosureEndpoint1.Init() == CHIP_NO_ERROR);
    ChipLogProgress(AppServer, "Closure Control Endpoint initialized successfully");

    VerifyOrDie(mClosurePanelEndpoint2.Init() == CHIP_NO_ERROR);
    ChipLogProgress(AppServer, "Closure Panel Endpoint 2 initialized successfully");

    VerifyOrDie(mClosurePanelEndpoint3.Init() == CHIP_NO_ERROR);
    ChipLogProgress(AppServer, "Closure Panel Endpoint 3 initialized successfully");

    // Set Taglist for Closure endpoints
    SuccessOrDie(SetTagList(/* endpoint= */ kClosureEndpoint1,
                            Span<const Clusters::Descriptor::Structs::SemanticTagStruct::Type>(kClosureEndpoint1TagList)));
    SuccessOrDie(SetTagList(/* endpoint= */ kClosurePanelEndpoint2,
                            Span<const Clusters::Descriptor::Structs::SemanticTagStruct::Type>(kClosurePanelEndpoint2TagList)));
    SuccessOrDie(SetTagList(/* endpoint= */ kClosurePanelEndpoint3,
                            Span<const Clusters::Descriptor::Structs::SemanticTagStruct::Type>(kClosurePanelEndpoint3TagList)));

    // Set Initial state for Closure endpoints
    VerifyOrDie(SetClosureControlInitialState(mClosureEndpoint1) == CHIP_NO_ERROR);
    ChipLogProgress(AppServer, "Initial state for Closure Control Endpoint set successfully");
    VerifyOrDie(SetClosurePanelInitialState(mClosurePanelEndpoint2) == CHIP_NO_ERROR);
    ChipLogProgress(AppServer, "Initial state for Closure Panel Endpoint 2 set successfully");
    VerifyOrDie(SetClosurePanelInitialState(mClosurePanelEndpoint3) == CHIP_NO_ERROR);
    ChipLogProgress(AppServer, "Initial state for Closure Panel Endpoint 3 set successfully");

    TestEventTriggerDelegate * pTestEventDelegate = Server::GetInstance().GetTestEventTriggerDelegate();

    if (pTestEventDelegate != nullptr)
    {
        CHIP_ERROR err = pTestEventDelegate->AddHandler(&mClosureEndpoint1.GetDelegate());
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "Failed to add handler for delegate: %s", chip::ErrorStr(err));
        }
    }
    else
    {
        ChipLogError(AppServer, "TestEventTriggerDelegate is null, cannot add handler for delegate");
    }
}

void ClosureManager::Shutdown()
{
    TestEventTriggerDelegate * pTestEventDelegate = Server::GetInstance().GetTestEventTriggerDelegate();

    if (pTestEventDelegate != nullptr)
    {
        pTestEventDelegate->RemoveHandler(&mClosureEndpoint1.GetDelegate());
    }
    else
    {
        ChipLogError(AppServer, "TestEventTriggerDelegate is null, cannot remove handler for delegate");
    }
}

CHIP_ERROR ClosureManager::SetClosureControlInitialState(ClosureControlEndpoint & closureControlEndpoint)
{
    ChipLogProgress(AppServer, "ClosureControlEndpoint SetInitialState");
    ClosureControl::ClusterConformance conformance = closureControlEndpoint.GetLogic().GetConformance();
    Optional<DataModel::Nullable<CurrentPositionEnum>> currentPosition =
        conformance.HasFeature(ClosureControl::Feature::kPositioning)
        ? MakeOptional(DataModel::MakeNullable(CurrentPositionEnum::kFullyClosed))
        : NullOptional;
    Optional<DataModel::Nullable<bool>> currentLatch = conformance.HasFeature(ClosureControl::Feature::kMotionLatching)
        ? MakeOptional(DataModel::MakeNullable(true))
        : NullOptional;
    Optional<Globals::ThreeLevelAutoEnum> speed =
        conformance.HasFeature(ClosureControl::Feature::kSpeed) ? MakeOptional(Globals::ThreeLevelAutoEnum::kAuto) : NullOptional;
    DataModel::Nullable<GenericOverallCurrentState> overallState(
        GenericOverallCurrentState(currentPosition, currentLatch, speed, DataModel::MakeNullable(true)));
    ReturnErrorOnFailure(closureControlEndpoint.GetLogic().SetOverallCurrentState(overallState));

    Optional<DataModel::Nullable<TargetPositionEnum>> targetPosition =
        conformance.HasFeature(ClosureControl::Feature::kPositioning) ? MakeOptional(DataModel::NullNullable) : NullOptional;
    Optional<DataModel::Nullable<bool>> targetLatch =
        conformance.HasFeature(ClosureControl::Feature::kMotionLatching) ? MakeOptional(DataModel::NullNullable) : NullOptional;
    DataModel::Nullable<GenericOverallTargetState> overallTarget(GenericOverallTargetState(targetPosition, targetLatch, speed));
    ReturnErrorOnFailure(closureControlEndpoint.GetLogic().SetOverallTargetState(overallTarget));

    if (conformance.HasFeature(ClosureControl::Feature::kPositioning) &&
        !conformance.HasFeature(ClosureControl::Feature::kInstantaneous))
    {
        ReturnErrorOnFailure(closureControlEndpoint.GetLogic().SetCountdownTimeFromDelegate(NullNullable));
    }
    ReturnErrorOnFailure(closureControlEndpoint.GetLogic().SetMainState(MainStateEnum::kStopped));

    if (conformance.HasFeature(ClosureControl::Feature::kMotionLatching))
    {
        BitFlags<ClosureControl::LatchControlModesBitmap> latchControlModes;
        latchControlModes.Set(ClosureControl::LatchControlModesBitmap::kRemoteLatching)
            .Set(ClosureControl::LatchControlModesBitmap::kRemoteUnlatching);
        ReturnErrorOnFailure(closureControlEndpoint.GetLogic().SetLatchControlModes(latchControlModes));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ClosureManager::SetClosurePanelInitialState(ClosureDimensionEndpoint & closurePanelEndpoint)
{
    ChipLogProgress(AppServer, "ClosurePanelEndpoint SetInitialState");
    ClosureDimension::ClusterConformance conformance = closurePanelEndpoint.GetLogic().GetConformance();

    Optional<DataModel::Nullable<Percent100ths>> currentPosition = conformance.HasFeature(ClosureDimension::Feature::kPositioning)
        ? MakeOptional(DataModel::MakeNullable<Percent100ths>(10000))
        : NullOptional;
    Optional<DataModel::Nullable<bool>> currentLatch = conformance.HasFeature(ClosureDimension::Feature::kMotionLatching)
        ? MakeOptional(DataModel::MakeNullable(true))
        : NullOptional;
    Optional<Globals::ThreeLevelAutoEnum> speed =
        conformance.HasFeature(ClosureDimension::Feature::kSpeed) ? MakeOptional(Globals::ThreeLevelAutoEnum::kAuto) : NullOptional;
    DataModel::Nullable<GenericDimensionStateStruct> currentState(
        GenericDimensionStateStruct(currentPosition, currentLatch, speed));
    ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetCurrentState(currentState));

    Optional<DataModel::Nullable<Percent100ths>> targetPosition =
        conformance.HasFeature(ClosureDimension::Feature::kPositioning) ? MakeOptional(DataModel::NullNullable) : NullOptional;
    Optional<DataModel::Nullable<bool>> targetLatch =
        conformance.HasFeature(ClosureDimension::Feature::kMotionLatching) ? MakeOptional(DataModel::NullNullable) : NullOptional;
    DataModel::Nullable<GenericDimensionStateStruct> targetState(GenericDimensionStateStruct(targetPosition, targetLatch, speed));
    ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetTargetState(targetState));

    if (conformance.HasFeature(ClosureDimension::Feature::kPositioning))
    {
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetResolution(Percent100ths(100)));
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetStepValue(1000));
    }
    if (conformance.HasFeature(ClosureDimension::Feature::kUnit))
    {
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetUnit(ClosureUnitEnum::kMillimeter));
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetUnitRange(ClosureDimension::Structs::UnitRangeStruct::Type{
            .min = static_cast<int16_t>(0), .max = static_cast<int16_t>(10000) }));
    }
    if (conformance.HasFeature(ClosureDimension::Feature::kRotation))
    {
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetOverflow(OverflowEnum::kTopInside));
    }
    if (conformance.HasFeature(ClosureDimension::Feature::kLimitation))
    {
        ClosureDimension::Structs::RangePercent100thsStruct::Type limitRange{ .min = static_cast<Percent100ths>(0),
                                                                              .max = static_cast<Percent100ths>(10000) };
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetLimitRange(limitRange));
    }
    if (conformance.HasFeature(ClosureDimension::Feature::kMotionLatching))
    {
        BitFlags<ClosureDimension::LatchControlModesBitmap> latchControlModes;
        latchControlModes.Set(ClosureDimension::LatchControlModesBitmap::kRemoteLatching)
            .Set(ClosureDimension::LatchControlModesBitmap::kRemoteUnlatching);
        ReturnErrorOnFailure(closurePanelEndpoint.GetLogic().SetLatchControlModes(latchControlModes));
    }

    return CHIP_NO_ERROR;
}

chip::Protocols::InteractionModel::Status ClosureManager::OnCalibrateCommand()
{
    // Cancel any existing timers for closure actions over all endpoints
    DeviceLayer::SystemLayer().CancelTimer(HandleEp1ClosureActionTimer, this);
    DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
    DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);

    mEp1CurrentAction              = ClosureAction::kCalibrateAction;
    mIsCalibrationActionInProgress = true;

    // For sample application, we are using a timer to simulate the hardware calibration action.
    // In a real application, this would be replaced with actual calibration logic and call HandleClosureActionComplete.
    VerifyOrReturnValue(DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kCalibrateCountdownTimeMs),
                                                              HandleEp1ClosureActionTimer, nullptr) == CHIP_NO_ERROR,
                        Status::Failure, ChipLogError(AppServer, "Failed to start closure action timer"));

    ChipLogProgress(AppServer, "ClosureManager: Calibration action started for endpoint 1");
    return Status::Success;
}

chip::Protocols::InteractionModel::Status ClosureManager::OnStopCommand()
{
    // Cancel any existing timers for closure action
    DeviceLayer::SystemLayer().CancelTimer(HandleEp1ClosureActionTimer, this);
    DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
    DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);
    mEp1CurrentAction = ClosureAction::kStopAction;
    HandleStopActionComplete();
    return Status::Success;
}

chip::Protocols::InteractionModel::Status
ClosureManager::OnMoveToCommand(const Optional<TargetPositionEnum> & position, const Optional<bool> & latch,
                                const Optional<chip::app::Clusters::Globals::ThreeLevelAutoEnum> & speed)
{
    // Cancel any existing timer for closure action
    (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp1ClosureActionTimer, this);

    // Update the target state for the closure panels based on the MoveTo command.
    // This closure sample app assumes that the closure panels are represented by two endpoints:
    // - Endpoint 2: Represents the Closure Dimension Cluster for the first panel.
    // - Endpoint 3: Represents the Closure Dimension Cluster for the second panel.

    // For sample app, MoveTo command to Fullopen , will set target position of both panels to 0
    //  MoveTo command to Fullclose will set target position of both panels to 10000
    //  We simulate harware action by using timer for 1 sec and updating the current state of the panels after the timer expires.
    //  till we reach the target position.

    DataModel::Nullable<GenericDimensionStateStruct> ep2CurrentState;
    VerifyOrReturnError(mClosurePanelEndpoint2.GetLogic().GetCurrentState(ep2CurrentState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get current state for Endpoint 2"));
    DataModel::Nullable<GenericDimensionStateStruct> ep3CurrentState;
    VerifyOrReturnError(mClosurePanelEndpoint3.GetLogic().GetCurrentState(ep3CurrentState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get current state for Endpoint 3"));

    DataModel::Nullable<GenericDimensionStateStruct> ep2TargetState;
    VerifyOrReturnError(mClosurePanelEndpoint2.GetLogic().GetTargetState(ep2TargetState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get target state for Endpoint 2"));
    DataModel::Nullable<GenericDimensionStateStruct> ep3TargetState;
    VerifyOrReturnError(mClosurePanelEndpoint3.GetLogic().GetTargetState(ep3TargetState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get target state for Endpoint 3"));

    VerifyOrReturnError(!ep2CurrentState.IsNull(), Status::Failure,
                        ChipLogError(AppServer, "MoveToCommand failed due to Null value Current state on Endpoint 2"));
    VerifyOrReturnError(!ep3CurrentState.IsNull(), Status::Failure,
                        ChipLogError(AppServer, "MoveToCommand failed due to Null value Current state on Endpoint 3"));

    // Create target struct for the panels if the target state is not set.
    GenericDimensionStateStruct ep2Target = ep2TargetState.IsNull() ? GenericDimensionStateStruct() : ep2TargetState.Value();
    GenericDimensionStateStruct ep3Target = ep3TargetState.IsNull() ? GenericDimensionStateStruct() : ep3TargetState.Value();
    ClosureDimension::ClusterConformance ep2Conformance = mClosurePanelEndpoint2.GetLogic().GetConformance();
    ClosureDimension::ClusterConformance ep3Conformance = mClosurePanelEndpoint3.GetLogic().GetConformance();
    if (position.HasValue())
    {
        // Set the Closure panel target position for the panels based on the MoveTo Command position.
        // For Sample App,TargetPositionEnum is mapped to specific positions for the panels.
        chip::Percent100ths ep2Position;
        chip::Percent100ths ep3Position;

        switch (position.Value())
        {
        case TargetPositionEnum::kMoveToFullyClosed:
            ep2Position = static_cast<chip::Percent100ths>(10000);
            ep3Position = static_cast<chip::Percent100ths>(10000);
            break;
        case TargetPositionEnum::kMoveToFullyOpen:
            ep2Position = static_cast<chip::Percent100ths>(0);
            ep3Position = static_cast<chip::Percent100ths>(0);
            break;
        case TargetPositionEnum::kMoveToPedestrianPosition:
            ep2Position = static_cast<chip::Percent100ths>(6000);
            ep3Position = static_cast<chip::Percent100ths>(6000);
            break;
        case TargetPositionEnum::kMoveToSignaturePosition:
            ep2Position = static_cast<chip::Percent100ths>(4000);
            ep3Position = static_cast<chip::Percent100ths>(4000);
            break;
        case TargetPositionEnum::kMoveToVentilationPosition:
            ep2Position = static_cast<chip::Percent100ths>(2000);
            ep3Position = static_cast<chip::Percent100ths>(2000);
            break;
        default:
            ChipLogError(AppServer, "Invalid target position received in OnMoveToCommand");
            return Status::Failure;
        }

        if (ep2Conformance.HasFeature(ClosureDimension::Feature::kPositioning))
        {
            ep2Target.position.SetValue(DataModel::MakeNullable(ep2Position));
        }
        if (ep3Conformance.HasFeature(ClosureDimension::Feature::kPositioning))
        {
            ep3Target.position.SetValue(DataModel::MakeNullable(ep3Position));
        }
    }

    if (latch.HasValue())
    {
        if (ep2Conformance.HasFeature(ClosureDimension::Feature::kMotionLatching))
        {
            ep2Target.latch.SetValue(DataModel::MakeNullable(latch.Value()));
        }
        if (ep3Conformance.HasFeature(ClosureDimension::Feature::kMotionLatching))
        {
            ep3Target.latch.SetValue(DataModel::MakeNullable(latch.Value()));
        }
    }

    if (speed.HasValue())
    {
        if (ep2Conformance.HasFeature(ClosureDimension::Feature::kSpeed))
        {
            ep2Target.speed.SetValue(speed.Value());
        }
        if (ep3Conformance.HasFeature(ClosureDimension::Feature::kSpeed))
        {
            ep3Target.speed.SetValue(speed.Value());
        }
    }

    VerifyOrReturnError(mClosurePanelEndpoint2.GetLogic().SetTargetState(DataModel::MakeNullable(ep2Target)) == CHIP_NO_ERROR,
                        Status::Failure, ChipLogError(AppServer, "Failed to set target for Endpoint 2"));
    VerifyOrReturnError(mClosurePanelEndpoint3.GetLogic().SetTargetState(DataModel::MakeNullable(ep3Target)) == CHIP_NO_ERROR,
                        Status::Failure, ChipLogError(AppServer, "Failed to set target for Endpoint 3"));
    VerifyOrReturnError(mClosureEndpoint1.GetLogic().SetCountdownTimeFromDelegate(kCountdownTimeSeconds) == CHIP_NO_ERROR,
                        Status::Failure, ChipLogError(AppServer, "Failed to set countdown time for move to command on Endpoint 1"));

    mEp1CurrentAction    = ClosureAction::kMoveToAction;
    mEp1MotionInProgress = true;
    TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                                   HandleEp1ClosureActionTimer, this);
    return Status::Success;
}

chip::Protocols::InteractionModel::Status ClosureManager::OnSetTargetCommand(const Optional<Percent100ths> & position,
                                                                             const Optional<bool> & latch,
                                                                             const Optional<Globals::ThreeLevelAutoEnum> & speed,
                                                                             const chip::EndpointId endpointId)
{
    MainStateEnum ep1MainState;
    VerifyOrReturnError(mClosureEndpoint1.GetLogic().GetMainState(ep1MainState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get main state for Step command on Endpoint 1"));

    // If this command is received while the MainState attribute is currently either in Disengaged, Protected, Calibrating,
    //  SetupRequired or Error, then a status code of INVALID_IN_STATE shall be returned.
    VerifyOrReturnError(ep1MainState != MainStateEnum::kDisengaged && ep1MainState != MainStateEnum::kProtected &&
                            ep1MainState != MainStateEnum::kSetupRequired && ep1MainState != MainStateEnum::kError &&
                            ep1MainState != MainStateEnum::kCalibrating,
                        Status::InvalidInState,
                        ChipLogError(AppServer, "Step command not allowed in current state: %d", static_cast<int>(ep1MainState)));

    // Update OverallTarget of Closure based on SetTarget command.
    DataModel::Nullable<GenericOverallTargetState> overallTargetState;
    VerifyOrReturnError(mClosureEndpoint1.GetLogic().GetOverallTargetState(overallTargetState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get overall target for SetTarget command"));

    if (overallTargetState.IsNull())
    {
        overallTargetState.SetNonNull(GenericOverallTargetState{});
    }

    ClosureDimensionEndpoint mClosurePanelEndpoint =
        endpointId == kClosurePanelEndpoint2 ? mClosurePanelEndpoint2 : mClosurePanelEndpoint3;
    ClosureDimension::ClusterConformance mClosurePanelConformance = mClosurePanelEndpoint.GetLogic().GetConformance();

    if (position.HasValue() && mClosurePanelConformance.HasFeature(ClosureDimension::Feature::kPositioning))
    {
        // Set overallTargetState position to NullOptional as panel position change cannot be represented in OverallTarget.
        overallTargetState.Value().position.SetValue(DataModel::NullNullable);
    }

    if (latch.HasValue() && mClosurePanelConformance.HasFeature(ClosureDimension::Feature::kMotionLatching))
    {
        overallTargetState.Value().latch.SetValue(DataModel::MakeNullable(latch.Value()));
    }

    if (speed.HasValue() && mClosurePanelConformance.HasFeature(ClosureDimension::Feature::kSpeed))
    {
        overallTargetState.Value().speed.SetValue(speed.Value());
    }

    VerifyOrReturnError(mClosureEndpoint1.GetLogic().SetOverallTargetState(overallTargetState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to set overall target for SetTarget command for Endpoint %d", endpointId));

    VerifyOrReturnError(mClosureEndpoint1.GetLogic().SetCountdownTimeFromDelegate(kCountdownTimeSeconds) == CHIP_NO_ERROR,
                        Status::Failure,
                        ChipLogError(AppServer, "Failed to set countdown time for SetTarget command on Endpoint %d", endpointId));

    VerifyOrReturnError(mClosureEndpoint1.GetLogic().SetMainState(MainStateEnum::kMoving) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to set main state for SetTarget command on Endpoint 1"));

    // Post an event to initiate the unlatch action asynchronously.
    // Closure panel first performs the unlatch action if it is currently latched,
    // and then continues with the SetTarget action.
    // This is to ensure that the panel can move to the target position without being latched.
    if (endpointId == kClosurePanelEndpoint2)
    {
        mEp2CurrentAction    = ClosureManager::ClosureAction::kSetTargetAction;
        mEp2MotionInProgress = true;
        (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
        (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                     HandleEp2ClosureActionTimer, this);
        ChipLogError(AppServer, "Triggered HandleEp2ClosureActionTimer for SetTarget command on Endpoint 2");
    }
    else if (endpointId == kClosurePanelEndpoint3)
    {
        mEp3CurrentAction    = ClosureManager::ClosureAction::kSetTargetAction;
        mEp3MotionInProgress = true;
        (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);
        (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                     HandleEp3ClosureActionTimer, this);
        ChipLogError(AppServer, "Triggered HandleEp3ClosureActionTimer for SetTarget command on Endpoint 3");
    }
    else
    {
        ChipLogError(AppServer, "Invalid endpoint ID for SetTarget command: %d", endpointId);
        return Status::Failure;
    }

    return Status::Success;
}

chip::Protocols::InteractionModel::Status ClosureManager::OnStepCommand(const StepDirectionEnum & direction,
                                                                        const uint16_t & numberOfSteps,
                                                                        const Optional<Globals::ThreeLevelAutoEnum> & speed,
                                                                        const chip::EndpointId endpointId)
{
    MainStateEnum ep1MainState;
    VerifyOrReturnError(mClosureEndpoint1.GetLogic().GetMainState(ep1MainState) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get main state for Step command on Endpoint 1"));

    // If this command is received while the MainState attribute is currently either in Disengaged, Protected, Calibrating,
    //  SetupRequired or Error, then a status code of INVALID_IN_STATE shall be returned.
    VerifyOrReturnError(ep1MainState != MainStateEnum::kDisengaged && ep1MainState != MainStateEnum::kProtected &&
                            ep1MainState != MainStateEnum::kSetupRequired && ep1MainState != MainStateEnum::kError &&
                            ep1MainState != MainStateEnum::kCalibrating,
                        Status::InvalidInState,
                        ChipLogError(AppServer, "Step command not allowed in current state: %d", static_cast<int>(ep1MainState)));

    VerifyOrReturnError(mClosureEndpoint1.GetLogic().SetMainState(MainStateEnum::kMoving) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to set countdown time for move to command on Endpoint 1"));

    VerifyOrReturnError(mClosureEndpoint1.GetLogic().SetCountdownTimeFromDelegate(10) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to set countdown time for move to command on Endpoint 1"));

    // Update Overall Target to Null for the Closure Control on Endpoint 1
    DataModel::Nullable<GenericOverallTargetState> ep1Target;

    VerifyOrReturnValue(mClosureEndpoint1.GetLogic().GetOverallTargetState(ep1Target) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to get overall target for Step command"));

    if (ep1Target.IsNull())
    {
        ep1Target.SetNonNull(GenericOverallTargetState{});
    }

    ep1Target.Value().position.SetValue(
        DataModel::NullNullable); // Set position to Null as it cannot represent panel position change.

    VerifyOrReturnValue(mClosureEndpoint1.GetLogic().SetOverallTargetState(ep1Target) == CHIP_NO_ERROR, Status::Failure,
                        ChipLogError(AppServer, "Failed to set overall target for Step command"));

    if (endpointId == kClosurePanelEndpoint2)
    {
        mEp2CurrentAction    = ClosureManager::ClosureAction::kStepAction;
        mEp2MotionInProgress = true;
        (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
        (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                     HandleEp2ClosureActionTimer, this);
        ChipLogError(AppServer, "Triggered HandleEp2ClosureActionTimer for Step command on Endpoint 2");
    }
    else if (endpointId == kClosurePanelEndpoint3)
    {
        mEp3CurrentAction    = ClosureManager::ClosureAction::kStepAction;
        mEp3MotionInProgress = true;
        (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);
        (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                     HandleEp3ClosureActionTimer, this);
        ChipLogError(AppServer, "Triggered HandleEp3ClosureActionTimer for Step command on Endpoint 3");
    }
    else
    {
        ChipLogError(AppServer, "Invalid endpoint ID for SetTarget command: %d", endpointId);
        return Status::Failure;
    }
    return Status::Success;
}

void ClosureManager::HandleEp1ClosureActionTimer(System::Layer * layer, void * aAppState)
{
    // Mark aAppState as unused to avoid compiler warnings
    // Will be used in closure dimension cluster Commands
    (void) aAppState;

    ClosureManager & instance = ClosureManager::GetInstance();
    ChipLogError(AppServer, "HandleEp1ClosureActionTimer called with current action: %d",
                 static_cast<int>(instance.mEp1CurrentAction));

    switch (instance.mEp1CurrentAction)
    {
    case ClosureAction::kCalibrateAction:
        instance.HandleCalibrateActionComplete();
        break;
    case ClosureAction::kStopAction:
        // Add logic to handle Stop action completion
        break;
    case ClosureAction::kMoveToAction:
        instance.HandleClosureMotionAction();
        break;
    case ClosureAction::kLatchAction:
        // Add logic to handle Latch action completion
        break;
    default:
        ChipLogError(AppServer, "Invalid action received in HandleEp1ClosureActionTimer");
        break;
    }
}

void ClosureManager::HandleEp2ClosureActionTimer(System::Layer * layer, void * aAppState)
{
    // Mark aAppState as unused to avoid compiler warnings
    // Will be used in closure dimension cluster Commands
    (void) aAppState;

    ClosureManager & instance = ClosureManager::GetInstance();
    ChipLogError(AppServer, "HandleEp2ClosureActionTimer called with current action: %d",
                 static_cast<int>(instance.mEp2CurrentAction));

    switch (instance.mEp2CurrentAction)
    {
    case ClosureAction::kSetTargetAction:
        instance.HandlePanelSetTargetAction(kClosurePanelEndpoint2);
        break;
    case ClosureAction::kStepAction:
        instance.HandlePanelStepAction(kClosurePanelEndpoint2);
        break;
    case ClosureAction::kPanelUnLatchAction:
        instance.HandlePanelUnlatchAction(kClosurePanelEndpoint2);
        break;
    default:
        ChipLogError(AppServer, "Invalid action received in HandleEp2ClosureActionTimer");
        break;
    }
}

void ClosureManager::HandleEp3ClosureActionTimer(System::Layer * layer, void * aAppState)
{
    // Mark aAppState as unused to avoid compiler warnings
    // Will be used in closure dimension cluster Commands
    (void) aAppState;

    ClosureManager & instance = ClosureManager::GetInstance();
    ChipLogError(AppServer, "HandleEp3ClosureActionTimer called with current action: %d",
                 static_cast<int>(instance.mEp3CurrentAction));

    switch (instance.mEp3CurrentAction)
    {
    case ClosureAction::kSetTargetAction:
        instance.HandlePanelSetTargetAction(kClosurePanelEndpoint3);
        break;
    case ClosureAction::kStepAction:
        instance.HandlePanelStepAction(kClosurePanelEndpoint3);
        break;
    case ClosureAction::kPanelLatchAction:
        instance.HandlePanelUnlatchAction(kClosurePanelEndpoint3);
        break;
    default:
        ChipLogError(AppServer, "Invalid action received in HandleEp3ClosureActionTimer");
        break;
    }
}

void ClosureManager::HandlePanelUnlatchAction(EndpointId endpointId)
{
    ClosureManager & instance = ClosureManager::GetInstance();

    // Get the endpoint instance based on the endpointId
    chip::app::Clusters::ClosureDimension::ClosureDimensionEndpoint * panelEp = GetCurrentPanelInstance(endpointId);
    VerifyOrReturn(panelEp != nullptr,
                   ChipLogError(AppServer, "HandlePanelSetTargetAction called with invalid endpointId: %u", endpointId));

    DataModel::Nullable<GenericDimensionStateStruct> panelCurrentState = DataModel::NullNullable;
    DataModel::Nullable<GenericDimensionStateStruct> panelTargetState  = DataModel::NullNullable;

    VerifyOrReturn(panelEp->GetLogic().GetCurrentState(panelCurrentState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get current state for Endpoint %d", endpointId));
    VerifyOrReturn(!panelCurrentState.IsNull(), ChipLogError(AppServer, "Current state is not set for Endpoint %d", endpointId));

    VerifyOrReturn(panelEp->GetLogic().GetTargetState(panelTargetState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get target for Endpoint %d", endpointId));
    VerifyOrReturn(!panelTargetState.IsNull(), ChipLogError(AppServer, "Target is not set for Endpoint %d", endpointId));

    // If currently latched (true) and target is unlatched (false), Perform unlatch action and call timer with SET_TARGET_ACTION
    // to continue with the SetTarget action.
    if (panelCurrentState.Value().latch.HasValue() && !panelCurrentState.Value().latch.Value().IsNull() &&
        panelTargetState.Value().latch.HasValue() && !panelTargetState.Value().latch.Value().IsNull() &&
        (panelCurrentState.Value().latch.Value().Value() && !panelTargetState.Value().latch.Value().Value()))
    {
        DataModel::Nullable<GenericOverallCurrentState> ep1OverallCurrentState = DataModel::NullNullable;

        VerifyOrReturn(mClosureEndpoint1.GetLogic().GetOverallCurrentState(ep1OverallCurrentState) == CHIP_NO_ERROR,
                       ChipLogError(AppServer, "Failed to get current state for Endpoint 1"));
        VerifyOrReturn(!ep1OverallCurrentState.IsNull(), ChipLogError(AppServer, "Current state is not set for Endpoint 1"));

        // In Real application, this would be replaced with actual unlatch logic.
        ChipLogProgress(AppServer, "Performing unlatch action");

        ep1OverallCurrentState.Value().latch.SetValue(DataModel::MakeNullable(false));
        ep1OverallCurrentState.Value().secureState.SetNonNull(false);
        TEMPORARY_RETURN_IGNORED mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1OverallCurrentState);

        panelCurrentState.Value().latch.SetValue(false);
        TEMPORARY_RETURN_IGNORED panelEp->GetLogic().SetCurrentState(panelCurrentState);

        ChipLogProgress(AppServer, "Unlatched action completed");
    }

    // Cancel any active timers before starting the panel movement
    if (endpointId == kClosurePanelEndpoint2)
    {
        (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
    }
    else if (endpointId == kClosurePanelEndpoint3)
    {
        (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);
    }
    else
    {
        ChipLogError(AppServer, "Invalid endpoint ID for SetTarget command: %d", endpointId);
        return;
    }

    instance.HandlePanelSetTargetAction(endpointId);
}

void ClosureManager::HandlePanelSetTargetAction(EndpointId endpointId)
{
    // Get the endpoint instance based on the endpointId
    chip::app::Clusters::ClosureDimension::ClosureDimensionEndpoint * ep = GetCurrentPanelInstance(endpointId);
    VerifyOrReturn(ep != nullptr,
                   ChipLogError(AppServer, "HandlePanelSetTargetAction called with invalid endpointId: %u", endpointId));

    DataModel::Nullable<GenericDimensionStateStruct> panelCurrentState = DataModel::NullNullable;
    DataModel::Nullable<GenericDimensionStateStruct> panelTargetState  = DataModel::NullNullable;

    VerifyOrReturn(ep->GetLogic().GetCurrentState(panelCurrentState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get current state for Endpoint %d", endpointId));
    VerifyOrReturn(!panelCurrentState.IsNull(), ChipLogError(AppServer, "Current state is not set for Endpoint %d", endpointId));

    VerifyOrReturn(ep->GetLogic().GetTargetState(panelTargetState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get target for Endpoint %d", endpointId));
    VerifyOrReturn(!panelTargetState.IsNull(), ChipLogError(AppServer, "Target is not set for Endpoint %d", endpointId));

    bool panelProgressPossible                            = false;
    DataModel::Nullable<chip::Percent100ths> nextPosition = DataModel::NullNullable;

    // Get the Next Current State to be set for the endpoint 2, if target postion is not reached.
    if (GetPanelNextPosition(panelCurrentState.Value(), panelTargetState.Value(), nextPosition))
    {
        VerifyOrReturn(!nextPosition.IsNull(), ChipLogError(AppServer, "Next position is not set for Endpoint %d", endpointId));

        panelCurrentState.Value().position.SetValue(DataModel::MakeNullable(nextPosition.Value()));
        TEMPORARY_RETURN_IGNORED ep->GetLogic().SetCurrentState(panelCurrentState);

        panelProgressPossible = (nextPosition.Value() != panelTargetState.Value().position.Value().Value());
        ChipLogProgress(AppServer, "EndPoint %d Current Position: %d, Target Position: %d", endpointId, nextPosition.Value(),
                        panelTargetState.Value().position.Value().Value());
    }

    if (panelProgressPossible)
    {
        // Start the timer for the respective endpoint to continue with the SetTarget action
        if (endpointId == kClosurePanelEndpoint2)
        {
            mEp2CurrentAction = ClosureManager::ClosureAction::kSetTargetAction;
            (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
            (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                         HandleEp2ClosureActionTimer, this);
            ChipLogError(AppServer, "Triggered HandleEp2ClosureActionTimer for SetTarget Action command on Endpoint 2");
        }
        else if (endpointId == kClosurePanelEndpoint3)
        {
            mEp3CurrentAction = ClosureManager::ClosureAction::kSetTargetAction;
            (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);
            (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                         HandleEp3ClosureActionTimer, this);
            ChipLogError(AppServer, "Triggered HandleEp3ClosureActionTimer for SetTarget Action command on Endpoint 3");
        }
        else
        {
            ChipLogError(AppServer, "Invalid endpoint ID for SetTarget command: %d", endpointId);
        }
        return;
    }

    // If currently unlatched (false) and target is latched (true), latch after completing motion if Latching feature is supported.
    if (ep->GetLogic().GetConformance().HasFeature(ClosureDimension::Feature::kMotionLatching))
    {
        if (panelCurrentState.Value().latch.HasValue() && !panelCurrentState.Value().latch.Value().IsNull() &&
            panelTargetState.Value().latch.HasValue() && !panelTargetState.Value().latch.Value().IsNull())
        {
            if (!panelCurrentState.Value().latch.Value().Value() && panelTargetState.Value().latch.Value().Value())
            {
                DataModel::Nullable<GenericOverallCurrentState> ep1OverallCurrentState = DataModel::NullNullable;
                VerifyOrReturn(mClosureEndpoint1.GetLogic().GetOverallCurrentState(ep1OverallCurrentState) == CHIP_NO_ERROR,
                               ChipLogError(AppServer, "Failed to get overall current state for Endpoint 1"));
                VerifyOrReturn(!ep1OverallCurrentState.IsNull(),
                               ChipLogError(AppServer, "Overall current state is not set for Endpoint 1"));

                // In Real application, this would be replaced with actual latch logic.
                ChipLogProgress(AppServer, "Performing latch action");

                ep1OverallCurrentState.Value().latch.SetValue(DataModel::MakeNullable(true));
                ep1OverallCurrentState.Value().secureState.SetNonNull(false);
                TEMPORARY_RETURN_IGNORED mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1OverallCurrentState);

                panelCurrentState.Value().latch.SetValue(DataModel::MakeNullable(true));
                TEMPORARY_RETURN_IGNORED ep->GetLogic().SetCurrentState(panelCurrentState);

                ChipLogProgress(AppServer, "Latch action completed");
            }
        }
    }
    // If the target position is reached, call the HandlePanelSetTargetActionComplete method to complete the action
    HandlePanelSetTargetActionComplete(endpointId);
}

void ClosureManager::HandlePanelStepAction(EndpointId endpointId)
{
    ClosureManager & instance = ClosureManager::GetInstance();

    // Get the endpoint instance based on the endpointId
    chip::app::Clusters::ClosureDimension::ClosureDimensionEndpoint * ep = GetCurrentPanelInstance(endpointId);
    VerifyOrReturn(ep != nullptr,
                   ChipLogError(AppServer, "HandlePanelSetTargetAction called with invalid endpointId: %u", endpointId));
    StepDirectionEnum stepDirection = ep->GetDelegate().GetStepCommandTargetDirection();

    DataModel::Nullable<GenericDimensionStateStruct> panelCurrentState;
    DataModel::Nullable<GenericDimensionStateStruct> panelTargetState;

    VerifyOrReturn(ep->GetLogic().GetCurrentState(panelCurrentState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get current state for Step action"));
    VerifyOrReturn(ep->GetLogic().GetTargetState(panelTargetState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get target state for Step action"));

    VerifyOrReturn(!panelCurrentState.IsNull(), ChipLogError(AppServer, "Current state is null, Step action Failed"));
    VerifyOrReturn(!panelTargetState.IsNull(), ChipLogError(AppServer, "Target state  is null, Step action Failed"));
    VerifyOrReturn(panelCurrentState.Value().position.HasValue() && !panelCurrentState.Value().position.Value().IsNull(),
                   ChipLogError(AppServer, "Current or target position is not set, Step action Failed"));
    VerifyOrReturn(panelTargetState.Value().position.HasValue() && !panelTargetState.Value().position.Value().IsNull(),
                   ChipLogError(AppServer, "Current or target position is not set, Step action Failed"));

    chip::Percent100ths currentPosition = panelCurrentState.Value().position.Value().Value();
    chip::Percent100ths targetPosition  = panelTargetState.Value().position.Value().Value();

    ChipLogProgress(AppServer, "Current Position: %d, Target Position: %d", currentPosition, targetPosition);

    bool panelTargetReached = (currentPosition == targetPosition);
    ChipLogProgress(AppServer, "Panel Target Reached: %s", panelTargetReached ? "true" : "false");

    if (!panelTargetReached)
    {
        chip::Percent100ths nextCurrentPosition;
        chip::Percent100ths stepValue;
        VerifyOrReturn(ep->GetLogic().GetStepValue(stepValue) == CHIP_NO_ERROR,
                       ChipLogError(AppServer, "Failed to get step value for Step action"));

        // Compute the next position
        if (stepDirection == StepDirectionEnum::kIncrease)
        {
            nextCurrentPosition = std::min(static_cast<chip::Percent100ths>(currentPosition + stepValue), targetPosition);
        }
        else
        {
            // Underflow protection: if currentPosition <= stepValue, set to 0.
            chip::Percent100ths decreasedCurrentPosition = (currentPosition > stepValue)
                ? static_cast<chip::Percent100ths>(currentPosition - stepValue)
                : static_cast<chip::Percent100ths>(0);
            nextCurrentPosition                          = std::max(decreasedCurrentPosition, targetPosition);
        }

        panelCurrentState.Value().position.SetValue(DataModel::MakeNullable(nextCurrentPosition));
        TEMPORARY_RETURN_IGNORED ep->GetLogic().SetCurrentState(panelCurrentState);

        // Cancel any existing timer before starting a new action
        if (endpointId == kClosurePanelEndpoint2)
        {
            instance.mEp2CurrentAction = ClosureManager::ClosureAction::kStepAction;
            (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp2ClosureActionTimer, this);
            (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                         HandleEp2ClosureActionTimer, this);
            ChipLogError(AppServer, "Triggered HandleEp2ClosureActionTimer for Step Action command on Endpoint 2");
        }
        else if (endpointId == kClosurePanelEndpoint3)
        {
            instance.mEp3CurrentAction = ClosureManager::ClosureAction::kStepAction;
            (void) DeviceLayer::SystemLayer().CancelTimer(HandleEp3ClosureActionTimer, this);
            (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                         HandleEp3ClosureActionTimer, this);
            ChipLogError(AppServer, "Triggered HandleEp3ClosureActionTimer for Step Action command on Endpoint 3");
        }
        else
        {
            ChipLogError(AppServer, "Invalid endpoint ID for SetTarget command: %d", endpointId);
        }
        return;
    }

    // If the target position is reached, we can complete the action
    HandlePanelStepActionComplete(endpointId);
}

void ClosureManager::HandleClosureMotionAction()
{
    ClosureManager & instance = ClosureManager::GetInstance();

    DataModel::Nullable<GenericOverallCurrentState> ep1CurrentState;
    DataModel::Nullable<GenericDimensionStateStruct> ep2CurrentState;
    DataModel::Nullable<GenericDimensionStateStruct> ep3CurrentState;

    DataModel::Nullable<GenericOverallTargetState> ep1TargetState;
    DataModel::Nullable<GenericDimensionStateStruct> ep2TargetState;
    DataModel::Nullable<GenericDimensionStateStruct> ep3TargetState;

    VerifyOrReturn(mClosureEndpoint1.GetLogic().GetOverallCurrentState(ep1CurrentState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get current state for Endpoint 1"));
    VerifyOrReturn(mClosureEndpoint1.GetLogic().GetOverallTargetState(ep1TargetState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get target state for Endpoint 1"));

    VerifyOrReturn(mClosurePanelEndpoint2.GetLogic().GetCurrentState(ep2CurrentState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get current state for Endpoint 2"));
    VerifyOrReturn(mClosurePanelEndpoint3.GetLogic().GetCurrentState(ep3CurrentState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get current state for Endpoint 3"));
    VerifyOrReturn(mClosurePanelEndpoint2.GetLogic().GetTargetState(ep2TargetState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get target state for Endpoint 2"));
    VerifyOrReturn(mClosurePanelEndpoint3.GetLogic().GetTargetState(ep3TargetState) == CHIP_NO_ERROR,
                   ChipLogError(AppServer, "Failed to get target state for Endpoint 3"));

    VerifyOrReturn(!ep1CurrentState.IsNull(),
                   ChipLogError(AppServer, "MoveToCommand failed due to Null value Current state on Endpoint 1"));
    VerifyOrReturn(!ep2CurrentState.IsNull(),
                   ChipLogError(AppServer, "MoveToCommand failed due to Null value Current state on Endpoint 2"));
    VerifyOrReturn(!ep3CurrentState.IsNull(),
                   ChipLogError(AppServer, "MoveToCommand failed due to Null value Current state on Endpoint 3"));

    VerifyOrReturn(!ep1TargetState.IsNull(),
                   ChipLogError(AppServer, "MoveToCommand failed due to Null value Target state on Endpoint 1"));
    VerifyOrReturn(!ep2TargetState.IsNull(),
                   ChipLogError(AppServer, "MoveToCommand failed due to Null value Target state on Endpoint 2"));
    VerifyOrReturn(!ep3TargetState.IsNull(),
                   ChipLogError(AppServer, "MoveToCommand failed due to Null value Target state on Endpoint 3"));

    // check if closure (endpoint 1) need unlatch before starting the motion action if Latching feature is supported.
    if (mClosureEndpoint1.GetLogic().GetConformance().HasFeature(ClosureControl::Feature::kMotionLatching))
    {
        if (ep1CurrentState.Value().latch.HasValue() && !ep1CurrentState.Value().latch.Value().IsNull() &&
            ep1TargetState.Value().latch.HasValue() && !ep1TargetState.Value().latch.Value().IsNull())
        {
            // If currently latched (true) and target is unlatched (false), unlatch first before moving
            if (ep1CurrentState.Value().latch.Value().Value() && !ep1TargetState.Value().latch.Value().Value())
            {
                // In Real application, this would be replaced with actual unlatch logic.
                ChipLogProgress(AppServer, "Performing unlatch action");
                ep1CurrentState.Value().latch.SetValue(DataModel::MakeNullable(false));
                ep1CurrentState.Value().secureState.SetNonNull(false);
                TEMPORARY_RETURN_IGNORED instance.mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1CurrentState);
                ep2CurrentState.Value().latch.SetValue(DataModel::MakeNullable(false));
                TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState);
                ep3CurrentState.Value().latch.SetValue(DataModel::MakeNullable(false));
                TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState);
                ChipLogProgress(AppServer, "Unlatched action completed");
            }
        }
    }

    // Once Closure is unlatched, we can proceed with the motion action for endpoints 2 and 3.
    DataModel::Nullable<chip::Percent100ths> ep2NextPosition = DataModel::NullNullable;
    DataModel::Nullable<chip::Percent100ths> ep3NextPosition = DataModel::NullNullable;

    bool isEndPoint2ProgressPossible = false;
    bool isEndPoint3ProgressPossible = false;

    // Get the Next Current State to be set for the endpoint 2, if target postion is not reached.
    if (GetPanelNextPosition(ep2CurrentState.Value(), ep2TargetState.Value(), ep2NextPosition))
    {
        VerifyOrReturn(!ep2NextPosition.IsNull(), ChipLogError(AppServer, "Failed to get next position for Endpoint 2"));
        ep2CurrentState.Value().position.SetValue(DataModel::MakeNullable(ep2NextPosition.Value()));
        TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState);
        isEndPoint2ProgressPossible = (ep2NextPosition.Value() != ep2TargetState.Value().position.Value().Value());
        ChipLogProgress(AppServer, "EndPoint 2 Current Position: %d, Target Position: %d", ep2NextPosition.Value(),
                        ep2TargetState.Value().position.Value().Value());
    }

    // Get the Next Current State to be set for the endpoint 3, if target postion is not reached.
    if (GetPanelNextPosition(ep3CurrentState.Value(), ep3TargetState.Value(), ep3NextPosition))
    {
        VerifyOrReturn(!ep3NextPosition.IsNull(), ChipLogError(AppServer, "Failed to get next position for Endpoint 3"));
        ep3CurrentState.Value().position.SetValue(DataModel::MakeNullable(ep3NextPosition.Value()));
        TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState);
        isEndPoint3ProgressPossible = (ep3NextPosition.Value() != ep3TargetState.Value().position.Value().Value());
        ChipLogProgress(AppServer, "EndPoint 3 Current Position: %d, Target Position: %d", ep3NextPosition.Value(),
                        ep3TargetState.Value().position.Value().Value());
    }

    // Check if both endpoints have reached their target positions
    // If both endpoints have reached their target positions, we can consider the closure motion action as complete.
    // If either endpoint has not reached its target position, we will continue the motion action
    // and set the closureTargetReached flag to false.
    // This will ensure that the closure motion action continues until both endpoints have reached their target positions.
    bool isProgressPossible = isEndPoint2ProgressPossible || isEndPoint3ProgressPossible;

    ChipLogProgress(AppServer, "Motion progress possible: %s", isProgressPossible ? "true" : "false");

    // If the closure target is not reached, we will reschedule the timer for motion action
    if (isProgressPossible)
    {
        mEp1CurrentAction    = ClosureAction::kMoveToAction;
        mEp1MotionInProgress = true;
        TEMPORARY_RETURN_IGNORED DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kMotionCountdownTimeMs),
                                                                       HandleEp1ClosureActionTimer, this);
        ChipLogProgress(AppServer, "Rescheduled HandleEp1ClosureActionTimer for motion action");
        return;
    }

    // If both endpoints have reached their target positions, we can consider the closure motion action as complete.
    // Before calling HandleClosureActionComplete, we need to check if a latch action is needed.
    if (mClosureEndpoint1.GetLogic().GetConformance().HasFeature(ClosureControl::Feature::kMotionLatching))
    {
        if (ep1CurrentState.Value().latch.HasValue() && !ep1CurrentState.Value().latch.Value().IsNull() &&
            ep1TargetState.Value().latch.HasValue() && !ep1TargetState.Value().latch.Value().IsNull())
        {
            // If currently latched (false) and target is unlatched (true), unlatch first before moving
            if (!ep1CurrentState.Value().latch.Value().Value() && ep1TargetState.Value().latch.Value().Value())
            {
                // In Real application, this would be replaced with actual latch logic.
                ChipLogProgress(AppServer, "Performing latch action");
                ep1CurrentState.Value().latch.SetValue(DataModel::MakeNullable(true));
                if (ep1CurrentState.Value().position.HasValue() && !ep1CurrentState.Value().position.Value().IsNull())
                {
                    if (ep1CurrentState.Value().position.Value().Value() == CurrentPositionEnum::kFullyClosed)
                    {
                        ep1CurrentState.Value().secureState.SetNonNull(true);
                    }
                    else
                    {
                        ep1CurrentState.Value().secureState.SetNonNull(false);
                    }
                }
                TEMPORARY_RETURN_IGNORED instance.mClosureEndpoint1.GetLogic().SetOverallCurrentState(ep1CurrentState);
                ep2CurrentState.Value().latch.SetValue(DataModel::MakeNullable(true));
                TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint2.GetLogic().SetCurrentState(ep2CurrentState);
                ep3CurrentState.Value().latch.SetValue(DataModel::MakeNullable(true));
                TEMPORARY_RETURN_IGNORED instance.mClosurePanelEndpoint3.GetLogic().SetCurrentState(ep3CurrentState);
                ChipLogProgress(AppServer, "latched action complete");
            }
        }
    }

    // Target reached, call HandleMoveToActionComplete
    instance.HandleMoveToActionComplete();
}

bool ClosureManager::GetPanelNextPosition(const GenericDimensionStateStruct & currentState,
                                          const GenericDimensionStateStruct & targetState,
                                          DataModel::Nullable<chip::Percent100ths> & nextPosition)
{
    VerifyOrReturnValue(targetState.position.HasValue() && !targetState.position.Value().IsNull(), false,
                        ChipLogError(AppServer, "Updating CurrentState to NextPosition failed due to Target position is not set"));

    VerifyOrReturnValue(currentState.position.HasValue() && !currentState.position.Value().IsNull(), false,
                        ChipLogError(AppServer, "Updating CurrentState to NextPosition failed due to Current position is not set"));

    chip::Percent100ths currentPosition = currentState.position.Value().Value();
    chip::Percent100ths targetPosition  = targetState.position.Value().Value();

    if (currentPosition < targetPosition)
    {
        // Increment position by 2000 units, capped at target.
        // No overflow handling needed due to currentposition max value is 10000
        nextPosition.SetNonNull(std::min(static_cast<chip::Percent100ths>(currentPosition + kMotionPositionStep), targetPosition));
    }
    else if (currentPosition > targetPosition)
    {
        // Handling underflow for CurrentPosition
        chip::Percent100ths newCurrentPosition =
            (currentPosition > kMotionPositionStep) ? currentPosition - kMotionPositionStep : 0;
        // Moving down: Decreasing the current position by a step of 2000 units,
        // ensuring it does not go below the target position.
        nextPosition.SetNonNull(std::max(newCurrentPosition, targetPosition));
    }
    else
    {
        // Already at target: No further action is needed as the current position matches the target position.
        nextPosition.SetNonNull(currentPosition);
        return false; // No update needed
    }
    return true;
}

ClosureDimensionEndpoint * ClosureManager::GetCurrentPanelInstance(EndpointId endpointId)
{
    ClosureManager & instance = ClosureManager::GetInstance();
    if (endpointId == instance.mClosurePanelEndpoint2.GetEndpointId())
    {
        return &instance.mClosurePanelEndpoint2;
    }
    if (endpointId == instance.mClosurePanelEndpoint3.GetEndpointId())
    {
        return &instance.mClosurePanelEndpoint3;
    }
    return nullptr;
}

void ClosureManager::HandleCalibrateActionComplete()
{
    ChipLogProgress(AppServer, "HandleCalibrateActionComplete called");

    mClosureEndpoint1.OnCalibrateActionComplete();
    mClosurePanelEndpoint2.OnCalibrateActionComplete();
    mClosurePanelEndpoint3.OnCalibrateActionComplete();
    mIsCalibrationActionInProgress = false;
    mEp1CurrentAction              = ClosureAction::kInvalidAction;
}

void ClosureManager::HandleStopActionComplete()
{
    ChipLogProgress(AppServer, "HandleStopActionComplete called");
    if (mIsCalibrationActionInProgress)
    {
        ChipLogDetail(AppServer, "Stopping calibration action");
        mClosureEndpoint1.OnStopCalibrateActionComplete();
        mClosurePanelEndpoint2.OnStopCalibrateActionComplete();
        mClosurePanelEndpoint3.OnStopCalibrateActionComplete();
        mIsCalibrationActionInProgress = false;
    }
    else if (mEp1MotionInProgress)
    {
        ChipLogDetail(AppServer, "Stopping move to action");
        mClosureEndpoint1.OnStopMotionActionComplete();
        mClosurePanelEndpoint2.OnStopMotionActionComplete();
        mClosurePanelEndpoint3.OnStopMotionActionComplete();
        mEp1MotionInProgress = false;
    }
    else
    {
        ChipLogDetail(AppServer, "No action in progress to stop");
    }
}

void ClosureManager::HandleMoveToActionComplete()
{
    ChipLogProgress(AppServer, "HandleMoveToActionComplete called");
    mClosureEndpoint1.OnMoveToActionComplete();
    mClosurePanelEndpoint2.OnMoveToActionComplete();
    mClosurePanelEndpoint3.OnMoveToActionComplete();
    mEp1MotionInProgress = false;
    mEp1CurrentAction    = ClosureAction::kInvalidAction;
}

void ClosureManager::HandlePanelSetTargetActionComplete(chip::EndpointId endpointId)
{
    ChipLogProgress(AppServer, "HandleSetTargetActionComplete called");

    ClosureManager & instance = ClosureManager::GetInstance();
    instance.mClosureEndpoint1.OnPanelMotionActionComplete();

    if (endpointId == instance.mClosurePanelEndpoint2.GetEndpointId())
    {
        instance.mClosurePanelEndpoint2.OnPanelMotionActionComplete();
        instance.mEp2CurrentAction    = ClosureAction::kInvalidAction;
        instance.mEp2MotionInProgress = false;
    }
    else if (endpointId == instance.mClosurePanelEndpoint3.GetEndpointId())
    {
        instance.mClosurePanelEndpoint3.OnPanelMotionActionComplete();
        instance.mEp3CurrentAction    = ClosureAction::kInvalidAction;
        instance.mEp3MotionInProgress = false;
    }
    else
    {
        ChipLogError(AppServer, "Invalid endpoint ID for SetTarget command: %d", endpointId);
        return;
    }

    ChipLogProgress(AppServer, "SetTarget action completed for Endpoint %d", endpointId);
}

void ClosureManager::HandlePanelStepActionComplete(chip::EndpointId endpointId)
{
    ChipLogProgress(AppServer, "HandleStepActionComplete called");

    ClosureManager & instance = ClosureManager::GetInstance();
    instance.mClosureEndpoint1.OnPanelMotionActionComplete();
    if (endpointId == instance.mClosurePanelEndpoint2.GetEndpointId())
    {
        instance.mClosurePanelEndpoint2.OnPanelMotionActionComplete();
        instance.mEp2CurrentAction    = ClosureAction::kInvalidAction;
        instance.mEp2MotionInProgress = false;
    }
    else if (endpointId == instance.mClosurePanelEndpoint3.GetEndpointId())
    {
        instance.mClosurePanelEndpoint3.OnPanelMotionActionComplete();
        instance.mEp3CurrentAction    = ClosureAction::kInvalidAction;
        instance.mEp3MotionInProgress = false;
    }
    else
    {
        ChipLogError(AppServer, "Invalid endpoint ID for Step command: %d", endpointId);
        return;
    }

    ChipLogProgress(AppServer, "Step action completed for Endpoint %d", endpointId);
}
