import React from 'react';

import {Button} from '@gravity-ui/uikit';
import block from 'bem-cn-lite';
import {I18n} from 'i18n';
import {useDispatch} from 'react-redux';
import {CollectionItemEntities} from 'shared';
import type {SharedEntryBindingsItem} from 'shared/schema';
import {getSdk} from 'ui/libs/schematic-sdk';
import type {AppDispatch} from 'ui/store';
import {closeDialog, openDialog} from 'ui/store/actions/dialog';
import {showToast} from 'ui/store/actions/toaster';

import {DIALOG_SHARED_ENTRY_PERMISSIONS} from '../../DialogSharedEntryPermissions/DialogSharedEntryPermissions';
import {DIALOG_SHARED_ENTRY_UNBIND} from '../../DialogSharedEntryUnbind/DialogSharedEntryUnbind';
import {DIALOG_SHARED_RELATED_ENTITIES} from '../../DialogSharedRelatedEntities/DialogSharedRelatedEntities';
import {PlaceholderIllustration} from '../../PlaceholderIllustration/PlaceholderIllustration';
import {SharedBindingsList} from '../../SharedBindingsList/SharedBindingsList';
import type {AttachmentValue} from '../constants';
import {DialogClassName, ObjectsListTitles} from '../constants';
import type {SharedEntry} from '../types';
import {getIsRelationUnbind} from '../utils';

type RelationsProps = {
    isError: boolean;
    isDeleteDialog: boolean;
    entities: SharedEntryBindingsItem[];
    entitiesForDeleteAlert: SharedEntryBindingsItem[];
    entry: SharedEntry;
    currentDirection: AttachmentValue;
    onSearch: (value: string) => void;
    searchValue: string;
    isLoading: boolean;
    isSearchLoading: boolean;
    showDirectionControl: boolean;
    fetchEntityBindings: (filter?: string) => void;
};

const i18n = I18n.keyset('component.dialog-shared-entry-bindings.view');
const b = block(DialogClassName);

export const Relations = ({
    isError,
    isDeleteDialog,
    entities,
    entry,
    currentDirection,
    onSearch,
    searchValue,
    isSearchLoading,
    isLoading,
    showDirectionControl,
    fetchEntityBindings,
    entitiesForDeleteAlert,
}: RelationsProps) => {
    const dispatch: AppDispatch = useDispatch();

    const onClickRelationButton = React.useCallback(
        ({workbookId, isDelegated}: SharedEntryBindingsItem) => {
            dispatch(
                openDialog({
                    id: DIALOG_SHARED_RELATED_ENTITIES,
                    props: {
                        entry: {...entry, isDelegated},
                        workbookId: workbookId!,
                        open: true,
                        onClose: () => dispatch(closeDialog()),
                    },
                }),
            );
        },
        [entry, dispatch],
    );

    const showErrorToast = React.useCallback(
        (error) => {
            dispatch(
                showToast({
                    title: error.message,
                    error,
                }),
            );
        },
        [dispatch],
    );

    const getListItemActions = React.useCallback(
        (item: SharedEntryBindingsItem) => {
            const isRelationUnbind = getIsRelationUnbind(currentDirection, item);
            const relation = isRelationUnbind ? undefined : item;
            const parentEntry = isRelationUnbind ? item : entry;
            const sourceId = isRelationUnbind ? item.entryId : entry.entryId;
            const target = isRelationUnbind ? entry : item;

            let targetId = '';

            if ('entity' in target && target.entity === CollectionItemEntities.WORKBOOK) {
                targetId = target.workbookId!;
            } else if ('entryId' in target) {
                targetId = target.entryId;
            }

            return [
                {
                    text: i18n('list-action-unbind'),
                    action: () => {
                        dispatch(
                            openDialog({
                                id: DIALOG_SHARED_ENTRY_UNBIND,
                                props: {
                                    entry: parentEntry,
                                    onClose: () => dispatch(closeDialog()),
                                    onApply: async () => {
                                        try {
                                            await getSdk().sdk.us.deleteSharedEntryBinding({
                                                sourceId,
                                                targetId,
                                            });
                                            dispatch(closeDialog());
                                            fetchEntityBindings(isDeleteDialog ? '' : searchValue);
                                        } catch (error) {
                                            showErrorToast(error);
                                        }
                                    },
                                    open: true,
                                    relation,
                                },
                            }),
                        );
                    },
                },
                {
                    text: i18n('list-action-change-permissions'),
                    action: () =>
                        dispatch(
                            openDialog({
                                id: DIALOG_SHARED_ENTRY_PERMISSIONS,
                                props: {
                                    entry: parentEntry,
                                    onClose: () => dispatch(closeDialog()),
                                    onApply: async (delegate) => {
                                        if (delegate === item.isDelegated) {
                                            dispatch(closeDialog());
                                            return;
                                        }
                                        try {
                                            await getSdk().sdk.us.updateSharedEntryBinding({
                                                sourceId,
                                                targetId,
                                                delegation: delegate,
                                            });
                                            dispatch(closeDialog());
                                            fetchEntityBindings(searchValue);
                                        } catch (error) {
                                            showErrorToast(error);
                                        }
                                    },
                                    open: true,
                                    delegation: item.isDelegated,
                                    relation,
                                },
                            }),
                        ),
                },
            ];
        },
        [
            currentDirection,
            dispatch,
            entry,
            fetchEntityBindings,
            showErrorToast,
            searchValue,
            isDeleteDialog,
        ],
    );

    if (isError) {
        const renderRetryAction = () => (
            <Button
                className={b('button-retry')}
                size="l"
                view="action"
                onClick={() => fetchEntityBindings(searchValue)}
            >
                {i18n('retry-btn')}
            </Button>
        );

        return (
            <div className={b('error-state')}>
                <PlaceholderIllustration
                    direction="column"
                    name="error"
                    title={i18n('dialog-error')}
                    renderAction={renderRetryAction}
                />
            </div>
        );
    }

    if (isDeleteDialog && entitiesForDeleteAlert.length === 0) {
        return null;
    }

    return (
        <SharedBindingsList
            entities={entities}
            searchProps={{
                value: searchValue,
                onUpdate: onSearch,
                placeholder: i18n('list-search-placeholder'),
                disabled: isLoading || isError,
                loading: isSearchLoading,
            }}
            title={
                showDirectionControl
                    ? i18n(ObjectsListTitles[currentDirection])
                    : i18n('list-title')
            }
            getListItemActions={getListItemActions}
            isLoading={isLoading}
            onClickRelationButton={onClickRelationButton}
        />
    );
};
