/**
 * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
 *
 * This software is the property of WSO2 LLC. and its suppliers, if any.
 * Dissemination of any information or reproduction of any material contained
 * herein in any form is strictly forbidden, unless permitted by WSO2 expressly.
 * You may not alter or remove any copyright or other notice from copies of this content.
 */

import { IdentifiableComponentInterface, SBACInterface } from "@wso2is/core/models";
import { Field, FormValue, Forms, Validation } from "@wso2is/forms";
import { Hint } from "@wso2is/react-components";
import React, { FunctionComponent, ReactElement } from "react";
import { Trans, useTranslation } from "react-i18next";
import { Grid } from "semantic-ui-react";
import { ExtendedFeatureConfigInterface } from "../../../../../configs/models";
import { APIResourcesConstants } from "../../../constants";
import { APIResourceInterface, BsaicAPIResourceInterface } from "../../../models";

/**
 * Prop-types for the API resources page component.
 */
interface AddAPIResourceBasicInterface extends SBACInterface<ExtendedFeatureConfigInterface>,
    IdentifiableComponentInterface {
    /**
     * initial basic details
     */
    initalBasicDetails: BsaicAPIResourceInterface;
    /**
     * trigger submission
     */
    triggerSubmission: boolean;
    /**
     * Is api resources list loading.
     */
    isAPIResourcesListLoading: boolean;
    /**
     * API resources list.
     */
    apiResourcesList: APIResourceInterface[];
    /**
     * Set current identifier value.
     */
    setCurrentIdentifierValue: (identifier: string) => void;
    /**
     * mutate api resources list call.
     */
    mutateAPIResourcesFetchRequest: () => void;
    /**
     * Set display name.
     */
    setBasicDetails: (basicDetails: BsaicAPIResourceInterface) => void;
    /**
     * callback function to invoke after basic details submission.
     */
    submitCallback?: () => void;
}

const FORM_ID: string = "apiResource-general-details";

/**
 * API Resources listing page.
 *
 * @param props - Props injected to the component.
 * @returns API Resources Page component
 */
export const AddAPIResourceBasic: FunctionComponent<AddAPIResourceBasicInterface> = (
    props: AddAPIResourceBasicInterface
): ReactElement => {

    const {
        triggerSubmission,
        initalBasicDetails,
        isAPIResourcesListLoading,
        apiResourcesList,
        setCurrentIdentifierValue,
        mutateAPIResourcesFetchRequest,
        setBasicDetails,
        submitCallback,
        ["data-componentid"]: componentId
    } = props;

    const { t } = useTranslation();
 

    /**
     * Prepare form values for submitting.
     *
     * @param values - Form values.
     */
    const submitBasicDetails = (values: Map<string, FormValue>): void => {
        setBasicDetails({
            displayName: values.get("displayName").toString(),
            identifier: values.get("identifier").toString()
        });

        submitCallback && submitCallback();
    };

    return (
        <Forms
            data-testid={ `${componentId}-form` }
            onSubmit={ submitBasicDetails }
            id={ FORM_ID }
            submitState={ triggerSubmission }
            uncontrolledForm={ false }
        >
            <Grid>
                <Grid.Row columns={ 1 }>
                    <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                        <Field            
                            type="text"
                            name="displayName"
                            label={ t("extensions:develop.apiResource.wizard.addApiResource.steps.basic.form.fields." + 
                                "name.label") }
                            placeholder={ t("extensions:develop.apiResource.wizard.addApiResource.steps.basic.form." +
                                "fields.name.placeholder") }
                            required={ true }
                            tabIndex={ 1 }
                            requiredErrorMessage={ t("extensions:develop.apiResource.wizard.addApiResource.steps." + 
                                "basic.form.fields.name.emptyValidate") }
                            value={ initalBasicDetails && initalBasicDetails.displayName }
                            data-testid={ `${componentId}-basic-form-displayName` }
                        />
                        <Hint className="mb-0">
                            { t("extensions:develop.apiResource.wizard.addApiResource.steps.basic.form.fields." +
                                "name.hint") }
                        </Hint>
                    </Grid.Column>
                </Grid.Row>
                <Grid.Row columns={ 1 }>
                    <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                        <Field
                            type="text"
                            name="identifier"
                            label={ t("extensions:develop.apiResource.wizard.addApiResource.steps.basic.form." +
                                "fields.identifier.label") }
                            placeholder={ t("extensions:develop.apiResource.wizard.addApiResource.steps.basic." +
                                "form.fields.identifier.placeholder") }
                            requiredErrorMessage={ t("extensions:develop.apiResource.wizard.addApiResource.steps." +
                                "basic.form.fields.identifier.emptyValidate") }
                            required={ true }
                            tabIndex={ 2 }
                            value={ initalBasicDetails && initalBasicDetails.identifier }
                            validation={ async (value: string, validation: Validation) => {
                                if (!APIResourcesConstants.checkValidPermissionIdentifier(value)) {
                                    validation.isValid = false;
                                    validation.errorMessages.push(t("extensions:develop.apiResource.wizard." +
                                        "addApiResource.steps.basic.form.fields.identifier.invalid"));

                                    return;
                                }

                                if (value) {
                                    setCurrentIdentifierValue(value);
                                    await mutateAPIResourcesFetchRequest();
                                    if (apiResourcesList?.length > 0) {
                                        validation.isValid = false;
                                        validation.errorMessages.push(t("extensions:develop.apiResource.wizard." +
                                            "addApiResource.steps.basic.form.fields.identifier.alreadyExistsError"));
                                    }
                                }
                            } }
                            data-testid={ `${componentId}-basic-form-identifier` }
                            loading={ isAPIResourcesListLoading }
                        />
                        <Hint className="mb-0">
                            <Trans 
                                i18nKey= { "extensions:develop.apiResource.wizard.addApiResource.steps.basic." +
                                    "form.fields.identifier.hint" }>
                                We recommend using a URL as the identifier, but you do not need to make the URL 
                                publicly available since Asgardeo will not access your API. Asgardeo will use this 
                                identifier value as the audience(aud) claim in the issued JWT tokens. 
                                <b>This field should be unique; once created, it is not editable.</b>
                            </Trans>
                        </Hint>
                    </Grid.Column>
                </Grid.Row>
            </Grid>
        </Forms>
    );
};

/**
 * Default props for the component.
 */
AddAPIResourceBasic.defaultProps = {
    "data-componentid": "add-api-resource-basic"
};
