import React, {useEffect, useMemo, useRef, useState} from 'react';
import {FormattedMessage, useIntl} from 'react-intl';

import {Client4} from 'mattermost-redux/client';
import {UserProfile} from 'mattermost-redux/types/users';

import {debounce, getUserDisplayName} from 'utils/helpers';
import CloseIcon from 'components/icons/close_icon';
import SearchIcon from 'components/icons/search_icon';

import './badges_admin_setting.scss';

type SelectedUser = {
    id: string;
    username: string;
    fullName: string;
    avatarUrl: string;
}

type Props = {
    id: string;
    value: string;
    disabled: boolean;
    onChange: (id: string, value: any) => void;
    setSaveNeeded: () => void;
    config: any;
    license: any;
    setByEnv: boolean;
    registerSaveAction: (action: () => Promise<{error?: {message?: string}}>) => void;
    unRegisterSaveAction: (action: () => Promise<{error?: {message?: string}}>) => void;
}

const BadgesAdminSetting: React.FC<Props> = ({id, value, disabled, onChange, setSaveNeeded}) => {
    const intl = useIntl();
    const containerRef = useRef<HTMLDivElement>(null);
    const inputRef = useRef<HTMLInputElement>(null);

    const [searchTerm, setSearchTerm] = useState('');
    const [results, setResults] = useState<UserProfile[]>([]);
    const [dropdownOpen, setDropdownOpen] = useState(false);
    const [loading, setLoading] = useState(false);
    const [selectedUsers, setSelectedUsers] = useState<SelectedUser[]>([]);

    useEffect(() => {
        if (!value) {
            return;
        }
        const usernames = value.split(',').map((u) => u.trim()).filter(Boolean);
        Promise.all(usernames.map(async (username) => {
            try {
                const user = await Client4.getUserByUsername(username);
                return {
                    id: user.id,
                    username: user.username,
                    fullName: getUserDisplayName(user),
                    avatarUrl: Client4.getProfilePictureUrl(user.id, user.last_picture_update),
                };
            } catch {
                return {id: '', username, fullName: '', avatarUrl: ''};
            }
        })).then(setSelectedUsers);
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

    useEffect(() => {
        const handleClickOutside = (e: MouseEvent) => {
            if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
                setDropdownOpen(false);
                setSearchTerm('');
            }
        };
        document.addEventListener('mousedown', handleClickOutside);
        return () => document.removeEventListener('mousedown', handleClickOutside);
    }, []);

    const performSearch = async (term: string, excluded: Set<string>) => {
        if (!term) {
            setResults([]);
            setDropdownOpen(false);
            setLoading(false);
            return;
        }
        setLoading(true);
        try {
            const data = await Client4.autocompleteUsers(term, '', '', {limit: 20});
            setResults(data.users.filter((u: UserProfile) => !excluded.has(u.username)));
        } catch {
            setResults([]);
        } finally {
            setLoading(false);
        }
    };

    const doSearch = useMemo(() => debounce(performSearch, 400), []); // eslint-disable-line react-hooks/exhaustive-deps

    const saveValue = (users: SelectedUser[]) => {
        onChange(id, users.map((u) => u.username).join(','));
        setSaveNeeded();
    };

    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const term = e.target.value;
        setSearchTerm(term);
        if (term) {
            setDropdownOpen(true);
        }
        doSearch(term, new Set(selectedUsers.map((u) => u.username)));
    };

    const handleSelect = (user: UserProfile) => {
        const next = [...selectedUsers, {
            id: user.id,
            username: user.username,
            fullName: getUserDisplayName(user),
            avatarUrl: Client4.getProfilePictureUrl(user.id, user.last_picture_update),
        }];
        setSelectedUsers(next);
        saveValue(next);
        setSearchTerm('');
        setResults([]);
        setDropdownOpen(false);
        inputRef.current?.focus();
    };

    const handleRemove = (username: string) => {
        const next = selectedUsers.filter((u) => u.username !== username);
        setSelectedUsers(next);
        saveValue(next);
    };

    return (
        <div className='form-group'>
            <label className='control-label col-sm-4'>
                <FormattedMessage
                    id='badges.admin.label'
                    defaultMessage='Администраторы достижений:'
                />
            </label>
            <div className='col-sm-8'>
                <div
                    className='admin-user-select'
                    ref={containerRef}
                >
                    <div
                        className='admin-user-select__container'
                        onClick={() => inputRef.current?.focus()}
                    >
                        {loading ? (
                            <div className='admin-user-select__spinner'/>
                        ) : (
                            <SearchIcon/>
                        )}
                        {selectedUsers.map((user) => (
                            <span
                                key={user.username}
                                className='admin-user-select__chip'
                            >
                                {user.avatarUrl && (
                                    <img
                                        className='admin-user-select__chip-avatar'
                                        src={user.avatarUrl}
                                        alt={user.username}
                                    />
                                )}
                                <span className='admin-user-select__chip-name'>
                                    {user.fullName || user.username}
                                </span>
                                {!disabled && (
                                    <button
                                        type='button'
                                        className='admin-user-select__chip-remove'
                                        onClick={(e) => {
                                            e.stopPropagation();
                                            handleRemove(user.username);
                                        }}
                                    >
                                        <CloseIcon size={12}/>
                                    </button>
                                )}
                            </span>
                        ))}
                        <input
                            ref={inputRef}
                            className='admin-user-select__input'
                            type='text'
                            value={searchTerm}
                            disabled={disabled}
                            onChange={handleInputChange}
                            placeholder={selectedUsers.length === 0 ? intl.formatMessage({
                                id: 'badges.admin.placeholder',
                                defaultMessage: 'Начните вводить имя...',
                            }) : ''}
                        />
                    </div>
                    {dropdownOpen && (
                        <div className='admin-user-select__dropdown'>
                            {results.length === 0 && searchTerm && (
                                <div className={`admin-user-select__no-results${loading ? ' admin-user-select__no-results--loading' : ''}`}>
                                    <FormattedMessage
                                        id='badges.admin.no_results'
                                        defaultMessage='Пользователь не найден'
                                    />
                                </div>
                            )}
                            {results.map((user) => (
                                <div
                                    key={user.id}
                                    className='admin-user-select__option'
                                    onClick={() => handleSelect(user)}
                                >
                                    <img
                                        className='admin-user-select__avatar'
                                        src={Client4.getProfilePictureUrl(user.id, user.last_picture_update)}
                                        alt={user.username}
                                    />
                                    <span className='admin-user-select__option-name'>
                                        {user.username}
                                    </span>
                                    {(user.first_name || user.last_name) && (
                                        <span className='admin-user-select__option-fullname'>
                                            {'— '}{`${user.first_name} ${user.last_name}`.trim()}
                                        </span>
                                    )}
                                </div>
                            ))}
                        </div>
                    )}
                </div>
                <div className='help-text'>
                    <FormattedMessage
                        id='badges.admin.help_text'
                        defaultMessage='Эти пользователи будут считаться администраторами плагина достижений. Они могут создавать типы, а также изменять и выдавать любые значки.'
                    />
                </div>
            </div>
        </div>
    );
};

export default BadgesAdminSetting;
