/*
 * Copyright OpenSearch Contributors
 * SPDX-License-Identifier: Apache-2.0
 */

import React, { Component } from "react";
import {
  EuiButton,
  EuiButtonEmpty,
  EuiModal,
  EuiModalBody,
  EuiModalFooter,
  EuiModalHeader,
  EuiModalHeaderTitle,
  EuiOverlayMask,
  EuiRadioGroup,
  EuiSelect,
  EuiSpacer,
  EuiFormRow,
} from "@elastic/eui";
import { ManagedIndexItem, State } from "../../../../../models/interfaces";
import { BrowserServices } from "../../../../models/interfaces";
import { getErrorMessage } from "../../../../utils/helpers";
import { CoreServicesContext } from "../../../../components/core_services";

interface RetryModalProps {
  services: BrowserServices;
  retryItems: ManagedIndexItem[];
  onClose: () => void;
}

interface RetryModalState {
  radioIdSelected: string;
  stateSelected: string;
  stateOptions: { value: string; text: string }[];
}

enum Radio {
  Current = "current",
  State = "state",
}

export default class RetryModal extends Component<RetryModalProps, RetryModalState> {
  static contextType = CoreServicesContext;
  state = {
    radioIdSelected: Radio.Current,
    stateSelected: "",
    stateOptions: [],
  };

  componentDidMount(): void {
    this.initOptions();
  }

  initOptions = (): void => {
    const { retryItems } = this.props;
    if (!retryItems.length) return;

    // we will use this first item as the base set of states
    // if we ever encounter an item with no policy, then simply return early
    // otherwise take the intersections of all next retry item states
    // until we have a final list of common states

    const firstRetryItem = retryItems[0];
    if (!firstRetryItem.policy || !firstRetryItem.policy.states) return;
    let states = new Set(firstRetryItem.policy.states.map((state: State) => state.name));

    for (let i = 1; i < retryItems.length; i++) {
      // if we ever end up with no states just return early
      if (!states.size) return;

      const retryItem = retryItems[i];
      if (!retryItem.policy || !retryItem.policy.states) return;
      const tempStates = new Set(retryItem.policy.states.map((state: State) => state.name));

      // take intersection of two state sets
      states = new Set([...states].filter((state) => tempStates.has(state)));
    }

    const stateOptions = [...states].map((state: string) => ({ value: state, text: state }));
    this.setState({ stateOptions });
  };

  onRetry = async (): Promise<void> => {
    const { radioIdSelected, stateSelected } = this.state;
    const {
      retryItems,
      onClose,
      services: { managedIndexService },
    } = this.props;
    try {
      const indices = retryItems.map((item) => item.index);
      const state = radioIdSelected == Radio.State ? stateSelected : null;
      const response = await managedIndexService.retryManagedIndexPolicy(indices, state);
      if (response.ok) {
        const {
          response: { updatedIndices, failedIndices, failures },
        } = response;
        if (failures) {
          this.context.notifications.toasts.addDanger(
            `Failed to retry: ${failedIndices.map((failedIndex) => `[${failedIndex.indexName}, ${failedIndex.reason}]`).join(", ")}`
          );
        }

        if (updatedIndices) {
          this.context.notifications.toasts.addSuccess(`Retried ${updatedIndices} managed indices`);
        }
      } else {
        this.context.notifications.toasts.addDanger(response.error);
      }
      onClose();
    } catch (err) {
      this.context.notifications.toasts.addDanger(getErrorMessage(err, "There was a problem retrying managed indices"));
    }
  };

  onChange = (optionId: string): void => {
    this.setState({ radioIdSelected: optionId });
  };

  onSelectChange = (e: React.ChangeEvent<HTMLSelectElement>): void => {
    this.setState({ stateSelected: e.target.value });
  };

  render() {
    const { radioIdSelected, stateSelected, stateOptions } = this.state;
    const { onClose, retryItems } = this.props;

    const currentRadio = { id: Radio.Current, label: "Retry policy from current action" };
    const stateRadio = { id: Radio.State, label: "Retry policy from selected state", disabled: !stateOptions.length };
    const radioOptions = [currentRadio, stateRadio];
    return (
      <EuiOverlayMask>
        {/*
            // @ts-ignore */}
        <EuiModal onCancel={onClose} onClose={onClose}>
          <EuiModalHeader>
            <EuiModalHeaderTitle>Retry policy</EuiModalHeaderTitle>
          </EuiModalHeader>

          <EuiModalBody>
            <EuiRadioGroup options={radioOptions} idSelected={radioIdSelected} onChange={this.onChange} />

            <EuiSpacer size="s" />
            <EuiFormRow label="Start state" helpText="Only common states shared across all selected indices are available">
              <EuiSelect
                disabled={radioIdSelected !== Radio.State}
                options={stateOptions}
                value={stateSelected}
                onChange={this.onSelectChange}
                aria-label="Retry failed policy from"
              />
            </EuiFormRow>
          </EuiModalBody>

          <EuiModalFooter>
            <EuiButtonEmpty onClick={onClose} data-test-subj="retryModalCloseButton">
              Close
            </EuiButtonEmpty>

            <EuiButton onClick={this.onRetry} disabled={!retryItems.length} fill data-test-subj="retryModalRetryButton">
              Retry
            </EuiButton>
          </EuiModalFooter>
        </EuiModal>
      </EuiOverlayMask>
    );
  }
}