import * as plugins from './plugins.js';
import { TypedResponseError } from './classes.typedresponseerror.js';
import { TypedTools } from './classes.typedtools.js';

export type THandlerFunction<T extends plugins.typedRequestInterfaces.ITypedRequest> = (
  requestArg: T['request'],
  typedToolsArg?: TypedTools
) => Promise<T['response']>;

/**
 * typed handler for dealing with typed requests
 */
export class TypedHandler<T extends plugins.typedRequestInterfaces.ITypedRequest> {
  public method: string;
  private handlerFunction: THandlerFunction<T>;

  constructor(methodArg: T['method'], handlerFunctionArg: THandlerFunction<T>) {
    this.method = methodArg;
    this.handlerFunction = handlerFunctionArg;
  }

  /**
   * adds a response to the typedRequest
   * @param typedRequestArg
   */
  public async addResponse(typedRequestArg: T) {
    if (typedRequestArg.method !== this.method) {
      throw new Error(
        'this handler has been given a wrong method to answer to. Please use a TypedRouter to filter requests'
      );
    }
    let typedResponseError: TypedResponseError;
    const typedtoolsInstance = new TypedTools();
    const response = await this.handlerFunction(typedRequestArg.request, typedtoolsInstance).catch((e) => {
      if (e instanceof TypedResponseError) {
        typedResponseError = e;
      } else {
        console.log(e);
      }
    });

    if (typedResponseError) {
      typedRequestArg.error = {
        text: typedResponseError.errorText,
        data: typedResponseError.errorData,
      };
    }

    if (response) {
      typedRequestArg.response = response;
    }

    typedRequestArg?.correlation?.phase ? (typedRequestArg.correlation.phase = 'response') : null;

    return typedRequestArg;
  }
}