/**
 * @license
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {customElement, property, query, state} from 'lit/decorators.js';
import {css, html, CSSResult, LitElement} from 'lit';
import {RestPluginApi} from '@gerritcodereview/typescript-api/rest';
import {Timestamp} from '@gerritcodereview/typescript-api/rest-api';

export interface BindValueChangeEventDetail {
  value: string | undefined;
}
export type BindValueChangeEvent = CustomEvent<BindValueChangeEventDetail>;

export interface TokenInfo {
  id: string;
  token?: string;
  expiration?: Timestamp;
}

//TODO(Thomas): Remove after updated Typescript API was released with Gerrit 3.13
export declare interface ServerInfo {
  auth: AuthInfo;
}

export declare interface AuthInfo {
  max_token_lifetime?: string;
}

@customElement('gr-serviceuser-tokens')
export class GrServiceUserTokens extends LitElement {
  @property()
  pluginRestApi!: RestPluginApi;

  @property({type: String})
  serviceUserId?: string;  @query('#generatedAuthTokenModal')

  @query('#generatedAuthTokenModal')
  generatedAuthTokenModal?: HTMLDialogElement;

  @state()
  username?: string;

  @state()
  generatedAuthToken?: TokenInfo;

  @state()
  status?: string;

  @state()
  maxLifetime: string = 'unlimited';

  @property({type: Array})
  tokens: TokenInfo[] = [];

  @property({type: String})
  newTokenId = '';

  @property({type: String})
  newLifetime = '';

  @query('#generateButton') generateButton!: HTMLButtonElement;

  @query('#newToken') tokenInput!: HTMLInputElement;

  @query('#lifetime') tokenLifetime!: HTMLInputElement;

  async loadData(pluginRestApi: RestPluginApi) {
    this.pluginRestApi = pluginRestApi;
    this.serviceUserId = this.baseURI.split('/').pop();
    await pluginRestApi
      .get<ServerInfo>('/a/config/server/info')
      .then(config => {
        this.maxLifetime = config?.auth?.max_token_lifetime || 'unlimited';
      });
    await this.fetchTokens();
  }

  private fetchTokens() {
    this.pluginRestApi
      .get<TokenInfo[]>(`/a/config/server/serviceuser~serviceusers/${this.serviceUserId}/tokens`)
      .then(tokens => {
        this.tokens = tokens;
      });
  }

  static override get styles() {
    return [
      window.Gerrit.styles.form as CSSResult,
      window.Gerrit.styles.modal as CSSResult,
      css`
        .token {
          font-family: var(--monospace-font-family);
          font-size: var(--font-size-mono);
          line-height: var(--line-height-mono);
        }
        #generatedAuthTokenModal {
          padding: var(--spacing-xxl);
          width: 50em;
        }
        #generatedAuthTokenDisplay {
          margin: var(--spacing-l) 0;
        }
        #generatedAuthTokenDisplay .title {
          width: unset;
        }
        #generatedAuthTokenDisplay .value {
          font-family: var(--monospace-font-family);
          font-size: var(--font-size-mono);
          line-height: var(--line-height-mono);
        }
        #authTokenWarning {
          font-style: italic;
          text-align: center;
        }
        #existing {
          margin-top: var(--spacing-l);
          margin-bottom: var(--spacing-l);
        }
        #existing .idColumn {
          min-width: 15em;
          width: auto;
        }
        .closeButton {
          bottom: 2em;
          position: absolute;
          right: 2em;
        }
        .expired {
          color: var(--negative-red-text-color);
        }
        .lifeTimeInput {
          min-width: 23em;
        }
      `,
    ];
  }

  override render() {
    return html`
      <div class="gr-form-styles">
        <fieldset id="existing">
          <table>
            <thead>
              <tr>
                <th class="idColumn">ID</th>
                <th class="expirationColumn">Expiration Date</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              ${this.tokens.map(tokenInfo => this.renderToken(tokenInfo))}
            </tbody>
            <tfoot>
              ${this.renderFooterRow()}
            </tfoot>
          </table>
        </fieldset>
      </div>
      <dialog
        tabindex="-1"
        id="generatedAuthTokenModal"
        @closed=${this.generatedAuthTokenModalClosed}
      >
        <div class="gr-form-styles">
          <section id="generatedAuthTokenDisplay">
            <span class="title">New Token:</span>
            <span class="value"
              >${this.status || this.generatedAuthToken?.token}</span
            >
            <gr-copy-clipboard
              hasTooltip=""
              buttonTitle="Copy token to clipboard"
              hideInput=""
              .text=${this.status ? '' : this.generatedAuthToken?.token}
            >
            </gr-copy-clipboard>
          </section>
          <section
            id="authTokenWarning"
            ?hidden=${!this.generatedAuthToken?.expiration}
          >
            This token will be valid until &nbsp;
            <gr-date-formatter
              showDateAndTime
              withTooltip
              .dateStr=${this.generatedAuthToken?.expiration}
            ></gr-date-formatter>
            .
          </section>
          <section id="authTokenWarning">
            This token will not be displayed again.<br />
            If you lose it, you will need to generate a new one.
          </section>
          <gr-button link="" class="closeButton" @click=${this.closeModal}
            >Close</gr-button
          >
        </div>
      </dialog>`;
  }

  private renderToken(tokenInfo: TokenInfo) {
    return html` <tr class=${this.isTokenExpired(tokenInfo) ? 'expired' : ''}>
      <td class="idColumn">${tokenInfo.id}</td>
      <td class="expirationColumn">
        <gr-date-formatter
          withTooltip
          showDateAndTime
          dateFormat="STD"
          .dateStr=${tokenInfo.expiration}
        ></gr-date-formatter>
      </td>
      <td>
        <gr-button
          id="deleteButton"
          @click=${() => this.handleDeleteTap(tokenInfo.id)}
          >Delete</gr-button
        >
      </td>
    </tr>`;
  }

  private renderFooterRow() {
    return html`
      <tr>
        <th style="vertical-align: top;">
          <iron-input
            id="newToken"
            .bindValue=${this.newTokenId}
            @bind-value-changed=${(e: BindValueChangeEvent) => {
              this.newTokenId = e.detail.value ?? '';
            }}
          >
            <input
              is="iron-input"
              placeholder="New Token ID"
              @keydown=${this.handleInputKeydown}
            />
          </iron-input>
        </th>
        <th style="vertical-align: top;">
          <iron-input
            .bindValue=${this.newLifetime}
            @bind-value-changed=${(e: BindValueChangeEvent) => {
              this.newLifetime = e.detail.value ?? '';
            }}
          >
            <input
              class="lifeTimeInput"
              is="iron-input"
              placeholder="Lifetime (e.g. 30d)"
              @keydown=${this.handleInputKeydown}
            />
          </iron-input></br>
          (Max. allowed lifetime: ${this.formatDuration(this.maxLifetime)})
        </th>
        <th>
          <gr-button
            id="generateButton"
            link=""
            ?disabled=${!this.newTokenId.length}
            @click=${this.handleGenerateTap}
            >Generate</gr-button
          >
        </th>
      </tr>
    `;
  }

  private formatDuration(durationMinutes: string) {
    if (!durationMinutes) return '';
    if (durationMinutes === 'unlimited') return 'unlimited';
    let minutes = parseInt(durationMinutes, 10);
    let hours = Math.floor(minutes / 60);
    minutes = minutes % 60;
    let days = Math.floor(hours / 24);
    hours = hours % 24;
    const years = Math.floor(days / 365);
    days = days % 365;
    let formatted = '';
    if (years) formatted += `${years}y `;
    if (days) formatted += `${days}d `;
    if (hours) formatted += `${hours}h `;
    if (minutes) formatted += `${minutes}m`;
    return formatted;
  }

  private isTokenExpired(tokenInfo: TokenInfo) {
    if (!tokenInfo.expiration) return false;
    return new Date(tokenInfo.expiration.replace(' ', 'T') + 'Z') < new Date();
  }

  private handleInputKeydown(e: KeyboardEvent) {
    if (e.key === 'Enter') {
      e.stopPropagation();
      this.handleGenerateTap();
    }
  }

  private handleGenerateTap() {
    this.generateButton.disabled = true;
    this.status = 'Generating...';
    this.generatedAuthTokenModal?.showModal();
    this.pluginRestApi
      .put<TokenInfo>(
        `/a/config/server/serviceuser~serviceusers/${this.serviceUserId}/tokens/${this.newTokenId}`,
        {
          id: this.newTokenId,
          lifetime: this.newLifetime,
        },
      )
      .catch(err => {
        this.closeModal();
        this.dispatchEvent(
          new CustomEvent('show-error', {
            detail: {message: err},
            composed: true,
            bubbles: true,
          })
        );
      })
      .then(newToken => {
        if (newToken) {
          this.generatedAuthToken = newToken;
          this.status = undefined;
          this.fetchTokens();
          this.tokenInput.value = '';
          this.tokenLifetime.value = '';
        } else {
          this.status = 'Failed to generate';
        }
      })
      .finally(() => {
        this.generateButton.disabled = false;
      });
  }

  private handleDeleteTap(id: string) {
    this.pluginRestApi
      .delete(
        `/a/config/server/serviceuser~serviceusers/${this.serviceUserId}/tokens/${id}`)
      .catch(err => {
        this.dispatchEvent(
          new CustomEvent('show-error', {
            detail: {message: err},
            composed: true,
            bubbles: true,
          })
        );
      })
      .then(() => {
        this.fetchTokens();
      });
  }

  private generatedAuthTokenModalClosed() {
    this.status = undefined;
    this.generatedAuthToken = undefined;
  }

  private closeModal() {
    this.generatedAuthTokenModal?.close();
  }
}
