import { getRecommendations } from '@rh-support/api';
import React, { useContext, useEffect, useRef } from 'react';
import { AppMetadataStateContext } from '../../context/AppMetadataContext';
import { CreateCaseDispatchContext, CreateCaseStateContext } from '../../context/CreateCaseContext';
import { RecommendationDispatchContext } from '../../context/RecommendationContext';
import { RouteContext, RouteDispatchContext } from '../../context/RouteContext';
import { useDebounce } from '../../hooks/useDebounce';
import { getDescriptionWOQues, isCaseStateValid } from '../../reducers/CreateCaseHelpers';
import { setCaseRecommendations } from '../../reducers/CreateCaseReducer';
import { RecommendationsConstants } from '../../reducers/RecommendationsReducer';
import { AppRouteSections, RouteReducerConstants } from '../../reducers/RouteReducer';
import CaseUtils from '../../utils/caseUtils';
import AlertMessage, { AlertType } from '../shared/AlertMessage';
import LoadingIndicator from '../shared/LoadingIndicator';
import CaseType from './CaseType';
import Description from './Description';
import Fts from './Fts';
import GroupNEnhancedSLA from './GroupNEnhancedSLA';
import OpenCaseIssue from './OpenCaseIssue';
import ProductNVersion from './ProductNVersion';
import SupportNSeveritySelector from './SupportNSeveritySelector';

interface IProps {}

export default function OpenCase(props: IProps) {
    const { appMetadataState: {
        loggedInUserJwtToken,
        loggedInUsersAccount,
        loggedInUser,
        allCaseTypes,
        caseGroups,
        allCaseSeverities,
        nextButtonRef
    } } = useContext(AppMetadataStateContext);
    const dispatchCreateCaseReducer = useContext(CreateCaseDispatchContext);
    const { createCaseState } = useContext(CreateCaseStateContext);
    const { routeState: {activeSection, isSectionValid} } = useContext(RouteContext);
    const dispatchToRouteReducer = useContext(RouteDispatchContext);

    // getting recommendation dispatch and state via context
    const recommendationDispatch = useContext(RecommendationDispatchContext);

    // abort controller ref
    const controllerRef: React.MutableRefObject<AbortController> = useRef(new AbortController());

    // Validations effect
    useEffect(() => {
        if (activeSection !== AppRouteSections.OPEN_CASE) { return; }
        const isSectionValidLocal = isCaseStateValid(createCaseState, loggedInUsersAccount.data.require_cgroup_on_create, loggedInUserJwtToken);
        if (isSectionValid === isSectionValidLocal) { return; }
        dispatchToRouteReducer({ type: RouteReducerConstants.setIsSectionValid, payload: { isSectionValid: isSectionValidLocal } });
    }, [createCaseState, activeSection, loggedInUsersAccount.data]);

    // sidebar recommendation using debounce hook
    useDebounce(() => {
        // fetching side recommendation
        const fetchRecommendation = async () => {
            recommendationDispatch({type: RecommendationsConstants.requestSidebarRecommendation});
            try {
            if (controllerRef.current) { controllerRef.current.abort(); }
            controllerRef.current = new AbortController();
            const response = await getRecommendations({
                product: createCaseState.product,
                version: createCaseState.version,
                summary: createCaseState.summary,
                description: getDescriptionWOQues(
                    createCaseState.issue,
                    createCaseState.environment,
                    createCaseState.periodicityOfIssue,
                    createCaseState.timeFramesAndUrgency
                )
            }, 5, controllerRef.current.signal);
            recommendationDispatch({
                type: RecommendationsConstants.receiveSidebarRecommendation,
                payload: {sideRecommendation: response.response.docs, sideRecommendationError: false}
            });
            setCaseRecommendations(dispatchCreateCaseReducer, response.response.docs, createCaseState.recommendations);
            } catch (error) {
            // AbortError is thrown even if we cancel our fetch request so to handle and not to consider this as an erro
            // as additional check has been used
            error.name !== 'AbortError' &&
            recommendationDispatch({
                type: RecommendationsConstants.receiveSidebarRecommendation,
                payload: {sideRecommendation: [], sideRecommendationError: true}
            });
            }
        };

        !loggedInUsersAccount.data.is_secured_support && fetchRecommendation();
    }, [ controllerRef, createCaseState.product, createCaseState.version, loggedInUsersAccount.data.is_secured_support,
        createCaseState.summary, createCaseState.issue, createCaseState.environment,
        createCaseState.timeFramesAndUrgency, createCaseState.periodicityOfIssue]
    , 1000);

    const isMetadataLoading = (): boolean => {
        return !isMetadataLoadingError() && (loggedInUser.isFetching || loggedInUsersAccount.isFetching);
    };

    const isMetadataLoadingError = (): boolean => {
        return loggedInUser.isError
            || loggedInUsersAccount.isError
            || allCaseTypes.isError
            || (loggedInUsersAccount.data.require_cgroup_on_create && caseGroups.isError)
            || allCaseSeverities.isError;
    };
    const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        // simulating click
        nextButtonRef.current.click();
    };

    return (<>
        <LoadingIndicator show={isMetadataLoading()} size="lg" />
        <AlertMessage type={AlertType.DANGER} className="push-top" message="Sorry, we're having a problem gathering your information." show={isMetadataLoadingError()} />
        <AlertMessage show={!CaseUtils.canManageCase(loggedInUserJwtToken)} type={AlertType.DANGER} className="push-top">
            <>
                You need additional access to manage cases.&nbsp;
                Please contact <a href="/support/contact/customerService">Customer Service</a> for assistance.
            </>
        </AlertMessage>
        {!isMetadataLoading() && !isMetadataLoadingError() && CaseUtils.canManageCase(loggedInUserJwtToken) && (<>
            <form onSubmit={handleFormSubmit}>
                <ProductNVersion />
                <OpenCaseIssue />
                <Description />
                <CaseType />
                <SupportNSeveritySelector />
                <Fts />
                <GroupNEnhancedSLA />
            </form>
        </>)}
    </>);
}
