import { Model } from '../core/Model.js'
import { exponentialBackoffDelay, type RetryOptions, shouldRetryApiError, retry } from './retry_logic.js'
import type SdkService from '../services/SdkService.js'
import type { InvitationSchema } from '@api-client/core/models/store/Invitation.js'

export default class InvitationModel extends Model<InvitationSchema> {
  /**
   * A reference to the SDK service used to perform API calls.
   */
  sdk: SdkService
  /**
   * Whether the model is currently loading data.
   */
  loading = false

  constructor(sdk: SdkService) {
    super()
    this.sdk = sdk
  }

  /**
   * Fetches the invitation data for the given token.
   * @param token The invitation token to fetch.
   * @returns The invitation data.
   * @throws Error if the invitation cannot be fetched (e.g., network error or invalid token).
   */
  async fetch(token: string): Promise<InvitationSchema> {
    this.loading = true
    const operation = async (): Promise<InvitationSchema> => {
      return this.sdk.organizations.invitations.findByToken(token)
    }
    const retryOptions: RetryOptions = {
      retries: this.retryCount,
      delayMs: exponentialBackoffDelay,
      shouldRetry: shouldRetryApiError,
    }
    try {
      this.raw = await retry(operation, retryOptions)
    } finally {
      this.loading = false
    }
    return this.raw
  }

  /**
   * Rejects the invitation.
   * @throws Error if the invitation cannot be rejected (e.g., network error).
   */
  async reject(): Promise<void> {
    const { value } = this
    if (!value) {
      throw new Error('Cannot reject invitation without fetching it first.')
    }
    this.loading = true
    const operation = async (): Promise<InvitationSchema> => {
      return this.sdk.organizations.invitations.decline(value.oid, value.token)
    }
    const retryOptions: RetryOptions = {
      retries: this.retryCount,
      delayMs: exponentialBackoffDelay,
      shouldRetry: shouldRetryApiError,
    }
    try {
      this.raw = await retry(operation, retryOptions)
    } finally {
      this.loading = false
    }
  }
}
