import { Http } from './Http.js'
import type { IStoreRequestOptions, IStoreResponse } from './SdkBase.js'
import { Headers } from '../lib/headers/Headers.js'

export class HttpWeb extends Http {
  /**
   * Performs the GET request.
   *
   * @param url The request URL
   * @param opts The request options
   * @returns The response info.
   */
  async get(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
    const { method = 'GET', headers = {}, token = this.sdk.token } = opts
    const requestHeaders = new Headers({ ...headers })
    if (token) {
      requestHeaders.append('Authorization', `Bearer ${token}`)
    }
    if (!requestHeaders.has('Accept')) {
      requestHeaders.append('Accept', 'application/json')
    }
    const init: RequestInit = {
      method,
      headers: requestHeaders.toJSON(),
      redirect: 'follow',
      credentials: 'include',
      mode: 'cors',
    }
    const response = await fetch(url, init)
    let body: string | undefined
    try {
      body = await response.text()
    } catch {
      // ...
    }

    const responseHeaders = new Headers()
    response.headers.forEach((value: string, key: string) => {
      responseHeaders.append(key, value)
    })

    const result: IStoreResponse = {
      status: response.status,
      headers: responseHeaders,
      body,
    }
    return result
  }

  async post(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
    const { method = 'POST', headers = {}, token = this.sdk.token } = opts
    const requestHeaders = new Headers({ ...headers })
    if (token) {
      requestHeaders.append('Authorization', `Bearer ${token}`)
    }
    if (!requestHeaders.has('Content-Type')) {
      requestHeaders.append('Content-Type', 'application/json')
    }
    if (!requestHeaders.has('Accept')) {
      requestHeaders.append('Accept', 'application/json')
    }
    const init: RequestInit = {
      method,
      headers: requestHeaders.toJSON(),
      redirect: 'follow',
      credentials: 'include',
    }
    if (opts.body) {
      init.body = opts.body.toString()
    }
    const response = await fetch(url, init)
    let body: string | undefined
    try {
      body = await response.text()
    } catch {
      // ...
    }

    const responseHeaders = new Headers()
    response.headers.forEach((value: string, key: string) => {
      responseHeaders.append(key, value)
    })

    const result: IStoreResponse = {
      status: response.status,
      headers: responseHeaders,
      body,
    }
    return result
  }

  patch(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
    const options: IStoreRequestOptions = { ...opts, method: 'PATCH' }
    return this.post(url, options)
  }

  put(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
    const options: IStoreRequestOptions = { ...opts, method: 'PUT' }
    return this.post(url, options)
  }

  delete(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
    const options: IStoreRequestOptions = { ...opts, method: 'DELETE' }
    return this.post(url, options)
  }
}
