/**
 * @license
 * Copyright (C) 2024 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 {css, html, LitElement, nothing, PropertyValues, CSSResult} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {
  AccountInfo,
  ApprovalInfo,
  ChangeInfo,
  ChangeStatus,
  GroupInfo,
  LabelInfo,
  isDetailedLabelInfo,
  EmailAddress,
  ReviewerState,
} from '@gerritcodereview/typescript-api/rest-api';
import {
  FilesOwners,
  isOwner,
  OwnersLabels,
  hasOwnersSubmitRequirement,
} from './owners-service';
import {
  FileOwnership,
  FileStatus,
  OwnerOrGroupOwner,
  PatchRange,
  UserRole,
} from './owners-model';
import {query} from './utils';
import {GrAccountLabel} from './gerrit-model';
import {OwnersMixin} from './owners-mixin';

const STATUS_CODE = {
  MISSING: 'missing',
  APPROVED: 'approved',
  AUTO_APPROVED: 'autoApproved',
};

const STATUS_ICON = {
  [STATUS_CODE.MISSING]: 'schedule',
  [STATUS_CODE.APPROVED]: 'check',
  [STATUS_CODE.AUTO_APPROVED]: 'published_with_changes',
};

const FILE_STATUS = {
  [FileStatus.NEEDS_APPROVAL]: STATUS_CODE.MISSING,
  [FileStatus.APPROVED]: STATUS_CODE.APPROVED,
  [FileStatus.AUTO_APPROVED]: STATUS_CODE.AUTO_APPROVED,
};

const HOVER_HEADING = {
  [STATUS_CODE.MISSING]: "Needs Owners' Approval",
  [STATUS_CODE.APPROVED]: 'Approved by Owners',
  [STATUS_CODE.AUTO_APPROVED]: 'Auto-approved by Owners',
};

const DISPLAY_OWNERS_FOR_FILE_LIMIT = 5;
const LIMITED_FILES_OWNERS_TOOLTIP = `File owners limited to first ${DISPLAY_OWNERS_FOR_FILE_LIMIT} accounts.`;

const common = OwnersMixin(LitElement);

class FilesCommon extends common {
  protected override willUpdate(changedProperties: PropertyValues): void {
    super.willUpdate(changedProperties);

    this.hidden = shouldHide(
      this.change,
      this.patchRange,
      this.filesOwners,
      this.user?.role
    );
  }

  protected static commonStyles(): CSSResult[] {
    return [window?.Gerrit?.styles.font as CSSResult];
  }
}

export const FILES_OWNERS_COLUMN_HEADER = 'files-owners-column-header';
@customElement(FILES_OWNERS_COLUMN_HEADER)
export class FilesColumnHeader extends FilesCommon {
  static override get styles() {
    return [
      ...FilesCommon.commonStyles(),
      css`
        :host() {
          display: block;
          padding-right: var(--spacing-m);
          width: 4em;
        }
        :host[hidden] {
          display: none;
        }
      `,
    ];
  }

  override render() {
    if (this.hidden) return nothing;
    return html`<div>Status</div>`;
  }
}

/**
 * It has to be part of this file as components defined in dedicated files are not visible
 */
@customElement('gr-owner')
export class GrOwner extends LitElement {
  @property({type: Object})
  owner?: AccountInfo;

  @property({type: Object})
  groupOwner?: GroupInfo;

  @property({type: Object})
  approval?: ApprovalInfo;

  @property({type: Object})
  info?: LabelInfo;

  @property({type: String})
  email?: EmailAddress;

  static override get styles() {
    return [
      css`
        .container {
          display: flex;
        }
        gr-vote-chip {
          margin-left: 5px;
          --gr-vote-chip-width: 14px;
          --gr-vote-chip-height: 14px;
        }
        gr-tooltip-content {
          display: inline-block;
        }
      `,
    ];
  }

  override render() {
    if (!this.owner && !this.groupOwner) {
      return nothing;
    }

    const isAccountOwner = this.owner !== undefined;
    const ownerLabel = isAccountOwner
      ? this.owner?._account_id
        ? html`<gr-account-label .account=${this.owner}></gr-account-label>`
        : html`<span>${this.owner?.display_name}</span>`
      : html`<span>Group: ${this.groupOwner?.name}</span>`;

    const voteChip =
      isAccountOwner && this.approval
        ? html` <gr-vote-chip
            .vote=${this.approval}
            .label=${this.info}
          ></gr-vote-chip>`
        : nothing;

    // allow user to copy what is available:
    // * email or name (if available) for AccountInfo owner type
    // * group name for GroupInfo owner type
    const [copyText, copyTooltip] = isAccountOwner
      ? this.email || this.owner?.display_name
        ? [
            this.email ?? this.owner?.display_name,
            this.email ? 'email' : 'name',
          ]
        : [nothing, nothing]
      : [this.groupOwner?.name, 'group name'];
    const copy = copyText
      ? html` <gr-copy-clipboard
          .text=${copyText}
          hasTooltip
          hideinput
          buttonTitle="Copy owner's ${copyTooltip} to clipboard"
        ></gr-copy-clipboard>`
      : nothing;

    return html`
      <div class="container">${ownerLabel} ${voteChip} ${copy}</div>
    `;
  }

  override async updated(changedProperties: PropertyValues) {
    super.updated(changedProperties);

    if (changedProperties.has('owner')) {
      if (this.owner && !this.email) {
        const accountLabel = query<GrAccountLabel>(this, 'gr-account-label');
        if (!accountLabel) {
          return;
        }

        const updateOwner = await accountLabel
          ?.getAccountsModel()
          ?.fillDetails(this.owner);
        this.email = updateOwner?.email;
      }
    }
  }
}

export const FILES_OWNERS_COLUMN_CONTENT = 'files-owners-column-content';
@customElement(FILES_OWNERS_COLUMN_CONTENT)
export class FilesColumnContent extends FilesCommon {
  @property({type: String})
  path?: string;

  @property({type: String})
  oldPath?: string;

  @property({type: String, reflect: true, attribute: 'file-status'})
  fileStatus?: string;

  private owners?: OwnerOrGroupOwner[];

  // taken from Gerrit's common-util.ts
  private uniqueId = Math.random().toString(36).substring(2);

  static override get styles() {
    return [
      ...FilesCommon.commonStyles(),
      css`
        :host {
          display: flex;
          padding-right: var(--spacing-m);
          width: 4em;
          text-align: center;
        }
        :host[hidden] {
          display: none;
        }
        gr-icon {
          padding: var(--spacing-xs) 0px;
          margin-left: 9px;
        }
        :host([file-status='approved']) gr-icon.status {
          color: var(--positive-green-text-color);
        }
        :host([file-status='autoApproved']) gr-icon.status {
          color: var(--positive-green-text-color);
        }
        :host([file-status='missing']) gr-icon.status {
          color: #ffa62f;
        }
      `,
    ];
  }

  override render() {
    if (this.hidden || !this.fileStatus) {
      return nothing;
    }

    const icon = STATUS_ICON[this.fileStatus];
    return html`
      <gr-icon
        id="${this.pathId()}"
        class="status"
        icon=${icon}
        aria-hidden="true"
      ></gr-icon>
      ${this.renderFileOwners()}
    `;
  }

  private pathId(): string {
    return `path-${this.uniqueId}`;
  }

  private renderFileOwners() {
    const owners = this.owners ?? [];
    const splicedOwners = owners.splice(0, DISPLAY_OWNERS_FOR_FILE_LIMIT);
    const showEllipsis = owners.length > DISPLAY_OWNERS_FOR_FILE_LIMIT;
    const heading = HOVER_HEADING[this.fileStatus ?? STATUS_CODE.MISSING];
    // inlining <style> here is ugly but an alternative would be to copy the `HovercardMixin` from Gerrit and implement hoover from scratch
    return html`<gr-hovercard for="${this.pathId()}">
      <style>
        #file-owners-hoovercard {
          min-width: 256px;
          max-width: 256px;
          margin: -10px;
          padding: var(--spacing-xl) 0 var(--spacing-m) 0;
        }
        h3 {
          font: inherit;
        }
        .heading-3 {
          margin-left: -2px;
          font-family: var(--header-font-family);
          font-size: var(--font-size-h3);
          font-weight: var(--font-weight-h3);
          line-height: var(--line-height-h3);
        }
        .row {
          display: flex;
        }
        div.section {
          margin: 0 var(--spacing-xl) var(--spacing-m) var(--spacing-xl);
          display: flex;
          align-items: center;
        }
        div.sectionIcon {
          flex: 0 0 30px;
        }
        div.sectionIcon gr-icon {
          position: relative;
        }
        div.sectionContent .row {
          margin-left: 2px;
        }
        div.sectionContent .notLast {
          margin-bottom: 2px;
        }
        div.sectionContent .ellipsis {
          margin-left: 5px;
        }
      </style>
      <div id="file-owners-hoovercard">
        <div class="section">
          <div class="sectionIcon">
            <gr-icon class="status" icon="info" aria-hidden="true"></gr-icon>
          </div>
          <div class="sectionContent">
            <h3 class="name heading-3">
              <span>${heading}</span>
            </h3>
          </div>
        </div>
        <div class="section">
          <div class="sectionContent">
            ${splicedOwners.map((owner, idx) => {
              const [approval, info] =
                computeApprovalAndInfo(
                  owner,
                  this.filesOwners?.owners_labels ?? {},
                  this.change
                ) ?? [];
              return html`
                <div
                  class="row ${showEllipsis || idx + 1 < splicedOwners.length
                    ? 'notLast'
                    : ''}"
                >
                  <gr-owner
                    .owner=${owner.owner}
                    .groupOwner=${owner.groupOwner}
                    .approval=${approval}
                    .info=${info}
                    .email=${owner.owner ? owner.owner.email : nothing}
                  ></gr-owner>
                </div>
              `;
            })}
            ${showEllipsis
              ? html`
                <gr-tooltip-content
                  title=${LIMITED_FILES_OWNERS_TOOLTIP}
                  aria-label="limited-file-onwers"
                  aria-description=${LIMITED_FILES_OWNERS_TOOLTIP}
                  has-tooltip
                >
                  <div class="row ellipsis">...</div>
                </gt-tooltip-content>`
              : nothing}
          </div>
        </div>
      </div>
    </gr-hovercard>`;
  }

  protected override willUpdate(changedProperties: PropertyValues): void {
    super.willUpdate(changedProperties);
    this.computeFileState();
  }

  private computeFileState(): void {
    const fileOwnership = getFileOwnership(this.path, this.filesOwners);
    if (!fileOwnership || fileOwnership.fileStatus === FileStatus.NOT_OWNED) {
      this.fileStatus = undefined;
      this.owners = undefined;
      return;
    }

    this.fileStatus = FILE_STATUS[fileOwnership.fileStatus];
    const accounts = getChangeAccounts(this.change);

    this.owners = (fileOwnership.owners ?? []).map(owner => {
      if (isOwner(owner)) {
        return {
          owner:
            accounts.byAccountId.get(owner.id) ??
            ({_account_id: owner.id} as unknown as AccountInfo),
        } as unknown as OwnerOrGroupOwner;
      }

      const groupPrefix = 'group/';
      if (owner.name.startsWith(groupPrefix)) {
        return {
          groupOwner: {
            name: owner.name.substring(groupPrefix.length),
          } as unknown as GroupInfo,
        } as unknown as OwnerOrGroupOwner;
      }

      // when `owners.expandGroups = false` then neither group nor account
      // will be expanded therefore try to match account with change's available
      // accounts through email without domain or by full name
      // finally construct `AccountInfo` just with a `name` property
      const accountOwner =
        accounts.byEmailWithoutDomain.get(owner.name) ??
        accounts.byFullName.get(owner.name) ??
        ({display_name: owner.name} as unknown as AccountInfo);
      return {owner: accountOwner} as unknown as OwnerOrGroupOwner;
    });
  }
}

export function shouldHide(
  change?: ChangeInfo,
  patchRange?: PatchRange,
  filesOwners?: FilesOwners,
  userRole?: UserRole
): boolean {
  // don't show owners when no change or change is merged
  if (change === undefined || patchRange === undefined) {
    return true;
  }
  if (
    change.status === ChangeStatus.ABANDONED ||
    change.status === ChangeStatus.MERGED
  ) {
    return true;
  }

  // Note: in some special cases, patchNum is undefined on latest patchset
  // like after publishing the edit, still show for them
  // TODO: this should be fixed in Gerrit
  if (patchRange?.patchNum === undefined) return false;

  // only show if its latest patchset
  const latestPatchset = change.revisions![change.current_revision!];
  if (`${patchRange.patchNum}` !== `${latestPatchset._number}`) {
    return true;
  }

  // show owners when they apply to the change and for logged in user
  if (
    hasOwnersSubmitRequirement(change) &&
    filesOwners &&
    (filesOwners.files ||
      filesOwners.files_approved ||
      filesOwners.files_auto_approved)
  ) {
    return !userRole || userRole === UserRole.ANONYMOUS;
  }
  return true;
}

export function getFileOwnership(
  path?: string,
  filesOwners?: FilesOwners
): FileOwnership | undefined {
  if (path === undefined || filesOwners === undefined) {
    return undefined;
  }

  const fileOwners = (filesOwners.files ?? {})[path];
  const fileApprovers = (filesOwners.files_approved ?? {})[path];
  const fileAutoApprovers = (filesOwners.files_auto_approved ?? {})[path];
  if (fileAutoApprovers) {
    return {
      fileStatus: FileStatus.AUTO_APPROVED,
      owners: fileAutoApprovers,
    };
  } else if (fileApprovers) {
    return {
      fileStatus: FileStatus.APPROVED,
      owners: fileApprovers,
    };
  } else if (fileOwners) {
    return {
      fileStatus: FileStatus.NEEDS_APPROVAL,
      owners: fileOwners,
    };
  } else {
    return {fileStatus: FileStatus.NOT_OWNED};
  }
}

export function computeApprovalAndInfo(
  fileOwner: OwnerOrGroupOwner,
  labels: OwnersLabels,
  change?: ChangeInfo
): [ApprovalInfo, LabelInfo] | undefined {
  if (!change?.labels || !fileOwner?.owner) {
    return;
  }
  const accountId = fileOwner.owner._account_id;
  const ownersLabel = labels[`${accountId}`];
  if (!ownersLabel) {
    return;
  }

  for (const label of Object.keys(ownersLabel)) {
    const info = change.labels[label];
    if (!info || !isDetailedLabelInfo(info)) {
      return;
    }

    const vote = ownersLabel[label];
    if ((info.default_value && info.default_value === vote) || vote === 0) {
      // ignore default value
      return;
    }

    const approval = info.all?.filter(x => x._account_id === accountId)[0];
    return approval ? [approval, info] : undefined;
  }

  return;
}

export interface ChangeAccounts {
  byAccountId: Map<number, AccountInfo>;
  byEmailWithoutDomain: Map<string, AccountInfo>;
  byFullName: Map<string, AccountInfo>;
}

export function getChangeAccounts(change?: ChangeInfo): ChangeAccounts {
  const accounts = {
    byAccountId: new Map(),
    byEmailWithoutDomain: new Map(),
    byFullName: new Map(),
  } as unknown as ChangeAccounts;

  if (!change) {
    return accounts;
  }

  [
    change.owner,
    ...(change.submitter ? [change.submitter] : []),
    ...(change.reviewers[ReviewerState.REVIEWER] ?? []),
    ...(change.reviewers[ReviewerState.CC] ?? []),
  ].forEach(account => {
    if (account._account_id) {
      accounts.byAccountId.set(account._account_id, account);
    }

    if (account.email && account.email.indexOf('@') > 0) {
      accounts.byEmailWithoutDomain.set(
        account.email.substring(
          0,
          account.email.indexOf('@')
        ) as unknown as string,
        account
      );
    }

    if (account.name) {
      accounts.byFullName.set(account.name, account);
    }
  });
  return accounts;
}
