/**
 * 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 { AlertInterface, AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models";
import { addAlert } from "@wso2is/core/store";
import {
    ContentLoader,
    EmphasizedSegment,
    Heading
} from "@wso2is/react-components";
import { getOIDCData } from "apps/console/src/features/applications/api";
import { OIDCDataInterface } from "apps/console/src/features/applications/models";
import { RequestErrorInterface } from "apps/console/src/features/core/hooks/use-request";
import { AxiosError } from "axios";
import React, {
    Fragment,
    FunctionComponent,
    ReactElement,
    useEffect,
    useState
} from "react";
import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
import { Dispatch } from "redux";
import { Divider, Grid } from "semantic-ui-react";
import { PolicySection, SubscribedAPIResources } from ".";
import { history } from "../../../../../features/core";
import { useAPIResources } from "../../../api-resources/api";
import { APIResourcesConstants } from "../../../api-resources/constants";
import { useSubscribedAPIResources } from "../../api";
import { APIAuthorizationConstants } from "../../constants";


/**
 * Application roles component.
 * 
 * @param props - Props related to application roles component.
 */
export const APIAuthorization: FunctionComponent<IdentifiableComponentInterface> = (
    props: IdentifiableComponentInterface
): ReactElement => {

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

    const { t } = useTranslation();
    const dispatch: Dispatch = useDispatch();

    const [ isSubAPIResourcesSectionLoading, setSubAPIResourcesSectionLoading ] = useState<boolean>(false);
    const [ isShownError, setIsShownError ] = useState<boolean>(false);
    const [ oidcData, setOidcData ] = useState<OIDCDataInterface>(undefined);
    const [ isClientCreditionalsGrantEnabled, setIsClientCreditionalsGrantEnabled ] = useState<boolean>(false);

    const path: string[] = history.location.pathname.split("/");
    const appId: string = path[path.length - 1].split("#")[0];

    const {
        data: allAPIResourcesListData,
        isLoading: isAllAPIResourcesListLoading,
        error: allAPIResourcesFetchRequestError
    } = useAPIResources();

    const {
        data: subscribedAPIResourcesListData,
        isLoading: isSubscribedAPIResourcesListLoading,
        error: subscribedAPIResourcesFetchRequestError
    } = useSubscribedAPIResources(appId);

    /**
     * The following method is used to get OIDC data of the application.
     */
    const getOIDCDataOfTheApplication = () => {
        getOIDCData(appId)
            .then((response: OIDCDataInterface) => {
                setOidcData(response);
            })
            .catch(() => {
                setOidcData(undefined);
            });
    };

    /**
     * The following useEffect is used to get OIDC data of the application.
     */
    useEffect(() => {
        getOIDCDataOfTheApplication();
    }, []);

    /**
     * The following useEffect is used to check if the client credentials grant is enabled.
     */
    useEffect(() => {
        if (oidcData) {
            const grantTypes: string[] = oidcData.grantTypes;

            if (grantTypes.includes(APIAuthorizationConstants.CLIENT_CREDENTIALS_GRANT_TYPE)) {
                setIsClientCreditionalsGrantEnabled(true);
            } else {
                setIsClientCreditionalsGrantEnabled(false);
            }
        }
    }, [ oidcData ]);

    /**
     * The following useEffect is used to handle if any error occurs while fetching API resources
     */
    useEffect(() => {
        if (allAPIResourcesFetchRequestError || subscribedAPIResourcesFetchRequestError) {
            if(!isShownError) {
                setIsShownError(true);

                const error: AxiosError<RequestErrorInterface> = allAPIResourcesFetchRequestError ? 
                    allAPIResourcesFetchRequestError : subscribedAPIResourcesFetchRequestError;
                
                switch (error.response?.data?.code) {
                    case APIResourcesConstants.UNAUTHORIZED_ACCESS:
                        dispatch(addAlert<AlertInterface>({
                            description: t("extensions:develop.apiResource.notifications.getAPIResources" +
                                ".unauthorizedError.description"),
                            level: AlertLevels.ERROR,
                            message: t("extensions:develop.apiResource.notifications.getAPIResources" +
                                ".unauthorizedError.message")
                        }));
    
                        break;
    
                    default:
                        dispatch(addAlert<AlertInterface>({
                            description: t("extensions:develop.apiResource.notifications.getAPIResources" +
                                ".genericError.description"),
                            level: AlertLevels.ERROR,
                            message: t("extensions:develop.apiResource.notifications.getAPIResources" +
                                ".genericError.message")
                        }));
                }
            }
        }
    }, [ allAPIResourcesFetchRequestError, subscribedAPIResourcesFetchRequestError ]);

    /**
     * The following useEffect is used to handle loading state of when API resources are being fetched.
     */
    useEffect(() => {
        setSubAPIResourcesSectionLoading(isAllAPIResourcesListLoading || isSubscribedAPIResourcesListLoading);
    }, [ isAllAPIResourcesListLoading, isSubscribedAPIResourcesListLoading ]);

    /**
     * Handles the hide of the policy selection./
     */
    const isHidePolicySelection = (): boolean => {
        return ( subscribedAPIResourcesFetchRequestError !== null || allAPIResourcesFetchRequestError !== null 
            || allAPIResourcesListData.apiResources.length === 0 || subscribedAPIResourcesListData.length === 0 );
    };

    return (
        <Fragment>
            <EmphasizedSegment padded="very" data-componentid={ ` ${componentId }-sub-api-resources-section` }>
                <Grid>
                    <Grid.Row>
                        <Grid.Column className="heading-wrapper" computer={ 10 }>
                            <Heading as="h4">
                                { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" + 
                                    ".apiSubscriptions.heading") }
                            </Heading>
                            <Heading subHeading ellipsis as="h6" >
                                { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" + 
                                    ".apiSubscriptions.subHeading") }
                            </Heading>
                        </Grid.Column >
                    </Grid.Row>
                </Grid>
                <Divider hidden />
                <Grid>
                    <Grid.Row>
                        <Grid.Column>
                            {
                                isSubAPIResourcesSectionLoading 
                                    ? <ContentLoader inline="centered" active/>
                                    : (<SubscribedAPIResources 
                                        allAPIResourcesListData={ allAPIResourcesListData?.apiResources } 
                                        allAPIResourcesFetchRequestError={ allAPIResourcesFetchRequestError } 
                                        subscribedAPIResourcesListData={ subscribedAPIResourcesListData } 
                                        subscribedAPIResourcesFetchRequestError=
                                            { subscribedAPIResourcesFetchRequestError } 
                                        isShownPlaceholder={ isHidePolicySelection() } 
                                    />)
                            }
                        </Grid.Column>
                    </Grid.Row>
                </Grid>
            </EmphasizedSegment>

            <EmphasizedSegment padded="very" data-componentid={ ` ${componentId }-policy-section` }>
                <Grid>
                    <Grid.Row>
                        <Grid.Column className="heading-wrapper" computer={ 10 }>
                            <Heading as="h4">
                                { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" + 
                                    ".policySection.heading") }
                            </Heading>
                            <Heading subHeading ellipsis as="h6" >
                                { t("extensions:develop.applications.edit.sections.apiAuthorization.sections" + 
                                    ".policySection.subHeading") }
                            </Heading>
                        </Grid.Column >
                    </Grid.Row>
                </Grid>
                <Divider hidden />
                <Grid>
                    <Grid.Row>
                        <Grid.Column>
                            <PolicySection 
                                isClientCredentialsEnabled={ isClientCreditionalsGrantEnabled }/>
                        </Grid.Column>
                    </Grid.Row>
                </Grid>
            </EmphasizedSegment>
        </Fragment>
        
    );
};

/**
 * Default props for application roles tab component.
 */
APIAuthorization.defaultProps = {
    "data-componentid": "api-authorization-tab"
};
