/**
 * @license
 * Copyright (C) 2020 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 {CodeOwnersModelMixin} from './code-owners-model-mixin';
import {showPluginFailedMessage} from './code-owners-banner';
import {isPluginErrorState, UserRole} from './code-owners-model';
import {css, html, LitElement} from 'lit';
import {customElement} from 'lit/decorators';
import {when} from 'lit/directives/when';
import {
  ApprovalInfo,
  DetailedLabelInfo,
} from '@gerritcodereview/typescript-api/rest-api';
import {OwnerStatus} from './code-owners-api';

const base = CodeOwnersModelMixin(LitElement);

export const OWNER_REQUIREMENT_VALUE = 'owner-requirement-value';
/**
 * Owner requirement control for `submit-requirement-item-code-owners` endpoint.
 *
 * This will show the status and suggest owners button next to
 * the code-owners submit requirement.
 */
@customElement(OWNER_REQUIREMENT_VALUE)
export class OwnerRequirementValue extends base {
  static override get styles() {
    return [
      css`
        :host {
          --gr-button: {
            padding: 0px;
          }
        }
        p.loading {
          display: flex;
          align-content: center;
          align-items: center;
          justify-content: center;
        }
        .loadingSpin {
          display: inline-block;
          margin-right: var(--spacing-m);
          width: 18px;
          height: 18px;
        }
        gr-button {
          padding-left: var(--spacing-m);
        }
        gr-button::part(paper-button) {
          padding: 0 var(--spacing-s);
        }
        a {
          text-decoration: none;
        }
      `,
    ];
  }

  override render() {
    // Compute whether plugin failed first because it might mean some of the
    // model parameters are not set which would result in a loading screen.
    if (this.pluginFailed()) {
      return html`
        <span>Code-owners plugin has failed</span>
        <gr-button link @click=${this.showFailDetails}>Details</gr-button>
      `;
    }
    if (!this.branchConfig || !this.status || !this.userRole) {
      return html`
        <p class="loading">
          <span class="loadingSpin"></span>
          Loading status ...
        </p>
      `;
    }

    if (this.status.newerPatchsetUploaded) {
      return html`<span>A newer patch set has been uploaded.</span>`;
    }
    const overrideInfoUrl = this.computeOverrideInfoUrl();
    const statusCount = this.getStatusCount();
    this.reporting?.reportLifeCycle('owners-submit-requirement-summary-shown', {
      ...statusCount,
      user_role: this.userRole,
    });
    return html`
      <span>${this.computeStatusText(statusCount)}</span>
      ${when(
        !!overrideInfoUrl,
        () => html`
          <a
            @click=${this.reportDocClick}
            href=${overrideInfoUrl}
            target="_blank"
          >
            <gr-icon
              icon="help"
              title="Documentation for overriding code owners"
            ></gr-icon>
          </a>
        `
      )}
      ${when(
        this.computeIsSignedInUser(this.userRole),
        () => html`
          <gr-button link @click=${this.openReplyDialog}>
            ${this.getSuggestOwnersText(statusCount)}
          </gr-button>
        `
      )}
    `;
  }

  override loadPropertiesAfterModelChanged() {
    super.loadPropertiesAfterModelChanged();
    this.reporting?.reportLifeCycle('owners-submit-requirement-summary-start');
    this.modelLoader?.loadBranchConfig();
    this.modelLoader?.loadStatus();
    this.modelLoader?.loadUserRole();
  }

  private computeIsSignedInUser(userRole: UserRole) {
    return userRole && userRole !== UserRole.ANONYMOUS;
  }

  private pluginFailed() {
    return this.pluginStatus && isPluginErrorState(this.pluginStatus.state);
  }

  private computeOverrideInfoUrl() {
    if (!this.branchConfig) {
      return '';
    }
    return this.branchConfig.general &&
      this.branchConfig.general.override_info_url
      ? this.branchConfig.general.override_info_url
      : '';
  }

  private computeIsOverriden() {
    if (
      !this.change ||
      !this.branchConfig ||
      !this.branchConfig['override_approval']
    ) {
      // no override labels configured
      return false;
    }

    for (const requiredApprovalInfo of this.branchConfig['override_approval']) {
      const overridenLabel = requiredApprovalInfo.label;
      const overridenValue = Number(requiredApprovalInfo.value);
      if (isNaN(overridenValue)) continue;

      if (this.change.labels?.[overridenLabel]) {
        const votes =
          (this.change.labels[overridenLabel] as DetailedLabelInfo).all || [];
        if (
          votes.find((v: ApprovalInfo) => Number(v.value) >= overridenValue)
        ) {
          return true;
        }
      }
    }

    // otherwise always reset it to false
    return false;
  }

  private getSuggestOwnersText(statusCount: {
    missing: number;
    pending: number;
    approved: number;
  }) {
    return statusCount && statusCount.missing === 0
      ? 'Add owners'
      : 'Suggest owners';
  }

  private getStatusCount() {
    return (this.status?.rawStatuses ?? []).reduce(
      (prev, cur) => {
        const oldPathStatus = cur.old_path_status;
        const newPathStatus = cur.new_path_status;
        if (newPathStatus && this.isMissing(newPathStatus.status)) {
          prev.missing++;
        } else if (newPathStatus && this.isPending(newPathStatus.status)) {
          prev.pending++;
        } else if (oldPathStatus) {
          // check oldPath if newPath approved or the file is deleted
          if (this.isMissing(oldPathStatus.status)) {
            prev.missing++;
          } else if (this.isPending(oldPathStatus.status)) {
            prev.pending++;
          }
        } else {
          prev.approved++;
        }
        return prev;
      },
      {missing: 0, pending: 0, approved: 0}
    );
  }

  private computeStatusText(statusCount: {
    missing: number;
    pending: number;
    approved: number;
  }) {
    if (this.model === undefined || this.change === undefined) return '';
    const isOverriden = this.computeIsOverriden();
    const statusText = [];
    if (statusCount.missing) {
      statusText.push(`${statusCount.missing} missing`);
    }

    if (statusCount.pending) {
      statusText.push(`${statusCount.pending} pending`);
    }

    if (!statusText.length) {
      statusText.push(isOverriden ? 'Approved (Owners-Override)' : 'Approved');
    }

    return statusText.join(', ');
  }

  private isMissing(status: OwnerStatus | undefined) {
    return status === OwnerStatus.INSUFFICIENT_REVIEWERS;
  }

  private isPending(status: OwnerStatus | undefined) {
    return status === OwnerStatus.PENDING;
  }

  private openReplyDialog() {
    this.model!.setShowSuggestions(true);
    this.dispatchEvent(
      new CustomEvent('open-reply-dialog', {
        detail: {},
        composed: true,
        bubbles: true,
      })
    );
    this.reporting?.reportInteraction(
      'suggest-owners-from-submit-requirement',
      {
        user_role: this.userRole,
      }
    );
  }

  private reportDocClick() {
    this.reporting?.reportInteraction('code-owners-doc-click', {
      section: 'no owners found',
    });
  }

  private showFailDetails() {
    showPluginFailedMessage(this, this.pluginStatus!);
  }
}
