import DataFetch from "./DataFetch.js"
import { Helpers } from "@budibase/bbui"
import { get } from "svelte/store"

export default class QueryFetch extends DataFetch {
  determineFeatureFlags(definition) {
    const supportsPagination =
      !!definition?.fields?.pagination?.type &&
      !!definition?.fields?.pagination?.location &&
      !!definition?.fields?.pagination?.pageParam
    return { supportsPagination }
  }

  async getDefinition(datasource) {
    if (!datasource?._id) {
      return null
    }
    try {
      const definition = await this.API.fetchQueryDefinition(datasource._id)
      // After getting the definition of query, it loses "fields" attribute
      // because of security reason from the server. However, this attribute
      // needs to be inside the definition for pagination.
      if (!definition.fields) {
        definition.fields = datasource.fields
      }
      return definition
    } catch (error) {
      return null
    }
  }

  async getData() {
    const { datasource, limit, paginate } = this.options
    const { supportsPagination } = get(this.featureStore)
    const { cursor, definition } = get(this.store)
    const type = definition?.fields?.pagination?.type

    // Set the default query params
    let parameters = Helpers.cloneDeep(datasource?.queryParams || {})
    for (let param of datasource?.parameters || {}) {
      if (!parameters[param.name]) {
        parameters[param.name] = param.default
      }
    }

    // Add pagination to query if supported
    let queryPayload = { queryId: datasource?._id, parameters }
    if (paginate && supportsPagination) {
      const requestCursor = type === "page" ? parseInt(cursor || 1) : cursor
      queryPayload.pagination = { page: requestCursor, limit }
    }

    // Execute query
    try {
      const res = await this.API.executeQuery(queryPayload)
      const { data, pagination, ...rest } = res

      // Derive pagination info from response
      let nextCursor = null
      let hasNextPage = false
      if (paginate && supportsPagination) {
        if (type === "page") {
          // For "page number" pagination, increment the existing page number
          nextCursor = queryPayload.pagination.page + 1
          hasNextPage = data?.length === limit && limit > 0
        } else {
          // For "cursor" pagination, the cursor should be in the response
          nextCursor = pagination?.cursor
          hasNextPage = nextCursor != null
        }
      }

      return {
        rows: data || [],
        info: rest,
        cursor: nextCursor,
        hasNextPage,
      }
    } catch (error) {
      return {
        rows: [],
        hasNextPage: false,
      }
    }
  }
}
