/**
 * Copyright 2026 Google LLC
 *
 * 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 {html, css, LitElement, TemplateResult} from 'lit';
import {SHARED_STYLES} from '../css/shared-css.js';
import {VARS} from '../css/_vars-css.js';
import {LAYOUT_CSS} from '../css/_layout-css.js';
import {customElement, property, query} from 'lit/decorators.js';
import '../js-src/openapi-client.js';
import {DefaultApiInterface, ComponentsUser} from 'chromestatus-openapi';
import {get} from 'http';

@customElement('chromedash-admin-blink-component-listing')
export class ChromedashAdminBlinkComponentListing extends LitElement {
  static get styles() {
    return [
      SHARED_STYLES,
      VARS,
      LAYOUT_CSS,
      css`
        :host {
          display: flex;
        }

        :host([editing]) .owners_list_add_remove {
          opacity: 1;
          pointer-events: all;
        }

        :host([editing]) .owners_list select[multiple] {
          background-color: #fff;
          border-color: rgba(0, 0, 0, 0);
        }

        :host([editing]) .owners_list select[multiple] option {
          padding-left: 4px;
        }

        .component_name {
          flex: 1 0 130px;
          margin-right: var(--content-padding);
        }

        .component_name h3 {
          color: initial;
          padding-top: 4px;
        }

        .column_header {
          margin-bottom: calc(var(--content-padding) / 2);
        }

        .owners_list {
          flex: 1 0 auto;
        }

        .component_owner {
          font-weight: 600;
        }

        .owners_list_add_remove {
          margin-left: calc(var(--content-padding) / 2);
          opacity: 0;
          transition: 200ms opacity cubic-bezier(0, 0, 0.2, 1);
          pointer-events: none;
        }

        .owners_list_add_remove button[disabled] {
          pointer-events: none;
          opacity: 0.5;
        }

        .remove_owner_button {
          color: darkred;
        }

        select[multiple] {
          min-width: 275px;
          background-color: #eee;
          border: none;
          transition: 200ms background-color cubic-bezier(0, 0, 0.2, 1);
          font-size: inherit;
        }

        select[multiple]:disabled option {
          color: initial;
          padding: 4px 0;
        }
      `,
    ];
  }

  @property({type: Boolean, reflect: true})
  editing = false;
  @property({type: Object})
  component = {};
  @property({type: Number})
  index = 0;
  @property({type: Object})
  usersMap: Map<number, ComponentsUser> = new Map();
  @property({type: Number})
  componentId = 0;
  @property({type: String})
  name = '';
  @property({type: Array})
  subscriberIds: number[] = [];
  @property({type: Array})
  ownerIds: number[] = [];

  _client: DefaultApiInterface = window.csOpenApiClient;

  @query('.owner_candidates')
  _ownerCandidates;
  @query('.is_primary_checkbox')
  _isPrimaryCheckbox;

  private getOwnerListElement(): HTMLSelectElement | null {
    return this.shadowRoot!?.querySelector(`#owner_list_${this.index}`);
  }

  _getOptionsElement() {
    return this._ownerCandidates;
  }

  _findSelectedOptionElement() {
    return this._getOptionsElement().selectedOptions[0];
  }

  _isOwnerCheckboxChecked() {
    return this._isPrimaryCheckbox.checked;
  }

  _isUserInOwnerList(userId: number) {
    const ownersList = this.getOwnerListElement()!;
    return Array.from(ownersList.options).find(
      option => parseInt((option as HTMLOptionElement).value) === userId
    );
  }

  _addUser() {
    const toggleAsOwner = this._isOwnerCheckboxChecked();
    const selectedCandidate = this._findSelectedOptionElement();

    const userId = parseInt(selectedCandidate.value);

    if (selectedCandidate.disabled) {
      alert('Please select a user before trying to add');
      return;
    }
    // Don't try to add user if they're already in the list, and we're not
    // modifying their owner state.
    if (this._isUserInOwnerList(userId) && !toggleAsOwner) {
      return;
    }

    let isError = false;
    this._client
      .addUserToComponent({
        componentId: this.componentId,
        userId: userId,
        componentUsersRequest: {owner: toggleAsOwner},
      })
      .then(() => {})
      .catch(() => {
        isError = true;
      })
      .finally(() => {
        this.dispatchEvent(
          new CustomEvent('adminAddComponentUser', {
            detail: {
              userId: userId,
              toggleAsOwner: toggleAsOwner,
              index: this.index,
              isError: isError,
            },
            bubbles: true,
            composed: true,
          })
        );
      });
  }
  /**
   * @param {PointerEvent} e event
   */
  _removeUser() {
    const toggleAsOwner = this._isOwnerCheckboxChecked();
    const selectedCandidate = this._findSelectedOptionElement();

    const userId = parseInt(selectedCandidate.value);
    if (selectedCandidate.disabled) {
      alert('Please select a user before trying to remove');
      return;
    }

    // Don't try to remove user if they do not exist in the list
    if (!this._isUserInOwnerList(userId)) {
      return;
    }

    let isError = false;
    this._client
      .removeUserFromComponent({
        componentId: this.componentId,
        userId: userId,
        componentUsersRequest: {owner: toggleAsOwner},
      })
      .then(() => {})
      .catch(() => {
        isError = true;
      })
      .finally(() => {
        this.dispatchEvent(
          new CustomEvent('adminRemoveComponentUser', {
            detail: {
              userId: userId,
              toggleAsOwner: toggleAsOwner,
              index: this.index,
              isError: isError,
            },
            bubbles: true,
            composed: true,
          })
        );
      });
  }

  _printUserDetails(userId) {
    return html`${this.usersMap.get(userId)!.name}:
    ${this.usersMap.get(userId)!.email}`;
  }

  render() {
    const userListTemplate: TemplateResult[] = [];
    for (const user of this.usersMap.values()) {
      userListTemplate.push(
        html`<option
          class="owner_name"
          value="${user.id}"
          data-email="${user.email}"
          data-name="${user.name}"
        >
          ${user.name}: ${user.email}
        </option>`
      );
    }
    return html`
      <div class="component_name">
        <div class="column_header">Component</div>
        <h3>${this.name}</h3>
      </div>
      <div class="owners_list layout horizontal center">
        <div>
          <div class="column_header">Receives email updates:</div>
          <select
            multiple
            disabled
            id="owner_list_${this.index}"
            size="${this.subscriberIds.length}"
          >
            ${this.subscriberIds.map(subscriberId =>
              this.ownerIds.includes(subscriberId)
                ? html`<option
                    class="owner_name component_owner"
                    value="${subscriberId}"
                  >
                    ${this._printUserDetails(subscriberId)}
                  </option>`
                : html`<option class="owner_name" value="${subscriberId}">
                    ${this._printUserDetails(subscriberId)}
                  </option>`
            )};
          </select>
        </div>
        <div class="owners_list_add_remove">
          <div>
            <select class="owner_candidates">
              <option selected disabled data-placeholder="true">
                Select owner to add/remove
              </option>
              ${userListTemplate}</select
            ><br />
            <label
              title="Toggles the user as an owner. If you click 'Remove' ans this is not checked, the user is removed from the component."
              >Owner? <input type="checkbox" class="is_primary_checkbox"
            /></label>
          </div>
          <button
            @click="${this._addUser}"
            class="add_owner_button"
            data-component-name="${this.name}"
          >
            Add
          </button>
          <button
            @click="${this._removeUser}"
            class="remove_owner_button"
            data-component-name="${this.name}"
          >
            Remove
          </button>
        </div>
      </div>
    `;
  }
}
