import { ISeverity, IStrataMetadataValue } from '@rh-support/api';
import { IDClassNameProps, IOption } from '@rh-support/types';
import { toOption, toOptions } from '@rh-support/utils';
import { IMaintenance } from 'hydrajs/types/src/models/maintenance';
import filter from 'lodash/filter';
import find from 'lodash/find';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import map from 'lodash/map';
import merge from 'lodash/merge';
import reduce from 'lodash/reduce';
import startsWith from 'lodash/startsWith';
import React, { useContext, useState } from 'react';
import { AppMetadataStateContext } from '../../context/AppMetadataContext';
import { CreateCaseDispatchContext, CreateCaseStateContext } from '../../context/CreateCaseContext';
import { getIrtForSLAAndSeverity } from '../../reducers/CreateCaseHelpers';
import { ICreateCaseState, setCaseCreationDetails } from '../../reducers/CreateCaseReducer';
import CaseUtils from '../../utils/caseUtils';
import { Dropdown } from '../shared/input/DropdownList';

interface IProps extends IDClassNameProps { }
const defaultProps: Partial<IProps> = {
    id: '',
    className: ''
};

function Severity(props: IProps) {
    const { createCaseState: {
        entitlement, severity, product, version
    } } = useContext(CreateCaseStateContext);
    const { appMetadataState: {
        allCaseEntitlements,
        allCaseSeverities,
        pcmConfig
    } } = useContext(AppMetadataStateContext);
    const createCaseDispatch = useContext(CreateCaseDispatchContext);

    const [isSeverityInValid, setIsSeverityInValid] = useState(false);

    const onCaseDetailsChange = (caseDetails: Partial<ICreateCaseState>) => {
        setCaseCreationDetails(createCaseDispatch, caseDetails);
    };

    const onSeverityChange = (option: IOption<IStrataMetadataValue>) => {
        const casePayload: Partial<ICreateCaseState> = { severity: option.value.name };
        casePayload.fts = CaseUtils.showFts(get(entitlement, 'sla', ''), option.value.name);
        validateSeverity(option);
        onCaseDetailsChange(casePayload);
    };
    const validateSeverity = (selectedItem: IOption<IStrataMetadataValue>): void => {
        const isInvalid = isEmpty(selectedItem) || isEmpty(selectedItem.label);
        setIsSeverityInValid(isInvalid);
    };

    const getField = (config: IMaintenance[], fieldName: string, fieldType: string) => {
        const values = reduce(config, (result, v) => {
            return startsWith(v.fieldName, fieldName) ? [...result, v.fieldValue] : result;
        }, []);
        if (values.length === 0) { return null; }
        if (!fieldType) { return values; }
        try {
            const parsed = map(values, JSON.parse);
            if (fieldType === 'JSON') { return parsed; }
            // if (fieldType === 'JSON-ARRAY') { return reduce(parsed, concat); }
            if (fieldType === 'JSON-HASHMAP') { return reduce(parsed, merge); }
        } catch (error) {
            // tslint:disable-next-line:no-console
            console.error(error);
        }
    };

    const allowedSeveritiesForProductAndVersion = (config: IMaintenance[], selectedProduct: string, selectedVersion: string): string[] => {
        const parsedConfig = getField(config, 'product_severity', 'JSON-HASHMAP');
        const allSeverities = map(allCaseSeverities.data, (s) => (s.name));
        const productConfig = get(parsedConfig, selectedProduct);
        if (!productConfig) { return allSeverities; }
        const versionConfig = find(productConfig.versionSeverities, (v) => (v.version === selectedVersion));
        return get(versionConfig, 'severities') || productConfig.severities || allSeverities;
    };

    const isValidSeverity = (config: IMaintenance[], severityOption: string, selectedProduct: string, selectedVersion: string): boolean => {
        const allowedSeverities = allowedSeveritiesForProductAndVersion(config, selectedProduct, selectedVersion);
        return Boolean(find(allowedSeverities, (s) => (s === severityOption)));
    };

    const limittedSeverities: ISeverity[] = map(allCaseSeverities.data, (s) => {
        const slaLocal = get(entitlement, 'sla', '');
        const sevItemIrt = getIrtForSLAAndSeverity(slaLocal, s.name);
        const sevItem = {
        ...s,
        disabled: !isValidSeverity(pcmConfig.data, s.name, product, version),
        label: `${s.name}${!isEmpty(sevItemIrt) ? ' - ' + sevItemIrt : ''}`
        };
        return sevItem;
    });

    const filteredSeverities = filter(limittedSeverities, (s) => !s.disabled);
    const selectedSeverityFromDropdown = (isEmpty(severity) && !isEmpty(filteredSeverities)) ? filteredSeverities[0].name : severity;
    if (selectedSeverityFromDropdown !== severity) { onCaseDetailsChange({ severity: selectedSeverityFromDropdown }); }
    const irt = getIrtForSLAAndSeverity(get(entitlement, 'sla', ''), severity);
    const selectedSeverity: ISeverity = { name: severity, disabled: false, label: `${severity}${!isEmpty(irt) ? ' - ' + irt : ''}` };
    const waitForSupportLevel = allCaseEntitlements.isFetching || (isEmpty(get(entitlement, 'sla', '')) && !isEmpty(allCaseEntitlements.data));

    return (<div className={`form-group ${props.className}`} id={`${props.id}`}>
        <label htmlFor="open-case-severity">Severity {!waitForSupportLevel && <span className="form-required">&#42;</span>}</label>
        <Dropdown<ISeverity>
            id="open-case-severity"
            name="open-case-severity"
            placeholder="Select"
            title={`Select Severity`}
            list={allCaseSeverities.data ? toOptions<ISeverity>(filteredSeverities, 'label', 'disabled') : []}
            selectedItem={toOption<ISeverity>(selectedSeverity, 'label', 'disabled')}
            disabled={allCaseSeverities.isError || waitForSupportLevel}
            isLoadingList={allCaseSeverities.isFetching}
            isInValid={allCaseSeverities.isError || isSeverityInValid}
            onChange={onSeverityChange}
            onOuterClick={validateSeverity}
        />
    </div>);
}
Severity.defaultProps = defaultProps;
export default Severity;
