import '@material/web/button/elevated-button.js'
import '../../components/role-selector'

import gql from 'graphql-tag'
import { css, html, LitElement } from 'lit'
import { customElement, property, query } from 'lit/decorators.js'

import { client } from '@operato/graphql'
import { i18next } from '@operato/i18n'
import { OxPrompt } from '@operato/popup/ox-prompt.js'
import { ButtonContainerStyles } from '@operato/styles'

@customElement('oauth2-decision')
class OAuth2DecisionPage extends LitElement {
  static styles = [
    ButtonContainerStyles,
    css`
      :host {
        display: flex;
        flex-direction: column;

        border: 1px solid var(--md-sys-color-primary);
        margin: var(--spacing-medium);
        padding: var(--spacing-medium);
        font: normal 15px var(--theme-font);
        color: var(--md-sys-color-secondary);
      }

      [field-2column] {
        border-radius: var(--border-radius);
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 5px 15px;
        clear: both;
        max-width: var(--input-container-max-width);
      }

      [field] {
        display: flex;
        flex-direction: column;
        padding-bottom: var(--spacing-medium);
      }

      input {
        border: var(--border-dim-color);
        border-radius: var(--border-radius);
        margin: var(--input-margin);
        padding: var(--input-padding);
        min-width: 250px;
        font: var(--input-font);
      }

      label {
        display: flex;
        flex-direction: column;
        font: var(--label-font);
        color: var(--label-color, var(--md-sys-color-on-surface));
        text-transform: var(--label-text-transform);
      }

      md-elevated-button {
        margin-right: var(--spacing-small);
      }
    `
  ]

  @property({ type: Object }) data: any = {}
  @property({ type: Object }) user: any = {}
  @property({ type: Object }) client: any = {}
  @property({ type: Object }) domain: any = {}
  @property({ type: Object }) req: any = {}
  @property({ type: String }) redirectURI: string = ''
  @property({ type: String }) transactionID: string = ''
  @property({ type: Array }) roles: any[] = []

  @query('role-selector') roleSelector!: HTMLElement & { selectedRoles: () => any[] }

  render() {
    return html`
      <h2>Application Binding</h2>
      <p>Hi ${this.user.name}!</p>
      <p><b> ${this.client.name} </b> is requesting access to your account.</p>
      <p>Do you approve?</p>

      <form field-2column>
        <div field>
          <label
            >${i18next.t('label.company')}
            <input readonly value="${this.domain.subdomain}" />
          </label>

          <label
            >${i18next.t('label.client-id')}
            <input readonly value="${this.req.clientID}" />
          </label>
        </div>

        <div field>
          <label
            >${i18next.t('label.redirect_uri')}
            <input readonly value="${this.redirectURI}" />
          </label>

          <label
            >${i18next.t('label.state')}
            <input readonly value="${this.req.state}" />
          </label>
        </div>
      </form>

      <role-selector .roleCategory="${this.domain.name}" .roles="${this.roles}"></role-selector>

      <div class="button-container">
        <md-elevated-button @click="${() => this.decision(true)}" raised label="Allow"></md-elevated-button>
        <md-elevated-button @click="${() => this.decision(false)}" raised danger label="Deny"></md-elevated-button>
      </div>
    `
  }

  async firstUpdated() {
    this.fetchMyRoles()
  }

  updated(changedProps) {
    if (changedProps.has('data')) {
      this.user = this.data?.oauth2?.user || this.user
      this.client = this.data?.oauth2?.client || this.client
      this.domain = this.data?.domain || this.domain
      this.req = this.data?.oauth2?.req || this.req
      this.redirectURI = this.data?.oauth2?.redirectURI || this.redirectURI
      this.transactionID = this.data?.oauth2?.transactionID || this.transactionID
    }
  }

  async fetchMyRoles() {
    const response = await client.query({
      query: gql`
        query myRoles {
          myRoles {
            id
            name
            description
          }
        }
      `
    })

    if (!response.errors?.length) {
      this.roles = response.data.myRoles
    }
  }

  async decision(allowOrCancel) {
    const selectedRoles = this.selectedRoles()
    if (allowOrCancel && !selectedRoles?.length) {
      await OxPrompt.open({
        title: i18next.t('title.nothing selected'),
        text: i18next.t('text.should select at least one of x', { x: i18next.t('label.role') }),
        confirmButton: { text: i18next.t('button.confirm') }
      })

      return
    }

    let data: any = {
      transaction_id: this.transactionID,
      subdomain: this.domain.subdomain,
      appKey: this.req.clientID,
      state: this.req.state,
      email: this.user.email,
      scopes: selectedRoles
    }
    if (!allowOrCancel) {
      data.cancel = 'Deny'
    }

    const response = await fetch('/oauth/decision', {
      method: 'POST',
      mode: 'cors',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json'
      },
      redirect: 'follow',
      body: JSON.stringify(data)
    })

    if (response.redirected) {
      location.href = response.url
    }
  }

  selectedRoles() {
    return this.roleSelector.selectedRoles()
  }
}
