import { Action, type ActionSchema } from './Action.js'
import { observed, toRaw } from '../../decorators/observed.js'

/**
 * Enables modifying an existing resource.
 * Endpoints: PUT or PATCH /[entity-collection-name]/{id}
 */
export interface UpdateActionSchema extends ActionSchema {
  kind: 'update'
  /**
   * The allowed HTTP methods for updates. Default: PATCH only.
   *
   * These two methods represent the two common ways to update a resource:
   * - PUT: Replaces the entire resource with the provided data.
   * - PATCH: Applies a partial update to the resource, allowing for specific fields to be modified.
   */
  allowedMethods: ('PUT' | 'PATCH')[]
}

/**
 * Enables modifying an existing resource.
 * Endpoints: PUT or PATCH /[entity-collection-name]/{id}
 */
export class UpdateAction extends Action implements UpdateActionSchema {
  @observed() override accessor kind: 'update'
  @observed({ deep: true }) accessor allowedMethods: ('PUT' | 'PATCH')[]

  constructor(state: Partial<UpdateActionSchema> = {}) {
    super(state)
    this.kind = 'update'
    this.allowedMethods = state.allowedMethods ? [...state.allowedMethods] : ['PATCH']
  }

  override toJSON(): UpdateActionSchema {
    return {
      ...(super.toJSON() as UpdateActionSchema),
      kind: 'update',
      allowedMethods: structuredClone(toRaw(this, this.allowedMethods)) as ('PUT' | 'PATCH')[],
    }
  }

  static isUpdateAction(action: Action): action is UpdateAction {
    return action.kind === 'update'
  }

  static isUpdateActionSchema(schema: ActionSchema): schema is UpdateActionSchema {
    return schema.kind === 'update'
  }
}
