import { TemplateResult } from 'lit'
import type {
  IApiSecurityOAuth2Settings,
  IApiSecurityScheme,
  IApiSecuritySettingsUnion,
} from '@api-client/core/amf/definitions/Api.js'
import { AmfNamespace } from '@api-client/core/amf/definitions/Namespace.js'
import ApiSecurityDocumentElement from './ApiSecurityDocument.element.js'

export default class ApiParametrizedSecurityScheme extends ApiSecurityDocumentElement {
  protected settingsValue: IApiSecuritySettingsUnion | undefined

  get settings(): IApiSecuritySettingsUnion | undefined {
    return this.settingsValue
  }

  set settings(value) {
    const old = this.settingsValue
    if (old === value) {
      return
    }
    this.settingsValue = value
    this.requestUpdate()
  }

  /**
   * @returns The template for the security settings, when required.
   */
  override settingsTemplate(scheme: IApiSecurityScheme): TemplateResult | string {
    const appliedSettings = this.settingsValue
    if (!appliedSettings) {
      return super.settingsTemplate(scheme)
    }
    const { settings } = scheme
    if (!settings) {
      return ''
    }
    const { types } = settings
    const mergedSettings = this.mergeSettings(appliedSettings, settings)

    if (types.includes(AmfNamespace.aml.vocabularies.security.ApiKeySettings)) {
      return this.apiKeySettingsTemplate(mergedSettings)
    }
    if (types.includes(AmfNamespace.aml.vocabularies.security.OpenIdConnectSettings)) {
      return this.openIdConnectSettingsTemplate(mergedSettings)
    }
    if (types.includes(AmfNamespace.aml.vocabularies.security.OAuth2Settings)) {
      return this.oAuth2SettingsTemplate(mergedSettings as IApiSecurityOAuth2Settings)
    }
    return ''
  }

  /**
   * @param applied The settings applied to the current object
   * @param scheme The settings defined in the scheme
   * @returns The merged settings to render.
   */
  protected mergeSettings(
    applied: IApiSecuritySettingsUnion,
    scheme: IApiSecuritySettingsUnion
  ): IApiSecuritySettingsUnion {
    const result = { ...scheme } as IApiSecuritySettingsUnion
    Object.keys(applied).forEach((key) => {
      if (['id', 'types', 'additionalProperties'].includes(key)) {
        return
      }
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      result[key as keyof IApiSecuritySettingsUnion] = (applied as any)[key]
    })
    return result
  }
}
