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

/**
 * Enables retrieving a collection of resources.
 * Endpoint: GET /[entity-collection-name]
 */
export interface ListActionSchema extends ActionSchema {
  kind: 'list'
  /**
   * The pagination strategy used for this action.
   * This defines how the results are paginated when retrieving a collection of resources.
   * It can be either 'cursor' or 'offset'.
   */
  pagination: PaginationStrategy
  /**
   * Fields from the entity that can be used for filtering.
   * Must be marked as "indexable" in the Data Model.
   */
  filterableFields: string[]
  /**
   * Fields from the entity that can be used for sorting.
   */
  sortableFields: string[]
}

/**
 * Enables retrieving a collection of resources.
 * Endpoint: GET /[entity-collection-name]
 */
export class ListAction extends Action implements ListActionSchema {
  @observed() override accessor kind: 'list'
  @observed({ deep: true }) accessor pagination: PaginationStrategy
  @observed({ deep: true }) accessor filterableFields: string[] = []
  @observed({ deep: true }) accessor sortableFields: string[] = []

  constructor(state: Partial<ListActionSchema> = {}) {
    super(state)
    this.kind = state.kind || 'list'
    this.pagination = state.pagination
      ? { ...state.pagination }
      : {
          kind: 'offset',
        }
    this.filterableFields = state.filterableFields ? [...state.filterableFields] : []
    this.sortableFields = state.sortableFields ? [...state.sortableFields] : []
  }

  override toJSON(): ListActionSchema {
    return {
      ...(super.toJSON() as ListActionSchema),
      pagination: structuredClone(toRaw(this, this.pagination)) as PaginationStrategy,
      filterableFields: structuredClone(toRaw(this, this.filterableFields)) as string[],
      sortableFields: structuredClone(toRaw(this, this.sortableFields)) as string[],
    }
  }

  static isListAction(action: Action): action is ListAction {
    return action.kind === 'list'
  }

  static isListActionSchema(schema: ActionSchema): schema is ListActionSchema {
    return schema.kind === 'list'
  }
}
