import { RequestConfig } from '@api-client/core/models/RequestConfig.js'
import { html, nothing, TemplateResult } from 'lit'
import { property } from 'lit/decorators.js'
import { live } from 'lit/directives/live.js'
import ApiElement from '../ApiElement.js'
import type SwitchElement from '../../md/switch/internals/SwitchElement.js'
import type Input from '../../md/input/Input.js'
import '../../md/switch/ui-switch.js'
import '../../md/text-field/ui-filled-text-field.js'

/**
 * @fires change - when the configuration object changed.
 */
export default class RequestConfigElement extends ApiElement {
  /**
   * HTTP request configuration for the transport.
   */
  @property({ type: Object }) accessor config = new RequestConfig().toJSON()

  protected handleEnabledToggle(e: Event): void {
    const node = e.currentTarget as SwitchElement
    this.config.enabled = !!node.checked
    this.notifyChange()
    this.requestUpdate()
  }

  protected handleFollowRedirects(e: Event): void {
    const node = e.currentTarget as SwitchElement
    this.config.followRedirects = node.checked
    this.notifyChange()
  }

  protected handleIgnoreCookies(e: Event): void {
    const node = e.currentTarget as SwitchElement
    this.config.ignoreSessionCookies = node.checked
    this.notifyChange()
  }

  protected handleValidateCertificates(e: Event): void {
    const node = e.currentTarget as SwitchElement
    this.config.validateCertificates = node.checked
    this.notifyChange()
  }

  protected handleDefaultHeaders(e: Event): void {
    const node = e.currentTarget as SwitchElement
    this.config.defaultHeaders = node.checked
    this.notifyChange()
    this.requestUpdate()
  }

  protected handleTimeoutChange(e: Event): void {
    const input = e.target as Input
    const raw = input.value.trim()
    if (!raw) {
      delete this.config.timeout
      this.requestUpdate()
    } else {
      const num = Number(raw)
      if (Number.isNaN(num)) {
        input.setCustomValidity('Invalid input.')
        input.checkValidity()
        return
      }
      if (this.config.timeout === num) {
        return
      }
      this.config.timeout = num
    }
    input.setCustomValidity('')
    input.checkValidity()
    this.notifyChange()
    this.requestUpdate()
  }

  protected handleDefaultUserAgentChange(e: Event): void {
    const input = e.target as Input
    const raw = input.value.trim()
    if (!raw) {
      if (!this.config.defaultUserAgent) {
        this.requestUpdate()
        return
      }
      delete this.config.defaultUserAgent
      this.requestUpdate()
    } else {
      if (this.config.defaultUserAgent === raw) {
        return
      }
      this.config.defaultUserAgent = raw
    }
    this.notifyChange()
  }

  protected handleDefaultAcceptChange(e: Event): void {
    const input = e.target as Input
    const raw = input.value.trim()
    if (!raw) {
      if (!this.config.defaultAccept) {
        this.requestUpdate()
        return
      }
      delete this.config.defaultAccept
      this.requestUpdate()
    } else {
      if (this.config.defaultAccept === raw) {
        return
      }
      this.config.defaultAccept = raw
    }
    this.notifyChange()
  }

  protected override render(): TemplateResult {
    return html`
      ${this.renderPanelTitle()} ${this.renderEnableSwitch()} ${this.renderRedirectsConfig()}
      ${this.renderIgnoreSessionCookiesConfig()} ${this.renderValidateCertificatesConfig()}
      ${this.renderDefaultHeadersConfig()} ${this.renderDefaultUserAgentConfig()} ${this.renderDefaultAcceptConfig()}
      ${this.renderTimeoutConfig()}
    `
  }

  protected renderPanelTitle(): TemplateResult {
    return html`
      <div class="title-medium">Request options</div>
      <p class="body-medium">This overrides other configurations defined in the application.</p>
    `
  }

  protected renderEnableSwitch(): TemplateResult {
    const { enabled = false } = this.config
    return html`
      <div class="form-row">
        <ui-switch
          name="enabled"
          .checked="${enabled}"
          @change="${this.handleEnabledToggle}"
          title="Toggle options enabled"
          aria-label="Toggle options enabled"
          id="enable"
        ></ui-switch>
        <label class="label-large" for="enable"> Enable custom request options </label>
      </div>
    `
  }

  protected renderRedirectsConfig(): TemplateResult | typeof nothing {
    const { enabled = false, followRedirects = false } = this.config
    if (!enabled) {
      return nothing
    }
    return html`
      <div class="form-row">
        <ui-switch
          name="followRedirects"
          id="followRedirects"
          .checked="${followRedirects}"
          @change="${this.handleFollowRedirects}"
          title="Toggle follow redirects"
          aria-label="Toggle follow redirects"
        ></ui-switch>
        <label class="label-large" for="followRedirects"> Follow redirects </label>
      </div>
    `
  }

  protected renderTimeoutConfig(): TemplateResult | typeof nothing {
    const { enabled = false, timeout = 90 } = this.config
    if (!enabled) {
      return nothing
    }
    const value = typeof timeout === 'number' ? String(timeout) : ''
    return html`
      <div class="form-row">
        <ui-filled-text-field
          name="timeout"
          label="Request timeout"
          .value="${live(value)}"
          @change="${this.handleTimeoutChange}"
          supportingText="0 for no timeout, clear for default."
          inputMode="numeric"
          invalidText="Enter a positive integer or zero."
        ></ui-filled-text-field>
      </div>
    `
  }

  protected renderDefaultUserAgentConfig(): TemplateResult | typeof nothing {
    const { enabled = false, defaultUserAgent = 'api-client', defaultHeaders = false } = this.config
    if (!enabled || !defaultHeaders) {
      return nothing
    }
    return html`
      <div class="form-row">
        <ui-filled-text-field
          name="defaultUserAgent"
          label="Default user agent"
          .value="${live(defaultUserAgent)}"
          @change="${this.handleDefaultUserAgentChange}"
        ></ui-filled-text-field>
      </div>
    `
  }

  protected renderDefaultAcceptConfig(): TemplateResult | typeof nothing {
    const { enabled = false, defaultAccept = '*/*', defaultHeaders = false } = this.config
    if (!enabled || !defaultHeaders) {
      return nothing
    }
    return html`
      <div class="form-row">
        <ui-filled-text-field
          name="defaultAccept"
          label="Default accept"
          .value="${live(defaultAccept)}"
          @change="${this.handleDefaultAcceptChange}"
        ></ui-filled-text-field>
      </div>
    `
  }

  protected renderIgnoreSessionCookiesConfig(): TemplateResult | typeof nothing {
    const { enabled = false, ignoreSessionCookies = false } = this.config
    if (!enabled) {
      return nothing
    }
    return html`
      <div class="form-row">
        <ui-switch
          name="ignoreSessionCookies"
          id="ignoreSessionCookies"
          .checked="${ignoreSessionCookies}"
          @change="${this.handleIgnoreCookies}"
          title="Toggle ignore cookies"
          aria-label="Toggle ignore cookies"
        ></ui-switch>
        <label class="label-large" for="ignoreSessionCookies"> Ignore cookies </label>
      </div>
    `
  }

  protected renderValidateCertificatesConfig(): TemplateResult | typeof nothing {
    const { enabled = false, validateCertificates = false } = this.config
    if (!enabled) {
      return nothing
    }
    return html`
      <div class="form-row">
        <ui-switch
          name="validateCertificates"
          id="validateCertificates"
          .checked="${validateCertificates}"
          @change="${this.handleValidateCertificates}"
          title="Toggle validate certificates"
          aria-label="Toggle validate certificates"
        ></ui-switch>
        <label class="label-large" for="validateCertificates"> Validate certificates </label>
      </div>
    `
  }

  protected renderDefaultHeadersConfig(): TemplateResult | typeof nothing {
    const { enabled = false, defaultHeaders = false } = this.config
    if (!enabled) {
      return nothing
    }
    return html`
      <div class="form-row">
        <ui-switch
          name="defaultHeaders"
          id="defaultHeaders"
          .checked="${defaultHeaders}"
          @change="${this.handleDefaultHeaders}"
          title="Toggle validate certificates"
          aria-label="Toggle validate certificates"
        ></ui-switch>
        <label class="label-large" for="defaultHeaders">
          Add default headers to the request (accept and user agent)
        </label>
      </div>
    `
  }
}
