import { LambdaClient, InvokeCommand, InvokeCommandOutput, InvocationType } from '@aws-sdk/client-lambda';

/**
 * Interface for the payload sent to the Lambda function.
 */
export interface InvokePayload {
  ipAddress: string;
  tag: string;
}

/**
 * Interface for the Lambda function's response.
 */
export interface LambdaResponse<T = any> {
  statusCode: number;
  body: T;
}

/**
 * Creates a LambdaClient with the specified region and profile.
 *
 * @param region - AWS region.
 * @param profile - AWS profile name.
 * @returns Configured LambdaClient instance.
 */
export const createLambdaClient = (region: string, profile?: string): LambdaClient => {
  const { fromIni } = require('@aws-sdk/credential-providers');

  const clientConfig: any = { region };

  if (profile) {
    clientConfig.credentials = fromIni({ profile });
  }

  return new LambdaClient(clientConfig);
};

/**
 * Invokes an AWS Lambda function with the given payload.
 *
 * @param lambdaClient - An instance of LambdaClient.
 * @param functionName - The name of the Lambda function to invoke.
 * @param payload - The payload to send to the Lambda function.
 * @param invocationType - The type of invocation (default is 'RequestResponse').
 * @returns The response from the Lambda function.
 */
export const invokeLambda = async <T = any>(
  lambdaClient: LambdaClient,
  functionName: string,
  payload: InvokePayload,
  invocationType: InvocationType = 'RequestResponse'
): Promise<LambdaResponse<T>> => {
  const params = {
    FunctionName: functionName,
    Payload: Buffer.from(JSON.stringify(payload)),
    InvocationType: invocationType,
  };

  const command = new InvokeCommand(params);

  try {
    const response: InvokeCommandOutput = await lambdaClient.send(command);

    if (!response.Payload) {
      throw new Error('No payload returned from Lambda function.');
    }

    const payloadString = Buffer.from(response.Payload).toString('utf-8');
    const parsedPayload: LambdaResponse<T> = JSON.parse(payloadString);

    if (response.FunctionError) {
      console.error(`Lambda function error: ${response.FunctionError}`, parsedPayload);
      throw new Error(`Lambda function error: ${response.FunctionError}`);
    }

    console.log('Lambda response:', parsedPayload);
    return parsedPayload;
  } catch (error: any) {
    console.error('Error invoking Lambda function:', error.message || error);
    throw error;
  }
};
