import {
  SdkBase,
  E_RESPONSE_STATUS,
  E_RESPONSE_NO_VALUE,
  E_INVALID_JSON,
  E_RESPONSE_UNKNOWN,
  type SdkOptions,
} from './SdkBase.js'
import { RouteBuilder } from './RouteBuilder.js'
import type { ContextListOptions, ContextListResult } from '../events/BaseEvents.js'
import type { TrashEntry } from '../models/TrashEntry.js'
import { Exception } from '../exceptions/exception.js'

export class TrashSdk extends SdkBase {
  /**
   * Lists trashed entires.
   * @param options The list query options.
   */
  async list(
    oid: string,
    options: ContextListOptions = {},
    request: SdkOptions = {}
  ): Promise<ContextListResult<TrashEntry>> {
    const { token } = request
    const url = this.sdk.getUrl(RouteBuilder.trash(oid))
    this.sdk.appendListOptions(url, options)
    const result = await this.sdk.http.get(url.toString(), { token })
    this.inspectCommonStatusCodes(result)
    const E_PREFIX = 'Unable to list trash. '
    if (result.status !== 200) {
      this.logInvalidResponse(result)
      throw this.createApiError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.body)
    }
    if (!result.body) {
      throw new Exception(`${E_PREFIX}${E_RESPONSE_NO_VALUE}`, { code: 'E_RESPONSE_NO_VALUE', status: result.status })
    }
    let data: ContextListResult<TrashEntry>
    try {
      data = JSON.parse(result.body)
    } catch {
      throw new Exception(`${E_PREFIX}${E_INVALID_JSON}`, { code: 'E_INVALID_JSON', status: result.status })
    }
    if (!Array.isArray(data.items)) {
      throw new Exception(`${E_PREFIX}${E_RESPONSE_UNKNOWN}`, { code: 'E_RESPONSE_UNKNOWN', status: result.status })
    }
    return data
  }

  /**
   * Permanently deletes a number of files in a batch operation.
   *
   * @param oid The parent organization
   * @param keys The list of trash entry keys to delete.
   * @param request Optional request options.
   */
  async delete(oid: string, keys: string[], request: SdkOptions = {}): Promise<void> {
    const path = RouteBuilder.trashBatchDelete(oid)
    const url = this.sdk.getUrl(path)
    const { token } = request
    const result = await this.sdk.http.delete(url.toString(), { token, body: JSON.stringify({ ids: keys }) })
    this.inspectCommonStatusCodes(result)
    const E_PREFIX = 'Unable to delete trash. '
    if (result.status !== 204) {
      this.logInvalidResponse(result)
      throw this.createApiError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.body)
    }
  }

  async restore(oid: string, keys: string[], request: SdkOptions = {}): Promise<void> {
    const url = this.sdk.getUrl(RouteBuilder.trashBatchRestore(oid))
    const { token } = request
    const result = await this.sdk.http.post(url.toString(), { token, body: JSON.stringify({ ids: keys }) })
    this.inspectCommonStatusCodes(result)
    const E_PREFIX = 'Unable to restore from trash. '
    if (result.status !== 204) {
      this.logInvalidResponse(result)
      throw this.createApiError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.body)
    }
  }

  /**
   * Empties the trash for the user in the given organization.
   * @param organization The organization key to remove trash for.
   */
  async empty(organization: string, request: SdkOptions = {}): Promise<void> {
    const { token } = request
    const url = this.sdk.getUrl(RouteBuilder.trashEmpty(organization))
    const result = await this.sdk.http.delete(url.toString(), { token })
    this.inspectCommonStatusCodes(result)
    const E_PREFIX = 'Unable to empty trash. '
    if (result.status !== 204) {
      this.logInvalidResponse(result)
      throw this.createApiError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.body)
    }
  }
}
