import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { ArrayField, UseFormMethods } from "react-hook-form";
import { ActionGroup, Button, TextInput } from "@patternfly/react-core";
import {
  TableComposable,
  Tbody,
  Td,
  Th,
  Thead,
  Tr,
} from "@patternfly/react-table";
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";

import { FormAccess } from "../form-access/FormAccess";

import "./attribute-form.css";

export type KeyValueType = { key: string; value: string };

export type AttributeForm = {
  attributes: KeyValueType[];
};

export type AttributesFormProps = {
  form: UseFormMethods<AttributeForm>;
  save: (model: AttributeForm) => void;
  reset: () => void;
  array: {
    fields: Partial<ArrayField<Record<string, any>, "id">>[];
    append: (
      value: Partial<Record<string, any>> | Partial<Record<string, any>>[],
      shouldFocus?: boolean | undefined
    ) => void;
    remove: (index?: number | number[] | undefined) => void;
  };
};

export const arrayToAttributes = (attributeArray: KeyValueType[]) => {
  const initValue: { [index: string]: string[] } = {};
  return attributeArray.reduce((acc, attribute) => {
    acc[attribute.key] = [attribute.value];
    return acc;
  }, initValue);
};

export const attributesToArray = (attributes?: {
  [key: string]: string[];
}): KeyValueType[] => {
  if (!attributes || Object.keys(attributes).length == 0) {
    return [];
  }
  return Object.keys(attributes).map((key) => ({
    key: key,
    value: attributes[key][0],
  }));
};

export const AttributesForm = ({
  form: { handleSubmit, register, formState, errors, watch },
  array: { fields, append, remove },
  reset,
  save,
}: AttributesFormProps) => {
  const { t } = useTranslation("roles");

  const columns = ["Key", "Value"];

  const watchLast = watch(`attributes[${fields.length - 1}].key`, "");

  useEffect(() => {
    if (fields.length === 0) {
      append({ key: "", value: "" });
    }
  }, [fields]);

  return (
    <>
      <FormAccess role="manage-realm" onSubmit={handleSubmit(save)}>
        <TableComposable
          className="kc-attributes__table"
          aria-label="Role attribute keys and values"
          variant="compact"
          borders={false}
        >
          <Thead>
            <Tr>
              <Th id="key" width={40}>
                {columns[0]}
              </Th>
              <Th id="value" width={40}>
                {columns[1]}
              </Th>
            </Tr>
          </Thead>
          <Tbody>
            {fields.map((attribute, rowIndex) => (
              <Tr key={attribute.id}>
                <Td
                  key={`${attribute.id}-key`}
                  id={`text-input-${rowIndex}-key`}
                  dataLabel={columns[0]}
                >
                  <TextInput
                    name={`attributes[${rowIndex}].key`}
                    ref={register()}
                    aria-label="key-input"
                    defaultValue={attribute.key}
                    validated={
                      errors.attributes && errors.attributes[rowIndex]
                        ? "error"
                        : "default"
                    }
                  />
                </Td>
                <Td
                  key={`${attribute}-value`}
                  id={`text-input-${rowIndex}-value`}
                  dataLabel={columns[1]}
                >
                  <TextInput
                    name={`attributes[${rowIndex}].value`}
                    ref={register()}
                    aria-label="value-input"
                    defaultValue={attribute.value}
                  />
                </Td>
                {rowIndex !== fields.length - 1 && fields.length - 1 !== 0 && (
                  <Td
                    key="minus-button"
                    id={`kc-minus-button-${rowIndex}`}
                    dataLabel={columns[2]}
                  >
                    <Button
                      id={`minus-button-${rowIndex}`}
                      aria-label={`remove ${attribute.key} with value ${attribute.value} `}
                      variant="link"
                      className="kc-attributes__minus-icon"
                      onClick={() => remove(rowIndex)}
                    >
                      <MinusCircleIcon />
                    </Button>
                  </Td>
                )}
                {rowIndex === fields.length - 1 && (
                  <Td key="add-button" id="add-button" dataLabel={columns[2]}>
                    {fields.length !== 1 && (
                      <Button
                        id={`minus-button-${rowIndex}`}
                        aria-label={`remove ${attribute.key} with value ${attribute.value} `}
                        variant="link"
                        className="kc-attributes__minus-icon"
                        onClick={() => remove(rowIndex)}
                      >
                        <MinusCircleIcon />
                      </Button>
                    )}
                  </Td>
                )}
              </Tr>
            ))}
            <Tr>
              <Td>
                <Button
                  aria-label={t("roles:addAttributeText")}
                  id="plus-icon"
                  variant="link"
                  className="kc-attributes__plus-icon"
                  onClick={() => append({ key: "", value: "" })}
                  icon={<PlusCircleIcon />}
                  isDisabled={!watchLast}
                >
                  {t("roles:addAttributeText")}
                </Button>
              </Td>
            </Tr>
          </Tbody>
        </TableComposable>
        <ActionGroup className="kc-attributes__action-group">
          <Button
            variant="primary"
            type="submit"
            isDisabled={!formState.isDirty}
          >
            {t("common:save")}
          </Button>
          <Button
            onClick={reset}
            variant="link"
            isDisabled={!formState.isDirty}
          >
            {t("common:revert")}
          </Button>
        </ActionGroup>
      </FormAccess>
    </>
  );
};
