import {
  FormGroup,
  Select,
  SelectOption,
  SelectVariant,
} from "@patternfly/react-core";
import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";

import { FormAccess } from "../../components/form/FormAccess";
import { HelpItem } from "ui-shared";
import { convertAttributeNameToForm } from "../../util";
import { FormFields } from "../ClientDetails";
import { Toggle } from "./SamlConfig";

const SIGNATURE_ALGORITHMS = [
  "RSA_SHA1",
  "RSA_SHA256",
  "RSA_SHA256_MGF1",
  "RSA_SHA512",
  "RSA_SHA512_MGF1",
  "DSA_SHA1",
] as const;

const KEYNAME_TRANSFORMER = ["NONE", "KEY_ID", "CERT_SUBJECT"] as const;

const CANONICALIZATION = [
  { name: "EXCLUSIVE", value: "http://www.w3.org/2001/10/xml-exc-c14n#" },
  {
    name: "EXCLUSIVE_WITH_COMMENTS",
    value: "http://www.w3.org/2001/10/xml-exc-c14n#WithComments",
  },
  {
    name: "INCLUSIVE",
    value: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
  },
  {
    name: "INCLUSIVE_WITH_COMMENTS",
    value: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments",
  },
] as const;

export const SamlSignature = () => {
  const { t } = useTranslation();
  const [algOpen, setAlgOpen] = useState(false);
  const [keyOpen, setKeyOpen] = useState(false);
  const [canOpen, setCanOpen] = useState(false);

  const { control, watch } = useFormContext<FormFields>();

  const signDocs = watch(
    convertAttributeNameToForm<FormFields>("attributes.saml.server.signature"),
  );
  const signAssertion = watch(
    convertAttributeNameToForm<FormFields>(
      "attributes.saml.assertion.signature",
    ),
  );

  return (
    <FormAccess
      isHorizontal
      role="manage-clients"
      className="keycloak__capability-config__form"
    >
      <Toggle
        name={convertAttributeNameToForm("attributes.saml.server.signature")}
        label="signDocuments"
      />
      <Toggle
        name={convertAttributeNameToForm("attributes.saml.assertion.signature")}
        label="signAssertions"
      />
      {(signDocs === "true" || signAssertion === "true") && (
        <>
          <FormGroup
            label={t("signatureAlgorithm")}
            fieldId="signatureAlgorithm"
            labelIcon={
              <HelpItem
                helpText={t("signatureAlgorithmHelp")}
                fieldLabelId="signatureAlgorithm"
              />
            }
          >
            <Controller
              name={convertAttributeNameToForm<FormFields>(
                "attributes.saml.signature.algorithm",
              )}
              defaultValue={SIGNATURE_ALGORITHMS[0]}
              control={control}
              render={({ field }) => (
                <Select
                  toggleId="signatureAlgorithm"
                  onToggle={setAlgOpen}
                  onSelect={(_, value) => {
                    field.onChange(value.toString());
                    setAlgOpen(false);
                  }}
                  selections={field.value}
                  variant={SelectVariant.single}
                  aria-label={t("signatureAlgorithm")}
                  isOpen={algOpen}
                >
                  {SIGNATURE_ALGORITHMS.map((algorithm) => (
                    <SelectOption
                      selected={algorithm === field.value}
                      key={algorithm}
                      value={algorithm}
                    />
                  ))}
                </Select>
              )}
            />
          </FormGroup>
          <FormGroup
            label={t("signatureKeyName")}
            fieldId="signatureKeyName"
            labelIcon={
              <HelpItem
                helpText={t("signatureKeyNameHelp")}
                fieldLabelId="signatureKeyName"
              />
            }
          >
            <Controller
              name={convertAttributeNameToForm<FormFields>(
                "attributes.saml.server.signature.keyinfo.xmlSigKeyInfoKeyNameTransformer",
              )}
              defaultValue={KEYNAME_TRANSFORMER[0]}
              control={control}
              render={({ field }) => (
                <Select
                  toggleId="signatureKeyName"
                  onToggle={setKeyOpen}
                  onSelect={(_, value) => {
                    field.onChange(value.toString());
                    setKeyOpen(false);
                  }}
                  selections={field.value}
                  variant={SelectVariant.single}
                  aria-label={t("signatureKeyName")}
                  isOpen={keyOpen}
                >
                  {KEYNAME_TRANSFORMER.map((key) => (
                    <SelectOption
                      selected={key === field.value}
                      key={key}
                      value={key}
                    />
                  ))}
                </Select>
              )}
            />
          </FormGroup>
          <FormGroup
            label={t("canonicalization")}
            fieldId="canonicalization"
            labelIcon={
              <HelpItem
                helpText={t("canonicalizationHelp")}
                fieldLabelId="canonicalization"
              />
            }
          >
            <Controller
              name="attributes.saml_signature_canonicalization_method"
              defaultValue={CANONICALIZATION[0].value}
              control={control}
              render={({ field }) => (
                <Select
                  toggleId="canonicalization"
                  onToggle={setCanOpen}
                  onSelect={(_, value) => {
                    field.onChange(value.toString());
                    setCanOpen(false);
                  }}
                  selections={
                    CANONICALIZATION.find((can) => can.value === field.value)
                      ?.name
                  }
                  variant={SelectVariant.single}
                  aria-label={t("canonicalization")}
                  isOpen={canOpen}
                >
                  {CANONICALIZATION.map((can) => (
                    <SelectOption
                      selected={can.value === field.value}
                      key={can.name}
                      value={can.value}
                    >
                      {can.name}
                    </SelectOption>
                  ))}
                </Select>
              )}
            />
          </FormGroup>
        </>
      )}
    </FormAccess>
  );
};
