import { FunctionRuntimeTemplate, MappingTemplateProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { BackedDataSource, BaseDataSource, CfnFunctionConfiguration } from 'aws-cdk-lib/aws-appsync';
import { Construct } from 'constructs';
import { InlineTemplate } from './cdk-compat/template-asset';
import { GraphQLApi } from './graphql-api';
import { setResourceName } from './utils';
import { getRuntimeSpecificFunctionProps } from './utils/function-runtime';

export interface BaseFunctionConfigurationProps {
  readonly description?: string;

  /**
   * The mapping template for this resolver.
   * Either a VTL template or a JS template.
   */
  readonly mappingTemplate: FunctionRuntimeTemplate;
}

/**
 * Additional properties for an AppSync resolver like GraphQL API reference and datasource
 */
export interface FunctionConfigurationProps extends BaseFunctionConfigurationProps {
  /**
   * The API this resolver is attached to
   */
  readonly api: GraphQLApi;
  /**
   * The data source this resolver is using
   *
   * @default - No datasource
   */
  readonly dataSource: BaseDataSource | string;

  /**
   * Describes a runtime used by an AWS AppSync resolver or AWS AppSync function.
   *
   * Specifies the name and version of the runtime to use. Note that if a runtime is specified, code must also be specified.
   *
   * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-functionconfiguration.html#cfn-appsync-functionconfiguration-runtime
   */
  readonly runtime: CfnFunctionConfiguration.AppSyncRuntimeProperty | undefined;
}

export class AppSyncFunctionConfiguration extends Construct {
  /**
   * the ARN of the resolver
   */
  public readonly arn: string;

  public readonly functionId: string;

  private function: CfnFunctionConfiguration;

  constructor(scope: Construct, id: string, props: FunctionConfigurationProps) {
    super(scope, id);

    const runtimeSpecificProps = getRuntimeSpecificFunctionProps(this, props);
    this.function = new CfnFunctionConfiguration(this, `${id}.AppSyncFunction`, {
      name: id,
      apiId: props.api.apiId,
      functionVersion: '2018-05-29',
      description: props.description,
      dataSourceName: props.dataSource instanceof BaseDataSource ? props.dataSource.ds.attrName : props.dataSource,
      ...runtimeSpecificProps,
    });
    setResourceName(this.function, { name: id });
    props.api.addSchemaDependency(this.function);
    if (props.dataSource instanceof BackedDataSource) {
      this.function.addDependency(props.dataSource?.ds);
    }
    this.arn = this.function.attrFunctionArn;
    this.functionId = this.function.attrFunctionId;
  }
}
