/*
 *    Copyright (c) 2026 Project CHIP Authors
 *
 *    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 <app/persistence/AttributePersistenceMigration.h>
#include <lib/core/CHIPEncoding.h>
#include <lib/support/logging/CHIPLogging.h>
#include <nlbyteorder.h>

#include <cstring>

namespace {

using namespace ::chip;
using namespace chip::app;

/**
 * Validates that the given size is a supported scalar width (1, 2, 4, or 8 bytes).
 * On big-endian systems, also performs an in-place little-endian to host byte-order swap.
 * On little-endian systems, no swap is needed so only the size validation is performed.
 */
CHIP_ERROR HostSwapBySize(uint8_t * data, size_t size)
{
    switch (size)
    {
#if (NLBYTEORDER == NLBYTEORDER_BIG_ENDIAN)
    case 1:
        // Single byte, no swap needed.
        return CHIP_NO_ERROR;
    case 2: {
        uint16_t val;
        memcpy(&val, data, sizeof(val));
        val = chip::Encoding::LittleEndian::HostSwap16(val);
        memcpy(data, &val, sizeof(val));
        return CHIP_NO_ERROR;
    }
    case 4: {
        uint32_t val;
        memcpy(&val, data, sizeof(val));
        val = chip::Encoding::LittleEndian::HostSwap32(val);
        memcpy(data, &val, sizeof(val));
        return CHIP_NO_ERROR;
    }
    case 8: {
        uint64_t val;
        memcpy(&val, data, sizeof(val));
        val = chip::Encoding::LittleEndian::HostSwap64(val);
        memcpy(data, &val, sizeof(val));
        return CHIP_NO_ERROR;
    }
#else
    case 1:
    case 2:
    case 4:
    case 8:
        return CHIP_NO_ERROR;
#endif
    default:
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
}

CHIP_ERROR MigrateValueFromSafe(const ConcreteAttributePath & attrPath, SafeAttributePersistenceProvider & provider,
                                MutableByteSpan & buffer, size_t valueSize, bool isScalar)
{

    VerifyOrReturnError(valueSize <= buffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL);

#if (NLBYTEORDER == NLBYTEORDER_LITTLE_ENDIAN)
    // On little-endian systems, no byte swap is needed for scalar values.
    // Read directly into the output buffer and validate the size.
    ReturnErrorOnFailure(provider.SafeReadValue(attrPath, buffer));
    // For scalar values in LE the function HostSwapBySize just checks that a valid size was provided.
    if (isScalar)
    {
        VerifyOrReturnError(buffer.size() == valueSize, CHIP_ERROR_INCORRECT_STATE);
        ReturnErrorOnFailure(HostSwapBySize(buffer.data(), valueSize));
    }
    else
    {
        VerifyOrReturnError(buffer.size() <= valueSize, CHIP_ERROR_INCORRECT_STATE);
    }
#else

    // On big-endian, no need to swap non-scalar values.
    // For non-scalar values, just return the raw data.
    if (!isScalar)
    {
        ReturnErrorOnFailure(provider.SafeReadValue(attrPath, buffer));
        return buffer.size() <= valueSize ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE;
    }

    // For scalar values, read into a temp buffer, byte-swap, then copy out.
    uint8_t attrData[sizeof(uint64_t)];
    MutableByteSpan tempVal(attrData);

    ReturnErrorOnFailure(provider.SafeReadValue(attrPath, tempVal));
    VerifyOrReturnError(tempVal.size() == valueSize, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(HostSwapBySize(tempVal.data(), valueSize));
    memcpy(buffer.data(), tempVal.data(), valueSize);
    buffer.reduce_size(valueSize);
#endif
    return CHIP_NO_ERROR;
}
} // namespace
namespace chip::app {

CHIP_ERROR MigrateFromSafeToAttributePersistenceProvider(SafeAttributePersistenceProvider & safeProvider,
                                                         AttributePersistenceProvider & dstProvider,
                                                         const ConcreteClusterPath & cluster,
                                                         Span<const AttrMigrationData> attributes, MutableByteSpan buffer)
{
    bool hadMigrationErrors = false;
    ConcreteAttributePath attrPath;

    for (const auto & entry : attributes)
    {
        attrPath = ConcreteAttributePath(cluster.mEndpointId, cluster.mClusterId, entry.attributeId);

        // Create a copy of the buffer to check if the value is already in the AttributePersistence.
        // If the attribute value is already stored in AttributePersistence, skip it.
        // Note: we assume any other error (e.g. including buffer too small) to be an indication that
        //       the key exists. The only case we migrate is if we are explicitly told "not found".
        MutableByteSpan readAttrBuffer = buffer;
        if (dstProvider.ReadValue(attrPath, readAttrBuffer) != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
        {
            continue;
        }

        // We make a copy of the buffer so it can be resized
        // Still refers to same internal buffer though
        // Read value from the safe provider, will resize copyOfBuffer to read size
        MutableByteSpan copyOfBuffer = buffer;
        // If there was an error reading from SafeAttributePersistence, then we shouldn't try to write that value
        // to AttributePersistence
        ChipError attributeMigrationError =
            MigrateValueFromSafe(attrPath, safeProvider, copyOfBuffer, entry.valueSize, entry.isScalar);
        if (attributeMigrationError != CHIP_NO_ERROR)
        {
            // If the value was not found in SafeAttributePersistence, it means that it was already migrated or that
            // there wasn't a value stored for this attribute in the first place, so we skip it.
            if (attributeMigrationError != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
            {
                hadMigrationErrors = true;
                ChipLogError(DataManagement,
                             "AttributeMigration: Error reading SafeAttribute '" ChipLogFormatMEI
                             "' from cluster '" ChipLogFormatMEI "' (err=%" CHIP_ERROR_FORMAT ")",
                             ChipLogValueMEI(entry.attributeId), ChipLogValueMEI(cluster.mClusterId),
                             attributeMigrationError.Format());
            }
            continue;
        }

        // Delete from the safe provider immediately after a successful read, so we only try to
        // migrate the persisted values once and avoid re-migrating after a reset.
        attributeMigrationError = safeProvider.SafeDeleteValue(attrPath);
        if (attributeMigrationError != CHIP_NO_ERROR)
        {
            hadMigrationErrors = true;
            ChipLogError(DataManagement,
                         "AttributeMigration: Error deleting SafeAttribute '" ChipLogFormatMEI "' from cluster '" ChipLogFormatMEI
                         "' (err=%" CHIP_ERROR_FORMAT ")",
                         ChipLogValueMEI(entry.attributeId), ChipLogValueMEI(cluster.mClusterId), attributeMigrationError.Format());
        }

        // Write value from SafeAttributePersistence into AttributePersistence
        attributeMigrationError = dstProvider.WriteValue(attrPath, copyOfBuffer);
        if (attributeMigrationError != CHIP_NO_ERROR)
        {
            hadMigrationErrors = true;
            ChipLogError(DataManagement,
                         "AttributeMigration: Error writing Attribute '" ChipLogFormatMEI "' from cluster '" ChipLogFormatMEI
                         "' (err=%" CHIP_ERROR_FORMAT ")",
                         ChipLogValueMEI(entry.attributeId), ChipLogValueMEI(cluster.mClusterId), attributeMigrationError.Format());
        }
    }
    return hadMigrationErrors ? CHIP_ERROR_HAD_FAILURES : CHIP_NO_ERROR;
}
} // namespace chip::app
