/*
 *
 *    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 "chef-pump.h"
#include "DeviceTypes.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/clusters/flow-measurement-server/CodegenIntegration.h>
#include <app/clusters/pressure-measurement-server/CodegenIntegration.h>
#include <app/clusters/temperature-measurement-server/CodegenIntegration.h>
#include <app/reporting/reporting.h>
#include <app/util/attribute-storage.h>
#include <app/util/endpoint-config-api.h>
#include <devices/Types.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using chip::Protocols::InteractionModel::Status;

namespace chef {
namespace pump {

namespace {

constexpr size_t kTemperatureMeasurementCount = MATTER_DM_TEMPERATURE_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT;
DataModel::Nullable<int16_t> TemperatureRangeMin[kTemperatureMeasurementCount];
DataModel::Nullable<int16_t> TemperatureRangeMax[kTemperatureMeasurementCount];
uint16_t getIndexTemperatureMeasurement(EndpointId endpointId)
{
    return emberAfGetClusterServerEndpointIndex(endpointId, TemperatureMeasurement::Id, kTemperatureMeasurementCount);
}
int16_t kDefaultMinTemperature = 100;
int16_t kDefaultMaxTemperature = 9000;

constexpr size_t kPressureMeasurementCount = MATTER_DM_PRESSURE_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT;
DataModel::Nullable<int16_t> PressureRangeMin[kPressureMeasurementCount];
DataModel::Nullable<int16_t> PressureRangeMax[kPressureMeasurementCount];
uint16_t getIndexPressureMeasurement(EndpointId endpointId)
{
    return emberAfGetClusterServerEndpointIndex(endpointId, PressureMeasurement::Id, kPressureMeasurementCount);
}
int16_t kDefaultMinPressure = 30;
int16_t kDefaultMaxPressure = 10000;

constexpr size_t kFlowMeasurementCount = MATTER_DM_FLOW_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT;
DataModel::Nullable<uint16_t> FlowRangeMin[kFlowMeasurementCount];
DataModel::Nullable<uint16_t> FlowRangeMax[kFlowMeasurementCount];
uint16_t getIndexFlowMeasurement(EndpointId endpointId)
{
    return emberAfGetClusterServerEndpointIndex(endpointId, FlowMeasurement::Id, kFlowMeasurementCount);
}
uint16_t kDefaultMinFlow = 1;
uint16_t kDefaultMaxFlow = 10;

int16_t kMinCapacity = 0;
int16_t kMaxCapacity = 100;

/**
 * @brief Sets all setpoints to Max if state is On else NULL.
 */
void updateSetPointsOnOff(EndpointId endpointId, bool onOff)
{
    uint16_t epIndex;

    epIndex = getIndexTemperatureMeasurement(endpointId);
    if (epIndex < kTemperatureMeasurementCount)
    {
        auto updatedTemperature = onOff ? TemperatureRangeMax[epIndex] : chip::app::DataModel::Nullable<int16_t>(0);
        LogErrorOnFailure(TemperatureMeasurement::SetMeasuredValue(endpointId, updatedTemperature));

        MatterReportingAttributeChangeCallback(endpointId, TemperatureMeasurement::Id,
                                               TemperatureMeasurement::Attributes::MeasuredValue::Id);
    }

    epIndex = getIndexPressureMeasurement(endpointId);
    if (epIndex < kPressureMeasurementCount)
    {
        // Use null when off: spec says null indicates unknown measurement, and 0 may violate MinMeasuredValue constraint.
        auto updatedPressure = onOff ? PressureRangeMax[epIndex] : DataModel::Nullable<int16_t>();
        LogErrorOnFailure(PressureMeasurement::SetMeasuredValue(endpointId, updatedPressure));
    }

    epIndex = getIndexFlowMeasurement(endpointId);
    if (epIndex < kFlowMeasurementCount)
    {
        // Use null when off: spec says null indicates unknown measurement, and 0 may violate MinMeasuredValue constraint.
        auto updatedFlow = onOff ? FlowRangeMax[epIndex] : DataModel::Nullable<uint16_t>();
        LogErrorOnFailure(FlowMeasurement::SetMeasuredValue(endpointId, updatedFlow));
    }

    DataModel::Nullable<int16_t> capacity = onOff ? DataModel::Nullable<int16_t>(kMaxCapacity) : DataModel::Nullable<int16_t>(0);
    PumpConfigurationAndControl::Attributes::Capacity::Set(endpointId, capacity);
    MatterReportingAttributeChangeCallback(endpointId, PumpConfigurationAndControl::Id,
                                           PumpConfigurationAndControl::Attributes::Capacity::Id);
}

constexpr size_t kLevelControlCount = MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT;

uint16_t getIndexLevelControl(EndpointId endpointId)
{
    return emberAfGetClusterServerEndpointIndex(endpointId, LevelControl::Id, kLevelControlCount);
}
constexpr uint8_t kMinLevel  = 1;
constexpr uint8_t kMaxLevel  = 254;
constexpr uint8_t kNullLevel = 255;

/**
 * @brief Maps the level (from LevelControl) to a setpoint value within range.
 */
template <typename T>
DataModel::Nullable<T> LevelToSetpoint(DataModel::Nullable<uint8_t> level, DataModel::Nullable<T> RangeMin,
                                       DataModel::Nullable<T> RangeMax)
{
    if (level.IsNull() || level.Value() == kNullLevel || RangeMin.IsNull() || RangeMax.IsNull())
        return DataModel::NullNullable;

    if (!level.Value())
    {
        return DataModel::Nullable<T>(0);
    }

    return RangeMin.Value() + (RangeMax.Value() - RangeMin.Value()) * std::min(level.ValueOr(0), (uint8_t) 200) / 200;
}

/**
 * Updates setpoints based on the current level.
 */
void updateSetPointsLevel(EndpointId endpointId, DataModel::Nullable<uint8_t> level)
{
    uint16_t epIndex;

    epIndex = getIndexTemperatureMeasurement(endpointId);
    if (epIndex < kTemperatureMeasurementCount)
    {
        DataModel::Nullable<int16_t> updatedTemperature =
            LevelToSetpoint(level, TemperatureRangeMin[epIndex], TemperatureRangeMax[epIndex]);
        LogErrorOnFailure(TemperatureMeasurement::SetMeasuredValue(endpointId, updatedTemperature));

        MatterReportingAttributeChangeCallback(endpointId, TemperatureMeasurement::Id,
                                               TemperatureMeasurement::Attributes::MeasuredValue::Id);
    }

    epIndex = getIndexPressureMeasurement(endpointId);
    if (epIndex < kPressureMeasurementCount)
    {
        DataModel::Nullable<int16_t> updatedPressure = LevelToSetpoint(level, PressureRangeMin[epIndex], PressureRangeMax[epIndex]);
        LogErrorOnFailure(PressureMeasurement::SetMeasuredValue(endpointId, updatedPressure));
    }

    epIndex = getIndexFlowMeasurement(endpointId);
    if (epIndex < kFlowMeasurementCount)
    {
        DataModel::Nullable<uint16_t> updatedFlow = LevelToSetpoint(level, FlowRangeMin[epIndex], FlowRangeMax[epIndex]);
        LogErrorOnFailure(FlowMeasurement::SetMeasuredValue(endpointId, updatedFlow));
    }

    DataModel::Nullable<int16_t> capacity =
        LevelToSetpoint(level, DataModel::Nullable<int16_t>(kMinCapacity), DataModel::Nullable<int16_t>(kMaxCapacity));
    PumpConfigurationAndControl::Attributes::Capacity::Set(endpointId, capacity);
    MatterReportingAttributeChangeCallback(endpointId, PumpConfigurationAndControl::Id,
                                           PumpConfigurationAndControl::Attributes::Capacity::Id);
}

CHIP_ERROR setPumpStatus(EndpointId endpoint, uint16_t status)
{

    Status res = PumpConfigurationAndControl::Attributes::PumpStatus::Set(
        endpoint, BitMask<PumpConfigurationAndControl::PumpStatusBitmap>(status));
    VerifyOrReturnLogError(res == Status::Success, CHIP_ERROR_INTERNAL);
    MatterReportingAttributeChangeCallback(endpoint, PumpConfigurationAndControl::Id,
                                           PumpConfigurationAndControl::Attributes::PumpStatus::Id);
    return CHIP_NO_ERROR;
}
} // namespace

/**
 * @brief Post moveToLevel handler. Updates all setpoint values to match current level.
 */
void postMoveToLevel(EndpointId endpoint, uint8_t level)
{
    ChipLogDetail(DeviceLayer, "[chef-pump] Inside handleMoveToLevel. level = %d", level);

    bool pumpOn = false;
    OnOff::Attributes::OnOff::Get(endpoint, &pumpOn);

    if (!pumpOn)
    {
        ChipLogDetail(DeviceLayer, "[chef-pump] Pump is not on. Setpoints not updated.");
        return;
    }

    if (level && level != kNullLevel)
        updateSetPointsLevel(endpoint, DataModel::Nullable<uint8_t>(level));
    else
        updateSetPointsLevel(endpoint, DataModel::Nullable<uint8_t>(0));
}

/**
 * @brief Post onOff change handler. Matches setpoints to currentLevel when going from
 * off to on. Sets setpoints to NULL when going from On to Off.
 */
void postOnOff(EndpointId endpoint, bool value)
{
    ChipLogDetail(DeviceLayer, "[chef-pump] Inside postOnOff. value: %d", value);
    uint16_t epIndex = getIndexLevelControl(endpoint);
    if (epIndex < kLevelControlCount)
    {
        if (value) // Off to On
        {
            auto level = DataModel::Nullable<uint8_t>(kMaxLevel);
            LevelControl::Attributes::CurrentLevel::Get(endpoint, level);
            updateSetPointsLevel(endpoint, level);
        }
        else // On to Off
        {
            updateSetPointsLevel(endpoint, DataModel::Nullable<uint8_t>(0));
        }
    }
    else
    {
        updateSetPointsOnOff(endpoint, value);
    }

    BitMask<PumpConfigurationAndControl::PumpStatusBitmap> currentStatus;
    Status res = PumpConfigurationAndControl::Attributes::PumpStatus::Get(endpoint, &currentStatus);
    VerifyOrReturn(res == Status::Success, ChipLogError(DeviceLayer, "Failed to read pump status."));
    if (value)
    {
        if (!currentStatus.GetField(PumpConfigurationAndControl::PumpStatusBitmap::kRunning))
        {
            currentStatus.SetField(PumpConfigurationAndControl::PumpStatusBitmap::kRunning, 1);
            TEMPORARY_RETURN_IGNORED setPumpStatus(endpoint, currentStatus.Raw());
        }
    }
    else
    {
        if (currentStatus.GetField(PumpConfigurationAndControl::PumpStatusBitmap::kRunning))
        {
            currentStatus.SetField(PumpConfigurationAndControl::PumpStatusBitmap::kRunning, 0);
            TEMPORARY_RETURN_IGNORED setPumpStatus(endpoint, currentStatus.Raw());
        }
    }
}

void init()
{
    const uint16_t endpointCount = emberAfEndpointCount();

    for (uint16_t endpointIndex = 0; endpointIndex < endpointCount; endpointIndex++)
    {

        EndpointId endpointId = emberAfEndpointFromIndex(endpointIndex);
        if (endpointId == kInvalidEndpointId)
        {
            continue;
        }

        if (!chef::DeviceTypes::EndpointHasDeviceType(endpointId, Device::kPumpDeviceTypeId))
        {
            continue;
        }

        uint16_t epIndex;

        epIndex = getIndexTemperatureMeasurement(endpointId);
        if (epIndex < kTemperatureMeasurementCount)
        {
            DataModel::Nullable<int16_t> temp;
            CHIP_ERROR err = TemperatureMeasurement::SetMeasuredValue(endpointId, temp);
            VerifyOrDieWithMsg(err == CHIP_NO_ERROR, DeviceLayer,
                               "Failed to initialize Temperature Measured Value to NULL for Endpoint: %d", endpointId);
            if (TemperatureMeasurement::Attributes::MinMeasuredValue::GetDefault(endpointId, TemperatureRangeMin[epIndex]) !=
                    Status::Success ||
                TemperatureRangeMin[epIndex].IsNull())
            {
                TemperatureRangeMin[epIndex].SetNonNull(kDefaultMinTemperature);
            }
            if (TemperatureMeasurement::Attributes::MaxMeasuredValue::GetDefault(endpointId, TemperatureRangeMax[epIndex]) !=
                    Status::Success ||
                TemperatureRangeMax[epIndex].IsNull())
            {
                TemperatureRangeMax[epIndex].SetNonNull(kDefaultMaxTemperature);
            }
        }

        epIndex = getIndexPressureMeasurement(endpointId);
        if (epIndex < kPressureMeasurementCount)
        {
            VerifyOrDieWithMsg(PressureMeasurement::SetMeasuredValue(endpointId, DataModel::Nullable<int16_t>()) == CHIP_NO_ERROR,
                               DeviceLayer, "Failed to initialize Pressure Measured Value to NULL for Endpoint: %d", endpointId);
            if (PressureMeasurement::Attributes::MinMeasuredValue::GetDefault(endpointId, PressureRangeMin[epIndex]) !=
                    Status::Success ||
                PressureRangeMin[epIndex].IsNull())
            {
                PressureRangeMin[epIndex].SetNonNull(kDefaultMinPressure);
            }
            if (PressureMeasurement::Attributes::MaxMeasuredValue::GetDefault(endpointId, PressureRangeMax[epIndex]) !=
                    Status::Success ||
                PressureRangeMax[epIndex].IsNull())
            {
                PressureRangeMax[epIndex].SetNonNull(kDefaultMaxPressure);
            }
        }

        epIndex = getIndexFlowMeasurement(endpointId);
        if (epIndex < kFlowMeasurementCount)
        {
            VerifyOrDieWithMsg(FlowMeasurement::SetMeasuredValue(endpointId, DataModel::Nullable<uint16_t>()) == CHIP_NO_ERROR,
                               DeviceLayer, "Failed to initialize Flow Measured Value to NULL for Endpoint: %d", endpointId);
            if (FlowMeasurement::Attributes::MinMeasuredValue::GetDefault(endpointId, FlowRangeMin[epIndex]) != Status::Success ||
                FlowRangeMin[epIndex].IsNull())
            {
                FlowRangeMin[epIndex].SetNonNull(kDefaultMinFlow);
            }
            if (FlowMeasurement::Attributes::MaxMeasuredValue::GetDefault(endpointId, FlowRangeMax[epIndex]) != Status::Success ||
                FlowRangeMax[epIndex].IsNull())
            {
                FlowRangeMax[epIndex].SetNonNull(kDefaultMaxFlow);
            }
        }

        epIndex = getIndexLevelControl(endpointId);
        if (epIndex < kLevelControlCount)
        {
            VerifyOrDieWithMsg(LevelControl::Attributes::CurrentLevel::Set(endpointId, kMinLevel) == Status::Success, DeviceLayer,
                               "Failed to initialize Current Level to %d for Endpoint: %d", kMinLevel, endpointId);
        }

        VerifyOrDieWithMsg(OnOff::Attributes::OnOff::Set(endpointId, false) == Status::Success, DeviceLayer,
                           "Failed to initialize OnOff to false for Endpoint: %d", endpointId);
        updateSetPointsOnOff(endpointId, false);

        TEMPORARY_RETURN_IGNORED setPumpStatus(endpointId, 0);
    }
}

} // namespace pump
} // namespace chef
