/**
 * 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 } from "@wso2is/forms";
import { Hint, Message, PrimaryButton } from "@wso2is/react-components";
import { ExtendedFeatureConfigInterface } from "apps/console/src/extensions/configs";
import React, { FunctionComponent, ReactElement, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { Grid } from "semantic-ui-react";
import { PolicyType, UserBasedPolicyType } from "../../constants";

/**
 * Prop types for the policy section component.
 */
interface PolicySectionProps extends
    SBACInterface<ExtendedFeatureConfigInterface>, IdentifiableComponentInterface {
    /**
     * Is client credentials enabled.
     */
    isClientCredentialsEnabled: boolean;
    /**
     * Is scopes available for update.
     */
    isScopesAvailableForUpdate: boolean;
}

/**
 * Policy section interface component.
 * 
 * TODO: Add a message notification if no roles have been created while the user have selected role based access policy.
 *
 * @param props - Props injected to the component.
 * @returns Functional component.
 */
export const PolicySection: FunctionComponent<PolicySectionProps> = (
    props: PolicySectionProps
): ReactElement => {

    const {
        isClientCredentialsEnabled,
        isScopesAvailableForUpdate,
        [ "data-componentid" ]: componentId
    } = props;

    const { t } = useTranslation();
    const [ isUserBasedPolicyEnabled, setUserBasedPolicyEnabled ] = useState<boolean>(false);
    const [ isApplicationBasedPolicyEnabled, setApplicationBasedPolicyEnabled ] = useState<boolean>(false);
    const [ enabledPolicies, setEnabledPolicies ] = useState<string[]>([]);

    /**
     * This function is used to handle the policy change.
     */
    const handlePolicyChange = (values: Map<string, FormValue>): void => {
        const policies: string[] = [];

        values.forEach((value: FormValue, key: string) => {
            if (value.length === 1) {
                policies.push(value[0]);
            }

            if (key === PolicyType.USER_BASED) {
                changeUserBasedPolicyEnabled(value);
            } else if (key === PolicyType.APPLICATION_BASED) {
                changeApplicationBasedPolicyEnabled(value);
            }
        });
        setEnabledPolicies(policies);
    };

    /**
     * This function is used to check whether the user based policy is enabled or not.
     */
    const changeUserBasedPolicyEnabled = (value: FormValue): void => {
        if (value.length === 1 && value.includes(PolicyType.USER_BASED)) {
            setUserBasedPolicyEnabled(true);
        } else {
            setUserBasedPolicyEnabled(false);
        }
    };

    /**
     * This function is used to check whether the application based policy is enabled or not.
     */
    const changeApplicationBasedPolicyEnabled = (value: FormValue): void => {
        if (value.length === 1 && value.includes(PolicyType.APPLICATION_BASED)) {
            setApplicationBasedPolicyEnabled(true);
        } else {
            setApplicationBasedPolicyEnabled(false);
        }
    };

    return (
        <Forms
            data-componentid={ `${componentId}-form` }
            uncontrolledForm={ false }
        >
            <Grid>
                { enabledPolicies.length === 0 && (
                    <Grid.Row columns={ 1 } className={ enabledPolicies.length === 0 ? "pb-0" : "" }>
                        <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                            <Message
                                type="warning"
                                header="Warning"
                                content={ t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                ".sections.policySection.messages.noPolicy") }
                            />
                        </Grid.Column>
                    </Grid.Row>) }
                { !isClientCredentialsEnabled && isApplicationBasedPolicyEnabled && (
                    <Grid.Row columns={ 1 } className={ "pb-0" }>
                        <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                            <Message
                                type="warning"
                                header="Warning"
                                content={ 
                                    (<Trans
                                        i18nKey={
                                            "extensions:develop.applications.edit.sections.apiAuthorization" + 
                                            ".sections.policySection.messages.noClientCredentials"
                                        }
                                    >
                                        Please <b>enable client credential grant</b> for your application before 
                                        applying the application-based policy for secure access to your subscribed APIs.
                                    </Trans>)
                                }
                            />
                        </Grid.Column>
                    </Grid.Row>) }
                <Grid.Row columns={ 1 }>
                    <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                        <Field
                            data-componentid={ `${ componentId }-user-based` }
                            name={ PolicyType.USER_BASED }
                            type="checkbox"
                            children={ [
                                {
                                    label: t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                    ".sections.policySection.form.fields.userPolicy.label"),
                                    value: PolicyType.USER_BASED
                                }
                            ] }
                            key={ "key" }
                            listen={ (values: Map<string, FormValue>) => handlePolicyChange(values) }
                            tabIndex={ 3 }
                            disabled={ !isScopesAvailableForUpdate }
                        />
                    </Grid.Column>
                </Grid.Row>
                <Grid.Row columns={ 1 } className="pt-0 ml-4">
                    <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 14 }>
                        { /* TODO : Add a link to the `Role` tab from the hint text */ }
                        <Field
                            data-testid="user-mgt-add-user-form-passwordOption-radio-button"
                            type="radio"
                            name="userBasedPolicy"
                            default={ UserBasedPolicyType.ROLE_BASED }
                            children={ [
                                {
                                    label: t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                        ".sections.policySection.form.fields.rbac.label"),
                                    value: UserBasedPolicyType.ROLE_BASED
                                }
                            ] }
                            tabIndex={ 4 }
                            listen={ (values: Map<string, FormValue>) => handlePolicyChange(values) }
                            disabled={ !isUserBasedPolicyEnabled || !isScopesAvailableForUpdate }
                        />
                        <Hint disabled={ !isUserBasedPolicyEnabled  || !isScopesAvailableForUpdate }>
                            { t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                        ".sections.policySection.form.fields.rbac.hint") }
                        </Hint>
                    </Grid.Column>
                </Grid.Row>
                <Grid.Row columns={ 1 } className="pt-0 ml-4">
                    <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 14 }>
                        <Field
                            data-testid="user-mgt-add-user-form-passwordOption-radio-button"
                            type="radio"
                            name="userBasedPolicy"
                            default={ UserBasedPolicyType.ROLE_BASED }
                            children={ [
                                {
                                    label: t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                    ".sections.policySection.form.fields.consent.label"),
                                    value: UserBasedPolicyType.CONSENT_BASED
                                }
                            ] }
                            tabIndex={ 4 }
                            listen={ (values: Map<string, FormValue>) => handlePolicyChange(values) }
                            disabled={ !isUserBasedPolicyEnabled || !isScopesAvailableForUpdate }
                        />
                        <Hint disabled={ !isUserBasedPolicyEnabled  || !isScopesAvailableForUpdate }>
                            { t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                    ".sections.policySection.form.fields.consent.hint") }
                        </Hint>
                    </Grid.Column>
                </Grid.Row>
                <Grid.Row columns={ 1 }>
                    <Grid.Column mobile={ 16 } tablet={ 16 } computer={ 12 }>
                        <Field
                            data-componentid={ `${ componentId }-user-based` }
                            name={ PolicyType.APPLICATION_BASED }
                            type="checkbox"
                            children={ [
                                {
                                    label: t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                    ".sections.policySection.form.fields.appPolicy.label"),
                                    value: PolicyType.APPLICATION_BASED
                                }
                            ] }
                            key={ "key" }
                            listen={ (values: Map<string, FormValue>) => handlePolicyChange(values) }
                            tabIndex={ 5 }
                            disabled={ !isScopesAvailableForUpdate }
                        />
                        <Hint disabled={ !isScopesAvailableForUpdate }>
                            { t("extensions:develop.applications.edit.sections.apiAuthorization" + 
                                    ".sections.policySection.form.fields.appPolicy.hint") }
                        </Hint>
                    </Grid.Column>
                </Grid.Row>
                {
                    isScopesAvailableForUpdate && (
                        <Grid.Row columns={ 1 }>
                            <Grid.Column width={ 16 }>
                                <PrimaryButton
                                    size="small"
                                    tabIndex={ 6 }
                                    onClick={ () => null }
                                    data-componentid={ `${componentId}-update-policy-btn` } 
                                >
                                    { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" + 
                                            ".policySection.buttons.update") }
                                </PrimaryButton>
                            </Grid.Column>
                        </Grid.Row> )
                }
            </Grid>
        </Forms>
    );
};

/**
 * Default props for the application advanced configurations form component.
 */
PolicySection.defaultProps = {
    "data-componentid": "policy-section"
};
