import React, {useCallback, useEffect, useRef, useState} from 'react';

import {useDispatch, useSelector} from 'react-redux';
import {FormattedMessage, useIntl} from 'react-intl';

import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/common';
import {GlobalState} from 'mattermost-redux/types/store';

import RenderEmoji from 'components/emoji/emoji';

import {isCreateBadgeModalVisible, getEditBadgeModalData, getEmojiMap} from 'selectors';
import {closeCreateBadgeModal, closeEditBadgeModal, setRHSView} from 'actions/actions';
import {RHS_STATE_ALL} from '../../constants';
import {BadgeFormData, BadgeTypeDefinition, TypeFormData} from 'types/badges';
import Client from 'client/api';
import {getServerErrorId} from 'utils/helpers';
import CloseIcon from 'components/icons/close_icon';
import EmojiIcon from 'components/icons/emoji_icon';

import ConfirmDialog from 'components/confirm_dialog/confirm_dialog';

import EmojiPickerOverlay from './emoji_picker';
import InlineTypeForm from './inline_type_form';
import TypeSelect from './type_select';

import './badge_modal.scss';

const NEW_TYPE_VALUE = '__new__';

const emptyBadgeForm: BadgeFormData = {
    name: '',
    description: '',
    image: '',
    badgeType: '',
    multiple: false,
};

const emptyTypeForm: TypeFormData = {
    name: '',
    everyoneCanCreate: false,
    everyoneCanGrant: false,
    allowlistCanCreate: '',
    allowlistCanGrant: '',
};

const BadgeModal: React.FC = () => {
    const dispatch = useDispatch();
    const intl = useIntl();
    const createVisible = useSelector(isCreateBadgeModalVisible);
    const editData = useSelector(getEditBadgeModalData);
    const channelId = useSelector((state: GlobalState) => getCurrentChannelId(state));
    const emojiMap = useSelector((state: GlobalState) => getEmojiMap(state));
    const isOpen = createVisible || editData !== null;
    const isEditMode = editData !== null;

    const [form, setForm] = useState<BadgeFormData>(emptyBadgeForm);
    const [newTypeForm, setNewTypeForm] = useState<TypeFormData>(emptyTypeForm);
    const [types, setTypes] = useState<BadgeTypeDefinition[]>([]);
    const [showCreateType, setShowCreateType] = useState(false);
    const [canCreateType, setCanCreateType] = useState(false);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [confirmDelete, setConfirmDelete] = useState(false);
    const [confirmDeleteTypeId, setConfirmDeleteTypeId] = useState<string | null>(null);
    const [typeDropdownOpen, setTypeDropdownOpen] = useState(false);
    const [showEmojiPicker, setShowEmojiPicker] = useState(false);
    const [closing, setClosing] = useState(false);
    const modalRef = useRef<HTMLDivElement>(null);
    const dialogRef = useRef<HTMLDivElement>(null);

    const updateForm = useCallback((updates: Partial<BadgeFormData>) => {
        setForm((prev) => ({...prev, ...updates}));
    }, []);

    const updateTypeForm = useCallback((updates: Partial<TypeFormData>) => {
        setNewTypeForm((prev) => ({...prev, ...updates}));
    }, []);

    const emojiData = (window as any)?.useGetEmojiSelectorData?.();
    const {
        emojiButtonRef,
        calculateRightOffSet,
    } = emojiData || {};

    useEffect(() => {
        if (!isOpen) {
            return;
        }
        const fetchTypes = async () => {
            const client = new Client();
            const resp = await client.getTypes();
            setTypes(resp.types);
            setCanCreateType(resp.can_create_type);
            if (!isEditMode && resp.types.length > 0) {
                const defaultType = resp.types.find((t) => t.is_default);
                setForm((prev) => ({...prev, badgeType: String(defaultType ? defaultType.id : resp.types[0].id)}));
            }
        };
        fetchTypes();

        if (isEditMode && editData) {
            setForm({
                name: editData.name,
                description: editData.description,
                image: editData.image,
                badgeType: String(editData.type),
                multiple: editData.multiple,
            });
        } else {
            setForm(emptyBadgeForm);
        }
        setShowCreateType(false);
        setNewTypeForm(emptyTypeForm);
        setError(null);
        setConfirmDelete(false);
        setConfirmDeleteTypeId(null);
        setTypeDropdownOpen(false);
        setShowEmojiPicker(false);
        setLoading(false);
    }, [isOpen, isEditMode]); // eslint-disable-line react-hooks/exhaustive-deps

    const doClose = useCallback(() => {
        if (createVisible) {
            dispatch(closeCreateBadgeModal());
        }
        if (editData) {
            dispatch(closeEditBadgeModal());
        }
        setClosing(false);
    }, [dispatch, createVisible, editData]);

    const handleClose = useCallback(() => {
        setClosing(true);
        setTimeout(doClose, 150);
    }, [doClose]);

    const handleTypeSelect = useCallback((val: string) => {
        if (val === NEW_TYPE_VALUE) {
            setShowCreateType(true);
            updateForm({badgeType: ''});
        } else {
            setShowCreateType(false);
            updateForm({badgeType: val});
        }
        setTypeDropdownOpen(false);
        setConfirmDeleteTypeId(null);
    }, [updateForm]);

    const handleEmojiSelect = (emoji: any) => {
        if (emoji.short_name) {
            updateForm({image: emoji.short_name});
        } else if (emoji.name) {
            updateForm({image: emoji.name});
        }
        setShowEmojiPicker(false);
    };

    const handleDeleteType = useCallback(async (typeId: string) => {
        if (confirmDeleteTypeId !== typeId) {
            setConfirmDeleteTypeId(typeId);
            return;
        }
        try {
            const client = new Client();
            await client.deleteType(typeId);
            const removeById = (t: BadgeTypeDefinition) => String(t.id) !== typeId;
            setTypes((prev) => prev.filter(removeById));
            if (form.badgeType === typeId) {
                updateForm({badgeType: ''});
            }
        } catch (err) {
            setError(intl.formatMessage({id: 'badges.error.' + (getServerErrorId(err) || 'unknown'), defaultMessage: 'Произошла ошибка'}));
        }
        setConfirmDeleteTypeId(null);
    }, [confirmDeleteTypeId, form.badgeType, updateForm, intl]);

    const handleSubmit = useCallback(async () => {
        setLoading(true);
        setError(null);
        try {
            const client = new Client();
            let typeID = form.badgeType;
            if (showCreateType) {
                if (!newTypeForm.name.trim()) {
                    setError(intl.formatMessage({id: 'badges.modal.error_type_name_required', defaultMessage: 'Введите название типа'}));
                    setLoading(false);
                    return;
                }
                const createdType = await client.createType({
                    name: newTypeForm.name.trim(),
                    everyone_can_create: newTypeForm.everyoneCanCreate,
                    everyone_can_grant: newTypeForm.everyoneCanGrant,
                    allowlist_can_create: newTypeForm.allowlistCanCreate.trim(),
                    allowlist_can_grant: newTypeForm.allowlistCanGrant.trim(),
                    channel_id: channelId,
                });
                typeID = String(createdType.id);
            }
            if (!typeID) {
                setError(intl.formatMessage({id: 'badges.modal.error_type_required', defaultMessage: 'Выберите тип достижения'}));
                setLoading(false);
                return;
            }
            const allBadges = await client.getAllBadges();
            const trimmedName = form.name.trim().toLowerCase();
            const duplicate = allBadges.find(
                (b) => b.name.toLowerCase() === trimmedName &&
                    String(b.type) === typeID &&
                    (!isEditMode || !editData || b.id !== editData.id),
            );
            if (!emojiMap.has(form.image)) {
                setError(intl.formatMessage({id: 'badges.modal.error_not_found_emoji', defaultMessage: 'Этот эмодзи не найден'}));
                setLoading(false);
                return;
            }
            if (duplicate) {
                setError(intl.formatMessage({id: 'badges.modal.error_duplicate_name', defaultMessage: 'Достижение в данном типе с таким названием уже существует'}));
                setLoading(false);
                return;
            }
            if (isEditMode && editData) {
                await client.updateBadge({
                    id: String(editData.id),
                    name: form.name.trim(),
                    description: form.description.trim(),
                    image: form.image.trim(),
                    type: typeID,
                    multiple: form.multiple,
                });
            } else {
                await client.createBadge({
                    name: form.name.trim(),
                    description: form.description.trim(),
                    image: form.image.trim(),
                    type: typeID,
                    multiple: form.multiple,
                    channel_id: channelId,
                });
            }
            handleClose();
            dispatch(setRHSView(RHS_STATE_ALL));
        } catch (err) {
            setError(intl.formatMessage({id: 'badges.error.' + (getServerErrorId(err) || 'unknown'), defaultMessage: 'Произошла ошибка'}));
        } finally {
            setLoading(false);
        }
    }, [form, showCreateType, newTypeForm, isEditMode, editData, handleClose, intl, channelId, dispatch, emojiMap]);

    const handleDelete = useCallback(async () => {
        if (!editData) {
            return;
        }
        if (!confirmDelete) {
            setConfirmDelete(true);
            return;
        }
        setLoading(true);
        setError(null);
        try {
            const client = new Client();
            await client.deleteBadge(editData.id);
            handleClose();
            dispatch(setRHSView(RHS_STATE_ALL));
        } catch (err) {
            setError(intl.formatMessage({id: 'badges.error.' + (getServerErrorId(err) || 'unknown'), defaultMessage: 'Произошла ошибка'}));
        } finally {
            setLoading(false);
        }
    }, [editData, confirmDelete, handleClose, intl, dispatch]);

    if (!isOpen && !closing) {
        return null;
    }

    const title = isEditMode
        ? intl.formatMessage({id: 'badges.modal.edit_badge_title', defaultMessage: 'Редактировать достижение'})
        : intl.formatMessage({id: 'badges.modal.create_badge_title', defaultMessage: 'Создать достижение'});
    const submitLabel = isEditMode
        ? intl.formatMessage({id: 'badges.modal.btn_save', defaultMessage: 'Сохранить'})
        : intl.formatMessage({id: 'badges.modal.btn_create', defaultMessage: 'Создать'});

    return (
        <div
            className={'BadgeModal' + (closing ? ' BadgeModal--closing' : '')}
            ref={modalRef}
        >
            <div
                className='BadgeModal__backdrop'
                onClick={handleClose}
            />
            <div
                className='BadgeModal__dialog'
                ref={dialogRef}
            >
                <div className='BadgeModal__header'>
                    <h4>{title}</h4>
                    <button
                        className='close-btn'
                        onClick={handleClose}
                    >
                        <CloseIcon/>
                    </button>
                </div>
                <div className='BadgeModal__body'>
                    <div className='form-group'>
                        <label>
                            <FormattedMessage
                                id='badges.modal.field_name'
                                defaultMessage='Название'
                            />
                            <span className='required'>{'*'}</span>
                        </label>
                        <input
                            type='text'
                            value={form.name}
                            onChange={(e) => updateForm({name: e.target.value})}
                            maxLength={20}
                            placeholder={intl.formatMessage({id: 'badges.modal.field_name_placeholder', defaultMessage: 'Название достижения (макс. 20 символов)'})}
                        />
                    </div>
                    <div className='form-group'>
                        <label>
                            <FormattedMessage
                                id='badges.modal.field_description'
                                defaultMessage='Описание'
                            />
                        </label>
                        <textarea
                            value={form.description}
                            onChange={(e) => updateForm({description: e.target.value})}
                            maxLength={120}
                            placeholder={intl.formatMessage({id: 'badges.modal.field_description_placeholder', defaultMessage: 'Описание достижения (макс. 120 символов)'})}
                        />
                    </div>
                    <div className='form-group'>
                        <label>
                            <FormattedMessage
                                id='badges.modal.field_image'
                                defaultMessage='Эмодзи'
                            />
                            <span className='required'>{'*'}</span>
                        </label>
                        <div className='emoji-input'>
                            <button
                                type='button'
                                className='emoji-input__icon'
                                onClick={() => setShowEmojiPicker((prev) => !prev)}
                                ref={emojiButtonRef}
                            >
                                <EmojiIcon/>
                            </button>
                            {form.image && (
                                <RenderEmoji
                                    emojiName={form.image}
                                    size={20}
                                />
                            )}
                            <input
                                type='text'
                                value={form.image}
                                onChange={(e) => updateForm({image: e.target.value.trim()})}
                                placeholder={intl.formatMessage({id: 'badges.modal.field_image_placeholder', defaultMessage: 'Название эмодзи (напр. star)'})}
                            />
                        </div>
                        {showEmojiPicker && (
                            <EmojiPickerOverlay
                                target={() => emojiButtonRef?.current}
                                container={() => modalRef.current}
                                show={showEmojiPicker}
                                onHide={() => setShowEmojiPicker(false)}
                                onEmojiClick={handleEmojiSelect}
                                rightOffset={calculateRightOffSet?.(emojiButtonRef?.current)}
                                defaultHorizontalPosition='right'
                                hideCustomEmojiButton={true}
                            />
                        )}
                    </div>
                    <div className='form-group'>
                        <label>
                            <FormattedMessage
                                id='badges.modal.field_type'
                                defaultMessage='Тип'
                            />
                            <span className='required'>{'*'}</span>
                        </label>
                        <TypeSelect
                            types={types}
                            badgeType={form.badgeType}
                            showCreateType={showCreateType}
                            canCreateType={canCreateType}
                            typeDropdownOpen={typeDropdownOpen}
                            confirmDeleteTypeId={confirmDeleteTypeId}
                            onToggleDropdown={() => setTypeDropdownOpen(!typeDropdownOpen)}
                            onSelect={handleTypeSelect}
                            onDeleteType={handleDeleteType}
                            onCancelDeleteType={() => setConfirmDeleteTypeId(null)}
                        />
                        {showCreateType && (
                            <InlineTypeForm
                                form={newTypeForm}
                                onChange={updateTypeForm}
                            />
                        )}
                    </div>
                    <div className='checkbox-group'>
                        <input
                            type='checkbox'
                            id='badgeMultiple'
                            checked={form.multiple}
                            onChange={(e) => updateForm({multiple: e.target.checked})}
                        />
                        <label htmlFor='badgeMultiple'>
                            <FormattedMessage
                                id='badges.modal.field_multiple'
                                defaultMessage='Можно выдавать несколько раз'
                            />
                        </label>
                    </div>
                    {error && <div className='error-message'>{error}</div>}
                    {isEditMode && (
                        <div className='delete-section'>
                            <button
                                className='btn btn--danger'
                                onClick={handleDelete}
                                disabled={loading}
                            >
                                <FormattedMessage
                                    id='badges.modal.btn_delete'
                                    defaultMessage='Удалить достижение'
                                />
                            </button>
                            {confirmDelete && (
                                <ConfirmDialog
                                    onConfirm={handleDelete}
                                    onCancel={() => setConfirmDelete(false)}
                                >
                                    <FormattedMessage
                                        id='badges.modal.confirm_delete_badge'
                                        defaultMessage='Удалить достижение «{name}»?'
                                        values={{name: form.name || editData?.name}}
                                    />
                                </ConfirmDialog>
                            )}
                        </div>
                    )}
                </div>
                <div className='BadgeModal__footer'>
                    <button
                        className='btn btn--cancel'
                        onClick={handleClose}
                    >
                        <FormattedMessage
                            id='badges.modal.btn_cancel'
                            defaultMessage='Отмена'
                        />
                    </button>
                    <button
                        className='btn btn--primary'
                        onClick={handleSubmit}
                        disabled={loading || !form.name.trim() || !form.image.trim()}
                    >
                        {loading ? intl.formatMessage({id: 'badges.modal.btn_creating', defaultMessage: 'Сохранение...'}) : submitLabel}
                    </button>
                </div>
            </div>
        </div>
    );
};

export default BadgeModal;
