import { memo, useCallback, useMemo, useState } from 'react'
import { Rule } from 'antd/lib/form'
import { Form, Input, Modal, FormProps } from 'antd'

import { AuthService, UserDto } from '@api'
import { getUserId, getUserLogin } from '@utils/storage'
import { passwordRules, createPasswordRules } from '@utils/validationRules'

import LoaderPortal from './LoaderPortal'
import { invokeWebApiWrapperAsync } from './factory'
import { UserView } from './views'

const formLayout: FormProps = { labelCol: { span: 11 }, wrapperCol: { span: 16 } }

export type ChangePasswordProps = {
    user?: UserDto
    visible?: boolean
    onCancel?: () => void
    onOk?: () => void
}

const fieldRules = [...passwordRules, ...createPasswordRules]

const confirmPasswordRules: Rule[] = [({ getFieldValue }) => ({ validator(_, value: string) {
    if (value !== getFieldValue('new-password'))
        return Promise.reject('Пароли не совпадают!')
    return Promise.resolve()
}})]

export const ChangePassword = memo<ChangePasswordProps>(({ user, visible, onCancel, onOk }) => {
    const [showLoader, setShowLoader] = useState<boolean>(false)
    const [isDisabled, setIsDisabled] = useState(true)

    const userData = useMemo(() => user ?? { id: getUserId(), login: getUserLogin() } as UserDto, [user])

    const [form] = Form.useForm()

    const onFormChange = async () => await form.validateFields()
        .then(() => setIsDisabled(false))
        .catch(() => setIsDisabled(true))

    const onModalCancel = () => {
        form.resetFields()
        onCancel?.()
    }

    const onFormFinish = useCallback((values: any) => invokeWebApiWrapperAsync(
        async() => {
            await AuthService.changePassword(userData.id ?? -1, `${values['new-password']}`)
            onOk?.()
        },
        setShowLoader,
        `Не удалось сменить пароль пользователя ${userData.login}`,
        'Смена пароля пользователя'
    ), [userData, onOk])

    return (
        <Modal
            centered
            title={(
                <>
                    Сменить пароль
                    {user && <>&nbsp;(<UserView user={user} />)</>}
                </>
            )}
            visible={visible}
            onCancel={onModalCancel}
            onOk={() => form.submit()}
            okText={'Сохранить'}
            okButtonProps={{
                disabled: isDisabled
            }}
            // getContainer={false} // Исправляет ошибку с формой, но портит вид модалки при вызове из user menu
            // TODO: разобраться
        >
            <LoaderPortal show={showLoader}>
                <Form
                    {...formLayout}
                    form={form}
                    name={'change-password'}
                    onFinish={onFormFinish}
                    onChange={onFormChange}
                >
                    <Form.Item required rules={fieldRules} name={'new-password'} label={'Новый пароль'}>
                        <Input.Password />
                    </Form.Item>
                    <Form.Item required name={'confirm-password'} rules={confirmPasswordRules} label={'Подтверждение пароля'}>
                        <Input.Password />
                    </Form.Item>
                </Form>
            </LoaderPortal>
        </Modal>
    )
})
