/* eslint-disable @typescript-eslint/unified-signatures */
import { FlowRequestDataEnum, FlowResponseDataEnum, FlowSourceEnum } from '../../HttpFlows.js'
import { HttpStep, IHttpStep } from '../../HttpStep.js'

export const ReadDataStepKind = 'HttpAction#ReadData'

/**
 * Reads the data from various sources.
 */
export interface IReadDataStep extends IHttpStep {
  kind: typeof ReadDataStepKind
  /**
   * The main data source.
   * In the legacy actions this was `type`.
   */
  source?: FlowSourceEnum
  /**
   * Source of the data.
   * In the legacy actions this was `source`.
   * This is not required when the source is not `request` or `response`.
   */
  data?: FlowRequestDataEnum | FlowResponseDataEnum
  /**
   * The path to the data.
   * For JSON value use https://jmespath.org/ syntax.
   * For XML use xpath.
   * For any other use a simple path to the data separated by dot (e.g. headers.content-type)
   */
  path?: string
}

export class ReadDataStep extends HttpStep {
  override kind = ReadDataStepKind

  /**
   * The main data source.
   * In the legacy actions this was `type`.
   */
  source?: FlowSourceEnum

  /**
   * Source of the data.
   * In the legacy actions this was `source`.
   * This is not required when the source is not `request` or `response`.
   */
  data?: FlowRequestDataEnum | FlowResponseDataEnum

  /**
   * The path to the data.
   * For JSON value use https://jmespath.org/ syntax.
   * For XML use xpath.
   * For any other use a simple path to the data separated by dot (e.g. headers.content-type)
   */
  path?: string

  /**
   * Creates the step from values.
   * @param source The main data source.
   * @param path The path to the data.
   * @param data Source of the data in the `source`. This is optional for non-http-request source.
   */
  constructor(source: FlowSourceEnum, path?: string, data?: FlowRequestDataEnum | FlowResponseDataEnum)

  /**
   * Creates the step from serialized schema.
   * @param init The serialized step values.
   */
  constructor(init: IReadDataStep)

  /**
   * Creates an empty step.
   */
  constructor()

  constructor(
    sourceOrInit?: FlowSourceEnum | IReadDataStep,
    path?: string,
    data?: FlowRequestDataEnum | FlowResponseDataEnum
  ) {
    super()
    if (!sourceOrInit) {
      return
    }
    if (typeof sourceOrInit === 'object') {
      const typed = sourceOrInit as IReadDataStep
      this.new(typed)
    } else if (typeof sourceOrInit === 'string') {
      this.new({
        kind: ReadDataStepKind,
        source: sourceOrInit,
        data,
        path,
        enabled: true,
      })
    }
  }

  override new(init: IReadDataStep): void {
    super.new(init)
    this.kind = ReadDataStepKind
    this.source = init.source
    this.data = init.data
    this.path = init.path
  }

  checkValidity(): boolean {
    const { source, path, data } = this
    if (!source && !path) {
      return false
    }
    if (source === FlowSourceEnum.variable) {
      return true
    }
    return !!data
  }

  override toJSON(): IReadDataStep {
    const result: IReadDataStep = {
      ...super.toJSON(),
      kind: ReadDataStepKind,
    }
    if (this.source) {
      result.source = this.source
    }
    if (this.data) {
      result.data = this.data
    }
    if (this.path) {
      result.path = this.path
    }
    return result
  }
}
