import React, { useState } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { Form, ButtonGroup, Button, CloseGlyph, CheckmarkGlyph, FormField, Help } from '@orchard/frontend-react-components';
import { formatMessage } from '@orchard/frontend-localization';
import { find } from 'lodash';
import { SplitEditState } from 'src/types/SplitEditState';
import PercentageInput from 'src/components/percentage-input/percentage-input';
import { clearSplitEditAction, setSplitEditFieldAction } from 'src/actions/split-edit';
import { SPLIT_LEVEL_TRACK } from 'src/constants';
import { CollaboratorSplitRateType, CollaboratorType } from 'src/__definitions__/globalTypes';
import AddCollaboratorModal from 'src/components/add-collaborator-modal/add-collaborator-modal';
import { Collaborator } from 'src/mutations/create-collaborator';
import { GroupedSplit } from 'src/types/GroupedSplit';
import CollaboratorDropdown, { Filter as CollabDropdownFilter } from './collaborator-dropdown';
import messages from './i18n';

const CLASS_NAME = 'SplitEditor';

const connector = connect(() => ({}));
type PropsFromRedux = ConnectedProps<typeof connector>;

type Props = {
    splitEdit: SplitEditState;
    readOnly: boolean;
    onSaveSplit(): void;
    saveSplitMutationLoading: boolean;
    hasDuplicateCollaboratorError?: boolean;
    subaccountId: string | null;
    vendorCurrencyCode: string;
    productSplits: GroupedSplit[];
    filterCollaboratorDropdown?: CollabDropdownFilter
} & PropsFromRedux;

const SplitEditor: React.FC<Props> = ({
    splitEdit,
    readOnly,
    dispatch,
    onSaveSplit,
    saveSplitMutationLoading,
    hasDuplicateCollaboratorError,
    subaccountId,
    vendorCurrencyCode,
    productSplits,
    filterCollaboratorDropdown
}) => {
    const [shouldValidate, setShouldValidate] = useState(false);
    const [showAddCollaboratorModal, setShowAddCollaboratorModal] = useState(false);

    const collaboratorError = hasDuplicateCollaboratorError
        ? formatMessage(messages.duplicateName)
        : !splitEdit.fields.collaborator
          && formatMessage(messages.selectACollaborator);
    const ratePercentageError = splitEdit.fields.ratePercentage === null && formatMessage(messages.enterAValue);

    const handleSetField = (...args: Parameters<typeof setSplitEditFieldAction>) => {
        setShouldValidate(false);
        dispatch(setSplitEditFieldAction(...args));
        if (splitEdit.level === 'PRODUCT') return;

        // When adding a collaborator split at the track level, if the product already contains track-level splits for
        // that collaborator, we want to make sure that the rate type used is consistent amongst all tracks.
        // Therefore we set each new track-level split's rate type to the type specified at the product-level (i.e. the first set)
        const [field, value] = args;
        if (field === 'collaborator' && value !== null) {
            const { id: collabId } = value as Collaborator;
            const productLevelSplit = find(productSplits, (split) => split.collaborator.id === collabId);
            if (productLevelSplit && productLevelSplit?.isProrated) // If this product has track level splits
                handleSetField('rateType', productLevelSplit.rateType); // Force this new track's rate type to the product's rate type
        }
    };

    const handleSave = () => {
        if (collaboratorError || ratePercentageError)
            return setShouldValidate(true);

        onSaveSplit();
    };

    const handleAddCollaborator = (collaborator: Collaborator) => {
        setShowAddCollaboratorModal(false);
        handleSetField('collaborator', collaborator);
    };

    const renderRateTypeInput = () => {
        const productLevelSplit = find(productSplits, (split) => split.collaborator.id === splitEdit.fields.collaborator?.id);

        const disabled = saveSplitMutationLoading || readOnly || (splitEdit.level === SPLIT_LEVEL_TRACK && !splitEdit.isNew)
            || (productLevelSplit && productLevelSplit?.isProrated);

        return (
            <ButtonGroup>
                <Button
                    onClick={ () => handleSetField('rateType', CollaboratorSplitRateType.NET) }
                    active={ splitEdit.fields.rateType === CollaboratorSplitRateType.NET }
                    disabled={ disabled }
                    variant="secondary"
                >
                    { formatMessage(messages.net) }
                </Button>
                <Button
                    onClick={ () => handleSetField('rateType', CollaboratorSplitRateType.GROSS) }
                    active={ splitEdit.fields.rateType === CollaboratorSplitRateType.GROSS }
                    disabled={ disabled }
                    variant="secondary"
                >
                    { formatMessage(messages.gross) }
                </Button>
            </ButtonGroup>
        );
    };

    const renderRatePercentageInput = () => (
        <PercentageInput
            value={ splitEdit.fields.ratePercentage }
            disabled={ readOnly || saveSplitMutationLoading || splitEdit.isProrated }
            onChange={ (value: number | null) => handleSetField('ratePercentage', value) }
            data-testid="percentage-rate-input"
        />
    );

    const collab = splitEdit.fields.collaborator;
    return (
        <div className={ CLASS_NAME }>
            <div className={ `${CLASS_NAME}-collaborator-input-container` }>
                <FormField
                    className={ `${CLASS_NAME}-form-group` }
                    errorMessage={ shouldValidate && collaboratorError }
                >
                    { readOnly || !splitEdit.isNew
                      || (collab?.collaboratorType === CollaboratorType.SUBACCOUNT && collab?.subaccountId?.toString() === subaccountId)
                        ? <Form.Control type="text" disabled value={ splitEdit.fields.collaborator?.name || '' } />
                        : (
                            <CollaboratorDropdown
                                value={ splitEdit.fields.collaborator }
                                onChange={ (collaborator) => handleSetField('collaborator', collaborator) }
                                disabled={ saveSplitMutationLoading }
                                onOpenAddCollaboratorModal={ () => setShowAddCollaboratorModal(true) }
                                filterOption={ filterCollaboratorDropdown }
                            />
                        ) }
                </FormField>
            </div>
            <div className={ `${CLASS_NAME}-rate-type-container` }>
                { splitEdit.level === SPLIT_LEVEL_TRACK && !splitEdit.isNew
                    ? (
                        <Help
                            id="track-rate-type"
                            message={ formatMessage(messages.thisValueCanOnlyBeEditedForAllTracksOnThisProductWarning) }
                        >
                            { renderRateTypeInput() }
                        </Help>
                    )
                    : renderRateTypeInput() }
            </div>
            <div className={ `${CLASS_NAME}-percentage-input-container` }>
                <FormField
                    className={ `${CLASS_NAME}-form-group` }
                    errorMessage={ shouldValidate && ratePercentageError }
                >
                    { splitEdit.isProrated
                        ? (
                            <Help
                                id="prorated-rate-input"
                                message={ formatMessage(messages.splitsAreNotTheSameForAllTracksOnThisProductWarning) }
                            >
                                { renderRatePercentageInput() }
                            </Help>
                        )
                        : renderRatePercentageInput() }
                </FormField>
            </div>
            { !readOnly && (
                <div className={ `${CLASS_NAME}-action-buttons-container` }>
                    <Button
                        data-testid="cancel-split-edit-button"
                        className={ `${CLASS_NAME}-action-button` }
                        disabled={ saveSplitMutationLoading }
                        onClick={ () => dispatch(clearSplitEditAction()) }
                        size="sm"
                    >
                        <CloseGlyph />
                    </Button>
                    <Button
                        data-testid="save-split-edit-button"
                        className={ `${CLASS_NAME}-action-button` }
                        disabled={ saveSplitMutationLoading }
                        onClick={ handleSave }
                        size="sm"
                        variant="primary"
                    >
                        <CheckmarkGlyph />
                    </Button>
                </div>
            ) }
            { showAddCollaboratorModal && (
                <AddCollaboratorModal
                    onAdd={ handleAddCollaborator }
                    onCancel={ () => setShowAddCollaboratorModal(false) }
                    subaccountId={ subaccountId }
                    vendorCurrencyCode={ vendorCurrencyCode }
                />
            ) }
        </div>
    );
};
export default connector(SplitEditor);
