/**
 * Copyright IBM Corp. 2024, 2025
 */

import { Variable as Variable_Ref } from '@apic/api-model/test/common/Variable.js';
import {
  Test_Environment as Environment_Ref,
  Test_Assertions,
  Test_Auth,
  Test_Auth_BasicAuth,
  Test_Headers,
  Test_Parameters,
  Test_Payload,
  Test_Request,
} from '@apic/api-model/test/Test.js';
// import { Metadata as Metadata_Ref } from '@apic/api-model/common/Metadata.js';
import { PolicySequence_Spec } from '@apic/api-model/policy/PolicySeq.js';
import { Assert } from '@apic/api-model/test/common/Assert.js';
import { Ref as Reference } from '@apic/api-model/common/Ref.js';
import { KindEnums } from '@apic/api-model/common/StudioEnums.js';
import { RefAndEndpoint } from '@apic/api-model/test/common/RefAndEndpoint.js';
import { PayLoadIdentifier } from '@apic/api-model/policy/common/PayLoadIdentifier.js';
import { CORS_Spec } from '@apic/api-model/policy/ResProcessing/CORS.js';
import { AuthorizeUser_Spec } from '@apic/api-model/policy/iam/AuthorizeUser.js';
import { Api } from '@apic/api-model/api/Api.js';
import { Xsl } from '@apic/api-model/policy/common/Xsl.js';

// type WithRequired<Type, Key extends keyof Type> = Type & {
//   [Property in Key]-?: Type[Property];
// };
export type Metadata = KindMetadata;
// WithRequired<Metadata_Ref, 'name' | 'version'>;
export interface KindMetadata {
  name: string;
  version: string;
  tags?: string[];
  namespace?: string;
  type?: string;
  description?: string;
  labels?: {
    gatewayTypes: string[];
  };
}
export type API_Spec_Ref = {
  $ref: string;
  $path: string;
};
export type Path = {
  path: string;
};

export type PolicySequenceSpec = PolicySequence_Spec;
export type TestAssertions = Test_Assertions;
export type AssertSpec = Assert;
export type Cors_Spec = CORS_Spec;
export type Authorize_Spec = AuthorizeUser_Spec;

export type TestBasicAuth = Test_Auth_BasicAuth;
export type TestHeaders = Test_Headers;
export type TestParamters = Test_Parameters;
export type TestPayload = Test_Payload;
export type TestAuth = Test_Auth;
export type RefEndpoint = RefAndEndpoint;

export type Ref = Required<Reference>;
export type Variable = Required<Variable_Ref>;
export type Environment = Environment_Ref;
export type PolicySequence = PolicySequence_Spec;
export type Expression = Required<Assert>;
export type Assertion = Required<Test_Assertions>;

// Extend the Test_Request type to ensure var is properly typed
export type Request = Required<Test_Request> & {
  var?: TestVariable[] | string;
  endpoint?: string;
};
export type Specification = {
  'api-spec'?: API_Spec_Ref | string;
  'policy-sequence'?: Ref[];
  api?: Ref | string;
  scopes?: Ref[];
  environment?: Ref | Environment;
  request?: Request[];
};
export type BaseAsset = {
  kind: string;
  apiVersion?: string;
  metadata: Metadata;
  spec: Specification | string | any;
  paths?: any;
  info?: any;
};

export type ApiObject = Api;

export type IAMPayloadIdentifier = PayLoadIdentifier;
export type XSL = Xsl;

export const AssetKinds = {
  API: 'API',
  Scope: 'Scope',
  PolicySequence: 'PolicySequence',
  CORS: 'CORS',
  Test: 'Test',
  Assertion: 'Assertion',
  Environment: 'Environment',
  Plan: 'Plan',
  Product: 'Product',
  Quota: 'Quota',
  Properties: 'Properties',
  URISchemes: 'URISchemes',
  DataPowerAssembly: 'DataPowerAssembly',
  FreeFlowPolicySequence: 'FreeFlowPolicySequence',
  StagedPolicySequence: 'StagedPolicySequence',
  Telemetry: 'Telemetry',
  Invoke: 'Invoke',
  LoadBalancer: 'LoadBalancer',
  InboundBulkHead: 'InboundBulkHead',
  InboundMessaging: 'InboundMessaging',
  SetMediaType: 'SetMediaType',
  AuthorizeUser: 'AuthorizeUser',
  SetContextVariable: 'SetContextVariable',
  WebMethodsISService: 'WebMethodsISService',
  Log: 'Log',
  IAM: 'IAM',
  Authorize: 'Authorize',
  TransformResponse: 'TransformResponse',
  TransformRequest: 'TransformRequest',
  MonitorTraffic: 'MonitorTraffic',
  SetAuthorization: 'SetAuthorization',
  OutboundAnonymous: 'OutboundAnonymous',
  OutboundAlias: 'OutboundAlias',
  CacheServiceResult: 'CacheServiceResult',
  ValidateAPISpecification: 'ValidateAPISpecification',
  ErrorProcessing: 'ErrorProcessing',
  HTTPEndpoint: 'HTTPEndpoint',
  HandlebarsTemplate: 'HandlebarsTemplate',
  Route: 'Route',
  SQLInjectionFilter: 'SQLInjectionFilter',
  MessageConfig: 'MessageConfig',
  LuaScript: 'LuaScript',
  Set: 'Set',
  RateLimitDef: 'RateLimitDef',
  RateLimit: 'RateLimit',
  Return: 'Return',
  GlobalPolicy: 'GlobalPolicy',
  DataMasking: 'DataMasking',
  InvokeMessagingExtension: 'InvokeMessagingExtension',
  HTTPInvoke: 'HTTPInvoke',
  CountLimit: 'CountLimit',
  CountLimitDef: 'CountLimitDef',
  Redact: 'Redact',
  Remove: 'Remove',
  Throw: 'Throw',
  Block: 'Block',
  Transform: 'Transform',
  Switch: 'Switch',
  If: 'If',
  OperationSwitch: 'OperationSwitch',
  InvokeAWSLambda: 'InvokeAWSLambda',
  WatsonXAIInvoke: 'WatsonXAIInvoke',
  OpenAIInvoke: 'OpenAIInvoke',
  ExtractIdentity: 'ExtractIdentity',
  EnforceCircuitBreaker: 'EnforceCircuitBreaker',
  Parse: 'Parse',
  Retry: 'Retry',
  IBMCloudLogin: 'IBMCloudLogin',
  Authenticate: 'Authenticate',
  Cache: 'Cache',
  Try: 'Try',
} as const;

export const POLICY_KINDS: string[] = [
  KindEnums.Log,
  KindEnums.Route,
  KindEnums.Transport,
  KindEnums.CacheServiceResult,
  KindEnums.ErrorProcessing,
  KindEnums.IdentifyAndAuthorize,
  KindEnums.InvokeMessagingExtension,
  KindEnums.InvokeAWSLambdaFunction,
  KindEnums.MonitorTraffic,
  KindEnums.RateLimiter,
  KindEnums.SetContextVariable,
  KindEnums.TransformRequest,
  KindEnums.ValidateAPISpecification,
  KindEnums.HTTPEndpoint,
  KindEnums.TransformResponse,
  KindEnums.SetMediaType,
  KindEnums.WebMethodsISService,
  KindEnums.InboundBulkHead,
  KindEnums.InboundMessaging,
  KindEnums.AuthorizeUser,
  KindEnums.CustomHttpHeader,
  KindEnums.MessageConfig,
  KindEnums.OutboundAlias,
  KindEnums.OutboundAnonymous,
  KindEnums.OutboundBasicAuth,
  KindEnums.OutboundOAuth2,
  KindEnums.OutboundIncomingJWT,
  KindEnums.OutboundNTLMAuth,
  KindEnums.OutboundKerberosAuth,
  AssetKinds.SetAuthorization,
  AssetKinds.Invoke,
  AssetKinds.LoadBalancer,
  AssetKinds.URISchemes,
  AssetKinds.Properties,
  AssetKinds.CORS,
  AssetKinds.Log,
  AssetKinds.MonitorTraffic,
  AssetKinds.OutboundAnonymous,
  AssetKinds.OutboundAlias,
  AssetKinds.CacheServiceResult,
  AssetKinds.RateLimitDef,
  AssetKinds.RateLimit,
  AssetKinds.IAM,
  AssetKinds.Set,
  AssetKinds.Return,
  AssetKinds.LuaScript,
  AssetKinds.CountLimit,
  AssetKinds.HTTPInvoke,
  AssetKinds.CountLimitDef,
  AssetKinds.Redact,
  AssetKinds.Remove,
  AssetKinds.Block,
  AssetKinds.InvokeAWSLambda,
  AssetKinds.EnforceCircuitBreaker,
  AssetKinds.Parse,
  AssetKinds.Switch,
  AssetKinds.InvokeMessagingExtension,
  AssetKinds.DataMasking,
  AssetKinds.If,
  AssetKinds.OperationSwitch,
  AssetKinds.HTTPInvoke,
  AssetKinds.Switch,
  AssetKinds.If,
  AssetKinds.ExtractIdentity,
  AssetKinds.SQLInjectionFilter,
  AssetKinds.Retry,
  AssetKinds.IBMCloudLogin,
  AssetKinds.Throw,
  AssetKinds.Authenticate,
  AssetKinds.Cache,
  AssetKinds.Try,
];
export type AssetKindsType = keyof typeof AssetKinds;

export const NANO_GW_POLICY_KINDS: string[] = [
  AssetKinds.Invoke,
  AssetKinds.HandlebarsTemplate,
  AssetKinds.LoadBalancer,
  AssetKinds.Telemetry,
  AssetKinds.Authorize,
  AssetKinds.Transform
];

type ExtensionInfo = {
  [K in keyof typeof AssetKinds]?: {
    versions: string[];
    defaultVersion: string;
  };
};
export const CommonModelExtensionInfo: ExtensionInfo = {
  [AssetKinds.Invoke]: {
    versions: ['api.ibm.com/v1'],
    defaultVersion: 'api.ibm.com/v1',
  },
};

export { KindEnums as AssetModelKindConstants };

export class AssetModelInternalKindConstants {
  public static readonly POLICY: string = 'Policy';
  public static readonly MOCK_END_POINT: string = 'MockEndpoint';
  public static readonly MOCK_RESPONSE: string = 'MockResponse';
}

// Define a specific type for test variables that includes name, key, and value
export interface TestVariable {
  key: string;
  value: string;
}
