// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
//
// SPDX-License-Identifier: Apache-2.0

import type { IMessageEndpointDefinition } from '@interfaces/api/MessageEndpointDefinition.js';
import { METADATA_MESSAGE_ENDPOINTS } from '@interfaces/api/metadata.js';
import type { CallAction } from '@ocpp/rpc/message.js';

/**
 * Decorator for use in module API class to expose methods as REST OCPP message endpoints.
 *
 * @param {CallAction} action - The call action.
 * @param {object} bodySchema - The body schema.
 * @param {Record<string, any>} optionalQuerystrings - The optional querystrings.
 * @return {void} This function does not return anything.
 */
export const AsMessageEndpoint = function (
  action: CallAction,
  bodySchema: object | ((instance: any) => object),
  optionalQuerystrings?: Record<string, any>,
) {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor): void => {
    if (!Reflect.hasMetadata(METADATA_MESSAGE_ENDPOINTS, target.constructor)) {
      Reflect.defineMetadata(
        METADATA_MESSAGE_ENDPOINTS,
        new Array<IMessageEndpointDefinition>(),
        target.constructor,
      );
    }
    const messageEndpoints = Reflect.getMetadata(
      METADATA_MESSAGE_ENDPOINTS,
      target.constructor,
    ) as Array<IMessageEndpointDefinition>;
    messageEndpoints.push({
      action: action,
      method: descriptor.value,
      methodName: propertyKey,
      bodySchema: bodySchema,
      optionalQuerystrings: optionalQuerystrings,
    });
    Reflect.defineMetadata(METADATA_MESSAGE_ENDPOINTS, messageEndpoints, target.constructor);
  };
};
