/**
 * Standalone type validation functions extracted from validationUtils.js.
 */

function validateNumber(configValue, rules, fieldSchema, name, key, logger) {
    if (typeof configValue !== "number") {
        const parsedValue = parseFloat(configValue);
        if (!isNaN(parsedValue)) {
            logger.warn(`${name}.${key} was parsed to a number: ${configValue} -> ${parsedValue}`);
            configValue = parsedValue;
        }
    }
    if (rules.min !== undefined && configValue < rules.min) {
        logger.warn(`${name}.${key} is below the minimum (${rules.min}). Using default value.`);
        return fieldSchema.default;
    }
    if (rules.max !== undefined && configValue > rules.max) {
        logger.warn(`${name}.${key} exceeds the maximum (${rules.max}). Using default value.`);
        return fieldSchema.default;
    }
    logger.debug(`${name}.${key} is a valid number: ${configValue}`);
    return configValue;
}

function validateInteger(configValue, rules, fieldSchema, name, key, logger) {
    if (typeof configValue !== "number" || !Number.isInteger(configValue)) {
        const parsedValue = parseInt(configValue, 10);
        if (!isNaN(parsedValue) && Number.isInteger(parsedValue)) {
            logger.warn(`${name}.${key} was parsed to an integer: ${configValue} -> ${parsedValue}`);
            configValue = parsedValue;
        } else {
            logger.warn(`${name}.${key} is not a valid integer. Using default value.`);
            return fieldSchema.default;
        }
    }
    if (rules.min !== undefined && configValue < rules.min) {
        logger.warn(`${name}.${key} is below the minimum integer value (${rules.min}). Using default value.`);
        return fieldSchema.default;
    }
    if (rules.max !== undefined && configValue > rules.max) {
        logger.warn(`${name}.${key} exceeds the maximum integer value (${rules.max}). Using default value.`);
        return fieldSchema.default;
    }
    logger.debug(`${name}.${key} is a valid integer: ${configValue}`);
    return configValue;
}

function validateBoolean(configValue, name, key, logger) {
    if (typeof configValue !== "boolean") {
        if (configValue === "true" || configValue === "false") {
            const parsedValue = configValue === "true";
            logger.debug(`${name}.${key} was parsed to a boolean: ${configValue} -> ${parsedValue}`);
            configValue = parsedValue;
        }
    }
    return configValue;
}

function _isUnitLikeField(path) {
    const normalized = String(path || "").toLowerCase();
    if (!normalized) return false;
    return /(^|\.)([a-z0-9]*unit|units)(\.|$)/.test(normalized)
        || normalized.includes(".curveunits.");
}

function _resolveStringNormalizeMode(path) {
    const normalized = String(path || "").toLowerCase();
    if (!normalized) return "none";

    if (_isUnitLikeField(normalized)) return "none";
    if (normalized.endsWith(".name")) return "none";
    if (normalized.endsWith(".model")) return "none";
    if (normalized.endsWith(".supplier")) return "none";
    if (normalized.endsWith(".role")) return "none";
    if (normalized.endsWith(".description")) return "none";

    if (normalized.endsWith(".softwaretype")) return "lowercase";
    if (normalized.endsWith(".type")) return "lowercase";
    if (normalized.endsWith(".category")) return "lowercase";

    return "lowercase";
}

function validateString(configValue, rules, fieldSchema, name, key, logger) {
    let newConfigValue = configValue;

    if (typeof configValue !== "string") {
        //check if the value is nullable
        if(rules.nullable){
            if(configValue === null){
                return null;
            }
        }

        logger.warn(`${name}.${key} is not a string. Trying to convert to string.`);
        newConfigValue = String(configValue); // Coerce to string if not already
    }

    //check if the string is a valid string after conversion
    if (typeof newConfigValue !== "string") {
        logger.warn(`${name}.${key} is not a valid string. Using default value.`);
        return fieldSchema.default;
    }

    const keyString = `${name}.${key}`;
    const normalizeMode = rules.normalize || _resolveStringNormalizeMode(keyString);
    const preserveCase = normalizeMode !== "lowercase";

    // Check for uppercase characters and convert to lowercase if present
    if (!preserveCase && newConfigValue !== newConfigValue.toLowerCase()) {
        logger.info(
            `${name}.${key} normalized to lowercase: ${newConfigValue} -> ${newConfigValue.toLowerCase()}`
        );
        newConfigValue = newConfigValue.toLowerCase();
    }

    return newConfigValue;
}

function validateEnum(configValue, rules, fieldSchema, name, key, logger) {
    if (Array.isArray(rules.values)) {
        //if value is null take default
        if(configValue === null){
            logger.warn(`${name}.${key} is null. Using default value.`);
            return fieldSchema.default;
        }

        if (typeof configValue !== "string") {
            logger.warn(`${name}.${key} is not a valid enum string. Using default value.`);
            return fieldSchema.default;
        }

        const validValues = rules.values.map(e => e.value.toLowerCase());

        //remove caps
        configValue = configValue.toLowerCase();
        if (!validValues.includes(configValue)) {
            logger.warn(
                `${name}.${key} has an invalid value : ${configValue}. Allowed values: [${validValues.join(", ")}]. Using default value.`
            );
            return fieldSchema.default;
        }
    } else {
        logger.warn(
            `${name}.${key} is an enum with no 'values' array. Using default value.`
        );
        return fieldSchema.default;
    }
    return configValue;
}

module.exports = {
    validateNumber,
    validateInteger,
    validateBoolean,
    validateString,
    validateEnum,
};
