/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../gr-error-dialog/gr-error-dialog';
import '../../shared/gr-alert/gr-alert';
import {getBaseUrl} from '../../../utils/url-util';
import {getAppContext} from '../../../services/app-context';
import {GrErrorDialog} from '../gr-error-dialog/gr-error-dialog';
import {GrAlert} from '../../shared/gr-alert/gr-alert';
import {ErrorType} from '../../../types/types';
import {AccountId} from '../../../types/common';
import {
  AuthErrorEvent,
  NetworkErrorEvent,
  ServerErrorEvent,
  ShowAlertEventDetail,
  ShowErrorEvent,
} from '../../../types/events';
import {windowLocationReload} from '../../../utils/dom-util';
import {debounce, DelayedTask} from '../../../utils/async-util';
import {fireIronAnnounce} from '../../../utils/event-util';
import {LitElement, html} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {authServiceToken} from '../../../services/gr-auth/gr-auth';
import {resolve} from '../../../models/dependency';
import {modalStyles} from '../../../styles/gr-modal-styles';
import {ironAnnouncerRequestAvailability} from '../../polymer-util';

const HIDE_ALERT_TIMEOUT_MS = 10 * 1000;
const CHECK_SIGN_IN_INTERVAL_MS = 60 * 1000;
const STALE_CREDENTIAL_THRESHOLD_MS = 10 * 60 * 1000;
const SIGN_IN_WIDTH_PX = 690;
const SIGN_IN_HEIGHT_PX = 500;
const TOO_MANY_FILES = 'too many files to find conflicts';
const AUTHENTICATION_REQUIRED = 'Authentication required\n';

// Bigger number has higher priority
const ErrorTypePriority = {
  [ErrorType.AUTH]: 3,
  [ErrorType.NETWORK]: 2,
  [ErrorType.GENERIC]: 1,
};

interface ErrorMsg {
  errorText?: string;
  status?: number;
  statusText?: string;
  url?: string;
  trace?: string | null;
  tip?: string;
}

export const __testOnly_ErrorType = ErrorType;

export function constructServerErrorMsg({
  errorText,
  status,
  statusText,
  url,
  trace,
  tip,
}: ErrorMsg) {
  let err = '';
  if (tip) {
    err += `${tip}\n\n`;
  }
  err += `Error ${status}`;
  if (statusText) {
    err += ` (${statusText})`;
  }
  if (errorText || url) {
    err += ': ';
  }
  if (errorText) {
    err += errorText;
  }
  if (url) {
    err += `\nEndpoint: ${url}`;
  }
  if (trace) {
    err += `\nTrace Id: ${trace}`;
  }
  return err;
}

@customElement('gr-error-manager')
export class GrErrorManager extends LitElement {
  /**
   * The ID of the account that was logged in when the app was launched. If
   * not set, then there was no account at launch.
   */
  @state() knownAccountId?: AccountId | null;

  @state() alertElement: GrAlert | null = null;

  @state() hideAlertHandle: number | null = null;

  @state() refreshingCredentials = false;

  @query('#signInModal') signInModal!: HTMLDialogElement;

  @query('#errorDialog') errorDialog!: GrErrorDialog;

  @query('#errorModal') errorModal!: HTMLDialogElement;

  /**
   * The time (in milliseconds) since the most recent credential check.
   */
  @state() lastCredentialCheck: number = Date.now();

  @property({type: String})
  loginUrl = '/login';

  @property({type: String})
  loginText = 'Sign in';

  private readonly reporting = getAppContext().reportingService;

  private readonly getAuthService = resolve(this, authServiceToken);

  private readonly restApiService = getAppContext().restApiService;

  private checkLoggedInTask?: DelayedTask;

  override connectedCallback() {
    super.connectedCallback();
    document.addEventListener('server-error', this.handleServerError);
    document.addEventListener('network-error', this.handleNetworkError);
    document.addEventListener('show-alert', this.handleShowAlert);
    document.addEventListener('hide-alert', this.hideAlert);
    document.addEventListener('show-error', this.handleShowErrorDialog);
    document.addEventListener('visibilitychange', this.handleVisibilityChange);
    document.addEventListener('show-auth-required', this.handleAuthRequired);
    document.addEventListener('auth-error', this.handleAuthError);

    ironAnnouncerRequestAvailability();
  }

  override disconnectedCallback() {
    this.clearHideAlertHandle();
    document.removeEventListener('server-error', this.handleServerError);
    document.removeEventListener('network-error', this.handleNetworkError);
    document.removeEventListener('show-alert', this.handleShowAlert);
    document.removeEventListener('hide-alert', this.hideAlert);
    document.removeEventListener('show-error', this.handleShowErrorDialog);
    document.removeEventListener(
      'visibilitychange',
      this.handleVisibilityChange
    );
    document.removeEventListener('show-auth-required', this.handleAuthRequired);
    this.checkLoggedInTask?.cancel();

    document.removeEventListener('auth-error', this.handleAuthError);
    super.disconnectedCallback();
  }

  static override get styles() {
    return [modalStyles];
  }

  override render() {
    return html`
      <dialog id="errorModal" tabindex="-1">
        <gr-error-dialog
          id="errorDialog"
          @dismiss=${() => this.errorModal.close()}
          .loginUrl=${this.loginUrl}
          .loginText=${this.loginText}
        ></gr-error-dialog>
      </dialog>
      <dialog
        id="signInModal"
        @keydown=${(e: KeyboardEvent) => {
          if (e.key === 'Escape') {
            e.preventDefault();
            e.stopPropagation();
          }
        }}
        tabindex="-1"
      >
        <gr-dialog
          id="signInDialog"
          confirm-label="Sign In"
          @confirm=${() => {
            this.createLoginPopup();
          }}
          cancel-label=""
        >
          <div class="header" slot="header">Refresh Credentials</div>
        </gr-dialog>
      </dialog>
    `;
  }

  private shouldSuppressError(msg: string) {
    return msg.includes(TOO_MANY_FILES);
  }

  private readonly handleAuthRequired = () => {
    this.showAuthErrorAlert(
      'Log in is required to perform that action.',
      'Log in.'
    );
  };

  private handleAuthError = (event: AuthErrorEvent) => {
    this.signInModal.showModal();
    this.showAuthErrorAlert(event.detail.message, event.detail.action);
  };

  private readonly handleServerError = (e: ServerErrorEvent) => {
    const {request, response} = e.detail;
    response.text().then(errorText => {
      const url = request && (request.anonymizedUrl || request.url);
      const {status, statusText} = response;
      if (
        response.status === 403 &&
        !this.getAuthService().isAuthed &&
        errorText === AUTHENTICATION_REQUIRED
      ) {
        // if not authed previously, this is trying to access auth required APIs
        // show auth required alert
        this.handleAuthRequired();
      } else if (
        response.status === 403 &&
        this.getAuthService().isAuthed &&
        errorText === AUTHENTICATION_REQUIRED
      ) {
        // The app was logged at one point and is now getting auth errors.
        // This indicates the auth token may no longer valid.
        // Re-check on auth
        this.getAuthService().clearCache();
        this.restApiService.getLoggedIn();
      } else if (!this.shouldSuppressError(errorText)) {
        const trace =
          response.headers && response.headers.get('X-Gerrit-Trace');
        if (response.status === 404) {
          this.showNotFoundMessageWithTip({
            status,
            statusText,
            errorText,
            url,
            trace,
          });
        } else if (response.status === 429) {
          this.showQuotaExceeded({status, statusText});
        } else {
          this.showErrorDialog(
            constructServerErrorMsg({
              status,
              statusText,
              errorText,
              url,
              trace,
            })
          );
        }
      }
      this.reporting.error('Server error', new Error(errorText));
    });
  };

  private showNotFoundMessageWithTip({
    status,
    statusText,
    errorText,
    url,
    trace,
  }: ErrorMsg) {
    this.restApiService.getLoggedIn().then(isLoggedIn => {
      const tip = isLoggedIn
        ? 'You might have not enough privileges.'
        : 'You might have not enough privileges. Sign in and try again.';
      this.showErrorDialog(
        constructServerErrorMsg({
          status,
          statusText,
          errorText,
          url,
          trace,
          tip,
        }),
        {
          showSignInButton: !isLoggedIn,
        }
      );
    });
  }

  private showQuotaExceeded({status, statusText}: ErrorMsg) {
    const tip = 'Try again later';
    const errorText = 'Too many requests from this client';
    this.showErrorDialog(
      constructServerErrorMsg({
        status,
        statusText,
        errorText,
        tip,
      })
    );
  }

  private readonly handleShowAlert = (e: CustomEvent<ShowAlertEventDetail>) => {
    this._showAlert(
      e.detail.message,
      e.detail.action,
      e.detail.callback,
      e.detail.dismissOnNavigation,
      undefined,
      e.detail.showDismiss
    );
  };

  private readonly handleNetworkError = (e: NetworkErrorEvent) => {
    this._showAlert('Server unavailable');
    this.reporting.error('Network error', new Error(e.detail.error.message));
  };

  // TODO(dhruvsri): allow less priority alerts to override high priority alerts
  // In some use cases we may want generic alerts to show along/over errors
  // private but used in tests
  canOverride(incoming = ErrorType.GENERIC, existing = ErrorType.GENERIC) {
    return ErrorTypePriority[incoming] >= ErrorTypePriority[existing];
  }

  _showAlert(
    text: string,
    actionText?: string,
    actionCallback?: () => void,
    dismissOnNavigation?: boolean,
    type?: ErrorType,
    showDismiss?: boolean
  ) {
    if (this.alertElement) {
      // check priority before hiding
      if (!this.canOverride(type, this.alertElement.type)) return;
      this.hideAlert();
    }

    this.clearHideAlertHandle();
    if (dismissOnNavigation) {
      // Persist alert until navigation.
      document.addEventListener('location-change', this.hideAlert);
    } else {
      this.hideAlertHandle = window.setTimeout(
        this.hideAlert,
        HIDE_ALERT_TIMEOUT_MS
      );
    }
    const el = this.createToastAlert(showDismiss);
    el.show(text, actionText, actionCallback);
    this.alertElement = el;
    fireIronAnnounce(this, `Alert: ${text}`);
    this.reporting.reportInteraction('show-alert', {text});
  }

  private readonly hideAlert = () => {
    if (!this.alertElement) {
      return;
    }

    this.alertElement.hide();
    this.alertElement = null;

    // Remove listener for page navigation, if it exists.
    document.removeEventListener('location-change', this.hideAlert);
  };

  private clearHideAlertHandle() {
    if (this.hideAlertHandle !== null) {
      window.clearTimeout(this.hideAlertHandle);
      this.hideAlertHandle = null;
    }
  }

  // private but used in tests
  showAuthErrorAlert(errorText: string, actionText?: string) {
    // hide any existing alert like `reload`
    // as auth error should have the highest priority
    if (this.alertElement) {
      this.alertElement.hide();
    }

    this.alertElement = this.createToastAlert();
    this.alertElement.type = ErrorType.AUTH;
    this.alertElement.show(errorText, actionText, () =>
      this.createLoginPopup()
    );
    fireIronAnnounce(this, errorText);
    this.reporting.reportInteraction('show-auth-error', {text: errorText});
    this.refreshingCredentials = true;
    this.requestCheckLoggedIn();
    if (!document.hidden) {
      this.handleVisibilityChange();
    }
  }

  // private but used in tests
  createToastAlert(showDismiss?: boolean) {
    const el = document.createElement('gr-alert');
    el.owner = this;
    el.toast = true;
    el.showDismiss = !!showDismiss;
    return el;
  }

  private readonly handleVisibilityChange = () => {
    // Ignore when the page is transitioning to hidden (or hidden is undefined).
    if (document.hidden !== false) return;

    // If not currently refreshing credentials and the credentials are old,
    // request them to confirm their validity or (display an auth toast if it
    // fails).
    const timeSinceLastCheck = Date.now() - this.lastCredentialCheck;
    if (
      !this.refreshingCredentials &&
      this.knownAccountId !== undefined &&
      timeSinceLastCheck > STALE_CREDENTIAL_THRESHOLD_MS
    ) {
      this.reporting.reportInteraction('visibility-sign-in-check');
      this.lastCredentialCheck = Date.now();

      // check auth status in case:
      // - user signed out
      // - user switched account
      this.checkSignedIn();
    }
  };

  // private but used in tests
  requestCheckLoggedIn() {
    this.checkLoggedInTask = debounce(
      this.checkLoggedInTask,
      () => this.checkSignedIn(),
      CHECK_SIGN_IN_INTERVAL_MS
    );
  }

  // private but used in tests
  checkSignedIn() {
    this.lastCredentialCheck = Date.now();

    // force to refetch account info
    this.restApiService.invalidateAccountsCache();
    this.getAuthService().clearCache();

    this.restApiService.getLoggedIn().then(isLoggedIn => {
      if (!this.refreshingCredentials) return;

      if (!isLoggedIn) {
        // check later
        // 1. guest mode
        // 2. or signed out
        // in case #2, auth-error is taken care of separately
        this.requestCheckLoggedIn();
      } else {
        this.restApiService.getAccount().then(account => {
          if (this.refreshingCredentials) {
            // If the credentials were refreshed but the account is different,
            // then reload the page completely.
            if (account?._account_id !== this.knownAccountId) {
              this.reporting.reportInteraction('sign-in-window-reload', {
                oldAccount: !!this.knownAccountId,
                newAccount: !!account?._account_id,
              });
              this.reloadPage();
              return;
            }

            this.handleCredentialRefreshed();
          }
        });
      }
    });
  }

  reloadPage() {
    windowLocationReload();
  }

  private createLoginPopup() {
    const left = window.screenLeft + (window.outerWidth - SIGN_IN_WIDTH_PX) / 2;
    const top = window.screenTop + (window.outerHeight - SIGN_IN_HEIGHT_PX) / 2;
    const options = [
      `width=${SIGN_IN_WIDTH_PX}`,
      `height=${SIGN_IN_HEIGHT_PX}`,
      `left=${left}`,
      `top=${top}`,
    ];
    window.open(
      getBaseUrl() + '/login/%3FcloseAfterLogin',
      '_blank',
      options.join(',')
    );
    window.addEventListener('focus', this.handleWindowFocus);
  }

  // private but used in tests
  handleCredentialRefreshed() {
    window.removeEventListener('focus', this.handleWindowFocus);
    this.refreshingCredentials = false;
    this.hideAlert();
    this._showAlert('Credentials refreshed.');
    this.signInModal.close();

    // Clear the cache for auth
    this.getAuthService().clearCache();
  }

  private readonly handleWindowFocus = () => {
    this.checkLoggedInTask?.flush();
  };

  private readonly handleShowErrorDialog = (e: ShowErrorEvent) => {
    this.showErrorDialog(e.detail.message);
  };

  // private but used in tests
  showErrorDialog(message: string, options?: {showSignInButton?: boolean}) {
    this.reporting.reportErrorDialog(message);
    this.errorDialog.text = message;
    this.errorDialog.showSignInButton = !!options && !!options.showSignInButton;
    if (this.errorModal.hasAttribute('open')) {
      this.errorModal.close();
    }
    this.errorModal.showModal();
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-error-manager': GrErrorManager;
  }
}
